> ## 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.

# Guía de uso de la caché de contexto de Claude

> Almacena en caché los prefijos de prompt reutilizados mediante la API Claude Messages o la API Chat Completions compatible con OpenAI para reducir el coste en tokens del procesamiento repetido de contenido largo.

La caché de contexto de Claude (Context Cache) es adecuada para reutilizar prefijos largos, como prompts del sistema, documentos, bases de código o historiales de conversación. Después de añadir `cache_control` a un prefijo estable, la primera solicitud crea una caché y las solicitudes posteriores pueden leerla mientras no haya caducado.

Antes de empezar, configura tu clave de API:

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

<Note>Los ejemplos de esta guía usan `claude-sonnet-5`. Para saber si otros modelos admiten la caché de contexto, consulta la descripción de los modelos en la plataforma.</Note>

## Casos de uso

Cuando varias solicitudes incluyen repetidamente el mismo bloque grande de contenido, puedes almacenar en caché un prefijo estable, por ejemplo:

* Un prompt del sistema largo
* Una base de conocimientos fija o documentación de producto
* Un historial de conversación de varios turnos que permanece sin cambios
* Bases de código, definiciones de herramientas e instrucciones que se reutilizan

La caché de contexto es adecuada para solicitudes en las que el contenido inicial permanece igual y solo cambia la pregunta final.

## API Claude Messages

### Caché de 5 minutos

Añade `cache_control` al bloque de contenido que quieras almacenar en caché:

```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": "Aquí se incluye el prefijo largo que se reutilizará…",
        "cache_control": {
          "type": "ephemeral"
        }
      }
    ],
    "messages": [
      {
        "role": "user",
        "content": "Responde a la pregunta a partir del contenido anterior."
      }
    ]
  }'
```

<Warning>`system` debe ser un array de bloques de contenido. No se puede añadir `cache_control` cuando `system` es una cadena.</Warning>

Si omites `ttl`, el periodo de validez predeterminado de la caché es de 5 minutos.

### Caché de 1 hora

Para usar una caché de 1 hora, añade también el encabezado de solicitud `anthropic-beta` y establece `ttl` en `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": "Aquí se incluye el prefijo largo que se reutilizará…",
        "cache_control": {
          "type": "ephemeral",
          "ttl": "1h"
        }
      }
    ],
    "messages": [
      {
        "role": "user",
        "content": "Responde a la pregunta a partir del contenido anterior."
      }
    ]
  }'
```

TTL admitidos:

| TTL  | Significado                                                                               |
| ---- | ----------------------------------------------------------------------------------------- |
| `5m` | Caché durante 5 minutos; se usa este valor si omites `ttl`                                |
| `1h` | Caché durante 1 hora; también debes añadir el encabezado `anthropic-beta` correspondiente |

### Campos de uso de la respuesta

La API Claude Messages devuelve por separado los tokens de entrada normal, escritura en caché y lectura de caché dentro de `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
  }
}
```

El total de tokens de entrada se calcula de la siguiente forma:

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

Estos tres valores no se solapan. La primera solicitud suele mostrar `cache_creation_input_tokens > 0`; al volver a enviar el mismo prefijo estable, debería aparecer `cache_read_input_tokens > 0`.

## API compatible con OpenAI

### Ejemplo de solicitud

Al usar la caché mediante `/v1/chat/completions`, la sintaxis de `cache_control` es similar a la de la 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": "Aquí se incluye el prefijo largo que se reutilizará…",
            "cache_control": {
              "type": "ephemeral"
            }
          }
        ]
      },
      {
        "role": "user",
        "content": "Responde a la pregunta a partir del contenido anterior."
      }
    ]
  }'
