> ## Documentation Index
> Fetch the complete documentation index at: https://docs.apimart.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Guide de mise en cache du contexte Claude

> Mettez en cache les préfixes de prompt réutilisés avec l’API Claude Messages ou l’API Chat Completions compatible OpenAI afin de réduire le coût en tokens du traitement répété de longs contenus.

Le cache de contexte Claude (Context Cache) convient à la réutilisation de longs préfixes, tels que des prompts système, des documents, des bases de code ou des historiques de conversation. Après l’ajout de `cache_control` à un préfixe stable, la première requête crée un cache et les requêtes suivantes peuvent lire ce cache tant qu’il n’a pas expiré.

Avant de commencer, définissez votre clé API :

```bash theme={null}
export API_KEY="VOTRE_CLE_API"
```

<Note>Les exemples de ce guide utilisent `claude-sonnet-5`. Consultez la description des modèles sur la plateforme pour savoir si d’autres modèles prennent en charge le cache de contexte.</Note>

## Cas d’utilisation

Lorsque plusieurs requêtes contiennent de façon répétée le même contenu volumineux, vous pouvez mettre en cache un préfixe stable. Par exemple :

* Un long prompt système
* Une base de connaissances ou une documentation produit fixe
* Un historique de conversation à plusieurs tours qui reste inchangé
* Des bases de code, des définitions de tools et des instructions réutilisées

Le cache de contexte convient aux requêtes dont le contenu initial reste inchangé tandis que la question finale varie.

## API Claude Messages

### Cache de 5 minutes

Ajoutez `cache_control` au bloc de contenu à mettre en cache :

```bash theme={null}
curl "https://api.apimart.ai/v1/messages" \
  -H "x-api-key: $API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-sonnet-5",
    "max_tokens": 1024,
    "system": [
      {
        "type": "text",
        "text": "Insérez ici le long préfixe à réutiliser…",
        "cache_control": {
          "type": "ephemeral"
        }
      }
    ],
    "messages": [
      {
        "role": "user",
        "content": "Répondez à la question à partir du contenu ci-dessus."
      }
    ]
  }'
```

<Warning>`system` doit être un tableau de blocs de contenu. Il est impossible d’ajouter `cache_control` lorsque `system` est une chaîne.</Warning>

Si `ttl` est omis, la durée de validité du cache est de 5 minutes par défaut.

### Cache de 1 heure

Pour utiliser un cache de 1 heure, ajoutez également l’en-tête de requête `anthropic-beta` et définissez `ttl` sur `1h` :

```bash theme={null}
curl "https://api.apimart.ai/v1/messages" \
  -H "x-api-key: $API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "anthropic-beta: extended-cache-ttl-2025-04-11" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-sonnet-5",
    "max_tokens": 1024,
    "system": [
      {
        "type": "text",
        "text": "Insérez ici le long préfixe à réutiliser…",
        "cache_control": {
          "type": "ephemeral",
          "ttl": "1h"
        }
      }
    ],
    "messages": [
      {
        "role": "user",
        "content": "Répondez à la question à partir du contenu ci-dessus."
      }
    ]
  }'
```

Valeurs TTL prises en charge :

| TTL  | Signification                                                                                       |
| ---- | --------------------------------------------------------------------------------------------------- |
| `5m` | Mise en cache pendant 5 minutes ; cette valeur est utilisée si `ttl` est omis                       |
| `1h` | Mise en cache pendant 1 heure ; l’en-tête `anthropic-beta` correspondant doit également être ajouté |

### Champs d’utilisation dans la réponse

L’API Claude Messages renvoie séparément les tokens d’entrée ordinaires, d’écriture dans le cache et de lecture du cache dans `usage` :

```json theme={null}
{
  "usage": {
    "input_tokens": 23,
    "cache_creation_input_tokens": 2619,
    "cache_read_input_tokens": 0,
    "cache_creation": {
      "ephemeral_5m_input_tokens": 2619,
      "ephemeral_1h_input_tokens": 0
    },
    "output_tokens": 24
  }
}
```

Le nombre total de tokens d’entrée est calculé comme suit :

```text theme={null}
input_tokens
+ cache_creation_input_tokens
+ cache_read_input_tokens
```

Ces trois valeurs ne se chevauchent pas. La première requête affiche généralement `cache_creation_input_tokens > 0` ; lorsque vous renvoyez le même préfixe stable, `cache_read_input_tokens > 0` doit apparaître.

## API compatible OpenAI

### Exemple de requête

Lorsque vous utilisez le cache avec `/v1/chat/completions`, la syntaxe de `cache_control` est similaire à celle de l’API Claude Messages :

