Prompt caching

Reuse a stable prompt prefix across requests to cut input cost and latency

Prompt caching lets a provider reuse the tokens it already processed for a repeated prompt prefix instead of reading them again. Use it when many requests share a large, stable head, such as a long system prompt, a tool schema, a document you ask several questions about, or the growing history of a chat or coding-agent session. The cached prefix is billed at a lower rate and skips re-processing, so repeated requests are cheaper and start returning tokens sooner.

Gateway treats caching as a vendor-route capability. The same canonical model can cache differently depending on the vendor that serves the request, so the caching behavior follows the route, not the model name alone.

Caching never fails a request. If a route cannot honor a cache marker, Gateway removes the marker and sends the request normally rather than returning an error.

How prompt caching works

Every route falls into one of three caching families. The family decides what Gateway does with your request.

FamilyWhat you sendWhat Gateway does
explicitcache_control markers on the content you want cachedForwards the markers to the provider
automaticNothing, or an optional session_idStrips any markers, the provider caches on its own
noneNothingStrips any markers, no caching happens

The split exists because providers disagree on how caching is triggered. Anthropic models need you to mark the cacheable prefix. Most other providers cache repeated prefixes automatically and reject the marker if you send it, so Gateway strips it for you rather than letting the request break.

Two things follow from this. Send cache_control markers only on explicit routes. On every other route, rely on automatic caching and skip the markers.

Which providers use which family

Provider and routeFamily
Anthropic (Claude)explicit
Claude on Bedrockexplicit
Amazon Nova on Bedrockexplicit
OpenAIautomatic
Google Geminiautomatic
DeepSeekautomatic
Qwenautomatic
Mistralautomatic
Z.AIautomatic
xAI (Grok)automatic

Routes not listed here are none today. A none route silently drops cache markers and bills every input token at the standard rate. Automatic caching is best-effort by the provider, so a given prompt may not produce a cache hit even on an automatic route, usually because the shared prefix is shorter than the provider’s minimum cacheable length.

Inputs: explicit caching with cache markers

On explicit routes, add a cache_control marker to the last content block of the prefix you want to reuse. Everything up to and including that block becomes the cached prefix. Put your stable content first (system instructions, tool definitions, a shared document), then the marker, then the part that changes per request.

$curl https://api-gateway.merge.dev/v1/responses \
> -H "Authorization: Bearer YOUR_API_KEY" \
> -H "Content-Type: application/json" \
> -d '{
> "model": "anthropic/claude-haiku-4-5-20251001",
> "vendor": "anthropic",
> "max_tokens": 1024,
> "input": [
> {
> "type": "message",
> "role": "user",
> "content": [
> {
> "type": "text",
> "text": "Here is the full onboarding handbook for Acme Corp: ...long stable document...",
> "cache_control": { "type": "ephemeral" }
> },
> {
> "type": "text",
> "text": "What is the PTO policy for a new hire in their first 90 days?"
> }
> ]
> }
> ]
> }'

The first request with a new prefix writes it to the cache and costs a small write premium. Every later request that repeats the same prefix reads it back at the discounted cache-read rate. The cache entry is short-lived, so caching pays off when repeat requests arrive close together, as they do in an agent loop or a multi-turn conversation.

You can place the marker on a text, image, document, or audio block. The block you mark, and everything before it, forms the cached prefix.

Inputs: automatic caching

On automatic routes, send the request as usual. The provider detects the repeated prefix and caches it without a marker. Keep the stable content at the front of the prompt so the reused prefix is as long as possible.

To help the provider group related requests onto the same cache, pass a session_id. Gateway namespaces it per organization and derives the provider cache key, so two of your requests with the same session_id land on the same cached prefix, and a different tenant’s identical value never collides with yours.

$curl https://api-gateway.merge.dev/v1/responses \
> -H "Authorization: Bearer YOUR_API_KEY" \
> -H "Content-Type: application/json" \
> -H "X-Session-Id: chat_9f2a7c" \
> -d '{
> "model": "openai/gpt-4o",
> "vendor": "openai",
> "max_tokens": 1024,
> "input": [
> {
> "type": "message",
> "role": "system",
> "content": "You are a support agent for Acme Corp. Follow this 3000-word policy: ...long stable document..."
> },
> {
> "type": "message",
> "role": "user",
> "content": "How do I reset a customer'\''s API key?"
> }
> ]
> }'

You can pass the session hint either as the X-Session-Id header or the session_id body field. The header wins when both are present. The value is capped at 256 characters and truncated rather than rejected, so a caching hint never fails a request.

Caching across API specs

Gateway accepts several request specs so you can point an existing SDK at it by changing the base URL. Each spec expresses caching in its own idiom, and Gateway normalizes them into the same caching contract. The X-Session-Id header works on every spec, since it rides on the HTTP request rather than the body.

SpecBase URLHow you express caching
Merge Responses APIhttps://api-gateway.merge.dev/v1/responsescache_control markers, session_id body field, or X-Session-Id header
Anthropic SDKhttps://api-gateway.merge.dev/v1/anthropiccache_control markers on content and system blocks
OpenAI SDKhttps://api-gateway.merge.dev/v1/openaiX-Session-Id header
Vercel AI SDKhttps://api-gateway.merge.dev/v1/ai-sdkproviderOptions.anthropic.cacheControl