```

### Caché de 1 hora

El formato compatible con OpenAI también admite una caché de 1 hora. Solo tienes que añadir el encabezado de solicitud `anthropic-beta` y establecer `ttl: "1h"` dentro de `cache_control`:

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

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

### `content` debe ser un array

En el formato compatible con OpenAI, `cache_control` debe estar dentro de un bloque de contenido concreto. No se puede añadir a un mensaje cuyo contenido sea una cadena.

```json theme={null}
{
  "role": "system",
  "content": "Aquí se incluye el prefijo largo…",
  "cache_control": {
    "type": "ephemeral"
  }
}
```

La sintaxis anterior no activa la caché, aunque la solicitud tampoco genera ningún error. Esta es la sintaxis correcta:

```json theme={null}
{
  "role": "system",
  "content": [
    {
      "type": "text",
      "text": "Aquí se incluye el prefijo largo…",
      "cache_control": {
        "type": "ephemeral"
      }
    }
  ]
}
```

<Warning>Si `content` es una cadena, el marcador de caché se ignora y el contenido sigue procesándose como entrada normal. Comprueba los campos de uso de la caché en la respuesta para confirmar si se ha leído la caché.</Warning>

### Almacenar en caché bloques de contenido `user` o `assistant`

También puedes colocar `cache_control` en el bloque de contenido de un mensaje `user` o `assistant` para almacenar en caché un documento largo o un prefijo de conversación de varios turnos:

```json theme={null}
{
  "role": "user",
  "content": [
    {
      "type": "text",
      "text": "Aquí se incluye el documento largo que se reutilizará…",
      "cache_control": {
        "type": "ephemeral"
      }
    },
    {
      "type": "text",
      "text": "Resume los tres puntos principales del documento anterior."
    }
  ]
}
```

Separa el contenido estable y la pregunta actual en distintos bloques de contenido y añade `cache_control` únicamente al bloque de contenido estable.

### Campos de uso de la respuesta

El formato compatible con OpenAI utiliza campos diferentes para informar del uso de la caché:

```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
  }
}
```

Correspondencia de campos:

| Significado                         | API Claude Messages                        | API compatible con OpenAI                                                                       |
| ----------------------------------- | ------------------------------------------ | ----------------------------------------------------------------------------------------------- |
| Entrada total                       | Suma de los tres campos de entrada         | `prompt_tokens`                                                                                 |
| Lectura de caché                    | `cache_read_input_tokens`                  | `prompt_tokens_details.cached_tokens`                                                           |
| Campo general de escritura en caché | `cache_creation_input_tokens`              | `prompt_tokens_details.cache_write_tokens` (solo tiene valor cuando no hay un desglose por TTL) |
| Escritura en la caché de 5 minutos  | `cache_creation.ephemeral_5m_input_tokens` | `claude_cache_creation_5_m_tokens`                                                              |
| Escritura en la caché de 1 hora     | `cache_creation.ephemeral_1h_input_tokens` | `claude_cache_creation_1_h_tokens`                                                              |
| Salida                              | `output_tokens`                            | `completion_tokens`                                                                             |

<Note>Si `prompt_tokens_details.cache_write_tokens` es `0`, también debes comprobar `claude_cache_creation_5_m_tokens` y `claude_cache_creation_1_h_tokens`. Cuando existen campos de desglose por TTL, la cantidad escrita en la caché se devuelve mediante el campo correspondiente.</Note>

<Note>En `claude_cache_creation_5_m_tokens` y `claude_cache_creation_1_h_tokens`, hay guiones bajos entre el número y la unidad. Utiliza exactamente los nombres de campo devueltos en la respuesta.</Note>

<Warning>La API compatible con OpenAI puede devolver una respuesta de streaming SSE aunque no envíes explícitamente `stream: true`. El cliente debe poder analizar `chat.completion.chunk`. El uso se encuentra en el último bloque de datos que contiene `usage`.</Warning>

## Condiciones para leer la caché

### El prefijo alcanza la longitud mínima

Por lo general, el prefijo de caché del modelo usado en los ejemplos debe tener al menos unos 1024 tokens. Si el prefijo es demasiado corto, el marcador de caché puede ignorarse sin generar ningún error.

### El prefijo permanece idéntico byte a byte

El texto, los espacios, los saltos de línea y el orden de los bloques de contenido del prefijo de caché deben permanecer sin cambios. No añadas al prefijo estable contenido dinámico, como marcas de tiempo, identificadores aleatorios o contadores de solicitudes.

### La solicitud no ha provocado un rechazo del modelo

Si la solicitud provoca un rechazo del modelo, la respuesta puede seguir informando de tokens de creación de caché, pero esa caché no se leerá en la siguiente solicitud. Al investigar por qué no se ha leído la caché, comprueba también si `stop_reason` es `refusal`.

### La caché sigue vigente

El periodo de validez de la caché es de 5 minutos o 1 hora y se calcula desde el último acceso. Una lectura de la caché renueva su periodo de validez.

## Uso para facturación

El uso relacionado con la caché se divide en tres categorías:

| Uso                | Cuándo se genera                                   |
| ------------------ | -------------------------------------------------- |
| Escritura en caché | Al crear la caché por primera vez                  |
| Lectura de caché   | Cuando una solicitud posterior encuentra la caché  |
| Entrada normal     | Para la entrada situada fuera del prefijo de caché |

Estas tres categorías de uso no se solapan. La escritura en caché suele costar más que la entrada normal, mientras que la lectura de caché suele costar menos. Por tanto, la caché de contexto es más adecuada para prefijos estables que se reutilicen dentro del TTL.

## Ejemplo mínimo reproducible

El siguiente script genera primero un prefijo estable suficientemente largo y después envía dos veces la misma solicitud. La segunda respuesta debería mostrar `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 "Solicitud ${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
```

Resultado esperado:

```text theme={null}
Solicitud 1: cache_creation_input_tokens > 0, cache_read_input_tokens = 0
Solicitud 2: cache_creation_input_tokens = 0, cache_read_input_tokens > 0
```

## Lista de comprobación para solucionar problemas

Si no se lee la caché, comprueba los siguientes puntos en orden:

* ¿`stop_reason` es `refusal`?
* ¿El prefijo de caché alcanza el número mínimo de tokens exigido por el modelo?
* ¿Los prefijos estables de ambas solicitudes son idénticos byte a byte?
* En el formato compatible con OpenAI, ¿`content` es un array?
* ¿`cache_control` está dentro de un bloque de contenido concreto?
* Para la caché de 1 hora, ¿se han configurado tanto `ttl: "1h"` como el encabezado `anthropic-beta` correspondiente?
* ¿La caché ha superado su TTL?
* ¿Estás leyendo los campos de uso de caché correspondientes a la API actual?