```bash theme={null}
curl "https://api.apimart.ai/v1/chat/completions" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-sonnet-5",
    "max_tokens": 1024,
    "messages": [
      {
        "role": "system",
        "content": [
          {
            "type": "text",
            "text": "Insérez ici le long préfixe à réutiliser…",
            "cache_control": {
              "type": "ephemeral"
            }
          }
        ]
      },
      {
        "role": "user",
        "content": "Répondez à la question à partir du contenu ci-dessus."
      }
    ]
  }'
```

### Cache de 1 heure

Le format compatible OpenAI prend également en charge le cache de 1 heure. Il suffit d’ajouter l’en-tête de requête `anthropic-beta` et de définir `ttl: "1h"` dans `cache_control` :

```bash theme={null}
-H "anthropic-beta: extended-cache-ttl-2025-04-11"
```

```json theme={null}
"cache_control": {
  "type": "ephemeral",
  "ttl": "1h"
}
```

### `content` doit être un tableau

Dans le format compatible OpenAI, `cache_control` doit se trouver dans un bloc de contenu précis. Il ne peut pas être attaché à un message dont le contenu est une chaîne.

```json theme={null}
{
  "role": "system",
  "content": "Insérez ici le long préfixe…",
  "cache_control": {
    "type": "ephemeral"
  }
}
```

La syntaxe ci-dessus n’active pas le cache, mais la requête ne renvoie aucune erreur. Voici la syntaxe correcte :

```json theme={null}
{
  "role": "system",
  "content": [
    {
      "type": "text",
      "text": "Insérez ici le long préfixe…",
      "cache_control": {
        "type": "ephemeral"
      }
    }
  ]
}
```

<Warning>Si `content` est une chaîne, le marqueur de cache est ignoré et le contenu est toujours traité comme une entrée ordinaire. Vérifiez les champs d’utilisation du cache dans la réponse pour confirmer que le cache a été lu.</Warning>

### Mise en cache des blocs de contenu `user` ou `assistant`

Vous pouvez également placer `cache_control` dans le bloc de contenu d’un message `user` ou `assistant` afin de mettre en cache un long document ou un préfixe de conversation à plusieurs tours :

```json theme={null}
{
  "role": "user",
  "content": [
    {
      "type": "text",
      "text": "Insérez ici le long document à réutiliser…",
      "cache_control": {
        "type": "ephemeral"
      }
    },
    {
      "type": "text",
      "text": "Résumez les trois idées principales du document ci-dessus."
    }
  ]
}
```

Séparez le contenu stable et la question actuelle dans différents blocs de contenu, puis ajoutez `cache_control` uniquement au bloc de contenu stable.

### Champs d’utilisation dans la réponse

Le format compatible OpenAI utilise des champs différents pour indiquer l’utilisation du cache :

```json theme={null}
{
  "usage": {
    "prompt_tokens": 1942,
    "completion_tokens": 22,
    "prompt_tokens_details": {
      "cached_tokens": 1921,
      "cache_write_tokens": 0
    },
    "claude_cache_creation_5_m_tokens": 0,
    "claude_cache_creation_1_h_tokens": 0
  }
}
```

Correspondance des champs :

| Signification                            | API Claude Messages                        | API compatible OpenAI                                                                            |
| ---------------------------------------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------ |
| Entrée totale                            | Somme des trois champs d’entrée            | `prompt_tokens`                                                                                  |
| Lecture du cache                         | `cache_read_input_tokens`                  | `prompt_tokens_details.cached_tokens`                                                            |
| Champ générique d’écriture dans le cache | `cache_creation_input_tokens`              | `prompt_tokens_details.cache_write_tokens` (renseigné uniquement en l’absence de détail par TTL) |
| Écriture dans le cache de 5 minutes      | `cache_creation.ephemeral_5m_input_tokens` | `claude_cache_creation_5_m_tokens`                                                               |
| Écriture dans le cache de 1 heure        | `cache_creation.ephemeral_1h_input_tokens` | `claude_cache_creation_1_h_tokens`                                                               |
| Sortie                                   | `output_tokens`                            | `completion_tokens`                                                                              |

<Note>Si `prompt_tokens_details.cache_write_tokens` vaut `0`, vérifiez tout de même `claude_cache_creation_5_m_tokens` et `claude_cache_creation_1_h_tokens`. Lorsque les champs détaillés par TTL sont présents, le volume écrit dans le cache est renvoyé dans le champ correspondant.</Note>