The Merge Responses API examples are shown above. The rest of this section shows the same caching on the other specs.

Anthropic SDK

Point the Anthropic SDK at the /v1/anthropic base URL and mark the cacheable prefix with cache_control, the same way you would against Anthropic directly. Use this on explicit routes.

Python
1from anthropic import Anthropic
2
3client = Anthropic(
4 api_key="YOUR_API_KEY",
5 base_url="https://api-gateway.merge.dev/v1/anthropic",
6)
7
8message = client.messages.create(
9 model="anthropic/claude-haiku-4-5-20251001",
10 max_tokens=1024,
11 system=[
12 {
13 "type": "text",
14 "text": "Here is the full onboarding handbook for Acme Corp: ...long stable document...",
15 "cache_control": {"type": "ephemeral"},
16 }
17 ],
18 messages=[
19 {"role": "user", "content": "What is the PTO policy for a new hire in their first 90 days?"}
20 ],
21)

OpenAI SDK

Point the OpenAI SDK at the /v1/openai base URL. The OpenAI request shape has no place for a session field in the body, so pass the caching session hint as the X-Session-Id header. This drives automatic caching on automatic routes.

Python
1from openai import OpenAI
2
3client = OpenAI(
4 api_key="YOUR_API_KEY",
5 base_url="https://api-gateway.merge.dev/v1/openai",
6 default_headers={"X-Session-Id": "chat_9f2a7c"},
7)
8
9response = client.chat.completions.create(
10 model="openai/gpt-4o",
11 messages=[
12 {
13 "role": "system",
14 "content": "You are a support agent for Acme Corp. Follow this policy: ...long stable document...",
15 },
16 {"role": "user", "content": "How do I reset a customer's API key?"},
17 ],
18)

Vercel AI SDK

Point the AI SDK at the /v1/ai-sdk base URL and attach the marker through providerOptions on the content part you want cached. Use this on explicit routes.

TypeScript
1import { createOpenAICompatible } from "@ai-sdk/openai-compatible";
2import { generateText } from "ai";
3
4const merge = createOpenAICompatible({
5 name: "merge",
6 apiKey: "YOUR_API_KEY",
7 baseURL: "https://api-gateway.merge.dev/v1/ai-sdk",
8});
9
10const { text } = await generateText({
11 model: merge("anthropic/claude-haiku-4-5-20251001"),
12 messages: [
13 {
14 role: "user",
15 content: [
16 {
17 type: "text",
18 text: "Here is the full onboarding handbook for Acme Corp: ...long stable document...",
19 providerOptions: { anthropic: { cacheControl: { type: "ephemeral" } } },
20 },
21 {
22 type: "text",
23 text: "What is the PTO policy for a new hire in their first 90 days?",
24 },
25 ],
26 },
27 ],
28});

Whichever spec you use, the response reports cache activity the same way, covered next.

Outputs: reading cache token usage

Gateway reports cache activity in the response usage object, normalized across providers so you read the same two fields regardless of the route.

FieldMeaning
cache_creation_input_tokensInput tokens written to the cache on this request
cache_read_input_tokensInput tokens served from the cache on this request
1{
2 "usage": {
3 "input_tokens": 5620,
4 "output_tokens": 180,
5 "total_tokens": 5800,
6 "cache_creation_input_tokens": 0,
7 "cache_read_input_tokens": 5533
8 }
9}

A first request that writes the prefix reports a positive cache_creation_input_tokens and a cache_read_input_tokens of 0. A later request that hits the cache reports a positive cache_read_input_tokens. On automatic routes the provider may report only reads.

1usage = response.usage
2cached = usage.cache_read_input_tokens or 0
3total_input = usage.input_tokens or 0
4
5if cached:
6 print(f"Cache hit: {cached} of {total_input} input tokens served from cache")
7else:
8 print("No cache hit on this request")

Cache-read tokens are billed at the route’s reduced cache-read rate instead of the standard input rate, which is where the savings come from. Track cache_read_input_tokens across your traffic to measure the hit rate and the spend you avoid. For budgets and spend reporting, see Cost governance and savings.

Get the most out of caching

  • Put stable content first. Order the prompt so the unchanging part (system instructions, tool schemas, shared documents) comes before the part that changes each request. The cached prefix ends at the first token that differs.
  • Reuse prefixes while they are warm. Cache entries are short-lived. Caching pays off most in agent loops and multi-turn chats where repeat requests arrive within seconds.
  • Keep the prefix long enough. Providers only cache prefixes above a minimum length. A short shared prefix produces no cache hit even on a caching-capable route.
  • Pin model and vendor when caching matters. Caching follows the route. A routing policy that can pick a none route for some requests will not cache those, so pin the route when you depend on cache hits.

Common errors

The route may be automatic or none, where Gateway strips the marker. Check the family for your provider in the table above. On automatic routes, remove the marker and rely on the provider caching the prefix on its own.

The cache entry may have expired between requests, the prefix may be shorter than the provider minimum, or the prefix may differ across requests. Confirm the marked content is byte-for-byte identical and that repeat requests arrive close together, then verify the marker sits on the last block of the stable prefix.

A policy that selects among several routes can land on one that does not cache. Pin model and vendor for requests that depend on cache hits, or configure the policy with routes that share the same caching family.

Next steps