<Note>Dans `claude_cache_creation_5_m_tokens` et `claude_cache_creation_1_h_tokens`, des traits de soulignement séparent le chiffre de l’unité. Utilisez exactement les noms de champs renvoyés dans la réponse.</Note>

<Warning>L’API compatible OpenAI peut renvoyer une réponse SSE en streaming même si vous ne transmettez pas explicitement `stream: true`. Le client doit pouvoir analyser `chat.completion.chunk`. L’utilisation se trouve dans le dernier bloc de données contenant `usage`.</Warning>

## Conditions requises pour lire le cache

### Le préfixe atteint la longueur minimale

Pour le modèle utilisé dans les exemples, le préfixe mis en cache doit généralement contenir au moins environ 1024 tokens. Si le préfixe est trop court, le marqueur de cache peut être ignoré sans qu’aucune erreur ne soit renvoyée.

### Le préfixe reste identique octet par octet

Le texte, les espaces, les sauts de ligne et l’ordre des blocs de contenu du préfixe mis en cache doivent rester identiques. N’ajoutez pas de contenu dynamique, comme un horodatage, un ID aléatoire ou un compteur de requêtes, au préfixe stable.

### La requête n’a pas déclenché un refus du modèle

Si la requête déclenche un refus du modèle, la réponse peut tout de même indiquer des tokens de création du cache, mais ce cache ne sera pas lu lors de la requête suivante. Lors du diagnostic d’un échec de lecture du cache, vérifiez également si `stop_reason` vaut `refusal`.

### Le cache n’a pas expiré

La durée de validité du cache est de 5 minutes ou 1 heure et est calculée à partir du dernier accès. Une lecture du cache renouvelle sa durée de validité.

## Utilisation facturée

L’utilisation liée au cache se répartit en trois catégories :

| Utilisation            | Quand est-elle générée ?                              |
| ---------------------- | ----------------------------------------------------- |
| Écriture dans le cache | Lors de la création initiale du cache                 |
| Lecture du cache       | Lorsqu’une requête suivante trouve le cache           |
| Entrée ordinaire       | Pour les entrées situées hors du préfixe mis en cache |

Ces trois catégories ne se chevauchent pas. L’écriture dans le cache coûte généralement plus cher qu’une entrée ordinaire, tandis que la lecture du cache coûte généralement moins cher. Le cache de contexte convient donc davantage aux préfixes stables réutilisés pendant la durée TTL.

## Exemple reproductible minimal

Le script suivant génère d’abord un préfixe stable suffisamment long, puis envoie deux fois la même requête. La seconde réponse doit contenir `cache_read_input_tokens > 0`.

```bash theme={null}
python3 - <<'PY' > /tmp/claude-cache-request.json
import json

paragraph = (
    "Prompt caching stores a prefix of the request so that later requests "
    "can reuse the same byte-identical prefix without processing it again. "
)

system_text = (
    "You are a documentation assistant. Reference material follows.\n\n"
    + paragraph * 40
)

print(json.dumps({
    "model": "claude-sonnet-5",
    "max_tokens": 32,
    "system": [{
        "type": "text",
        "text": system_text,
        "cache_control": {"type": "ephemeral"}
    }],
    "messages": [{
        "role": "user",
        "content": "In one sentence, what must remain unchanged?"
    }]
}))
PY

for request_number in 1 2; do
  echo "Requête ${request_number}"
  curl -s "https://api.apimart.ai/v1/messages" \
    -H "x-api-key: $API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "Content-Type: application/json" \
    --data @/tmp/claude-cache-request.json \
  | python3 -c "import json, sys; print(json.load(sys.stdin)['usage'])"
done
```

Résultat attendu :

```text theme={null}
Requête 1 : cache_creation_input_tokens > 0, cache_read_input_tokens = 0
Requête 2 : cache_creation_input_tokens = 0, cache_read_input_tokens > 0
```

## Liste de vérification pour le dépannage

Si le cache n’est pas lu, vérifiez les points suivants dans l’ordre :

* `stop_reason` vaut-il `refusal` ?
* Le préfixe mis en cache atteint-il le nombre minimal de tokens requis par le modèle ?
* Les préfixes stables des deux requêtes sont-ils identiques octet par octet ?
* Dans le format compatible OpenAI, `content` est-il un tableau ?
* `cache_control` se trouve-t-il dans un bloc de contenu précis ?
* Pour le cache de 1 heure, `ttl: "1h"` et l’en-tête `anthropic-beta` correspondant sont-ils tous les deux définis ?
* Le cache a-t-il dépassé sa durée TTL ?
* Lisez-vous les champs d’utilisation du cache correspondant à l’API utilisée ?
