Prompt caching
Prompt caching lets you reuse the large, static sections of your prompts — system prompts, schemas, tool definitions, context from documents or codebases — across many requests. On the first request that content is written to the cache as a prefix; later requests that start with the same prefix can read those tokens from cache. Cache charges are calculated as a multiplier of the selected model's standard input price. Prompt caching is available only on supported models, and the model catalog shows each supported model's current cache-read price. It's most valuable when many calls share a big chunk of context — a fleet of background agents all working from the same instructions and reference material, or a batch job running one prompt template over thousands of inputs — so that shared prefix is written once and then read cheaply on every call, instead of paid for in full each time. Switching it on takes only 3–4 extra lines of code.
Currently, prompt caching is opt-in and works on the OpenAI Chat Completions API (/v1/chat/completions) and the Anthropic Messages API (/v1/messages). The newer OpenAI Responses API (/v1/responses) isn't supported yet. Minimum cacheable prefix length is model-specific: most supported models currently require 1,024 tokens, while some differ. Check the selected model's pricing information for the current minimum.
Availability
Not every model supports prompt caching. A model supports it when its pricing metadata reports cache_pricing.enabled: true. Check the model catalog for the selected model rather than assuming caching is universally available.
How it works
A breakpoint (cache_control) marks the end of a cacheable prefix: everything from the start of the prompt up to and including that block.
- The first request with a given prefix writes it — a cache creation.
- Later requests that begin with the same prefix read it — a cache read, billed at the discounted rate.
Both the write and the reads are driven by the marker — a prefix isn't cached once and then reused automatically. Every request that should hit the cache must carry the same cache_control marker; a request sent without markers reads nothing, even if an identical prefix is already cached.
Matching is prefix-based and left-anchored: a request reuses the cache up to the longest leading run of content that is byte-for-byte identical to something cached before. As soon as content diverges, everything after it is treated as new.
Request A (writes): [ tools + system ]●[ user question 1 ]
Request B (reads): [ tools + system ]●[ user question 2 ]
└── identical ──┘ └── different ──┘
cache READ full price(● = breakpoint.)
TTL — each breakpoint lasts "5m" (the default) or "1h". The TTL is a sliding window: every read refreshes the expiry, so an actively-reused prefix stays warm and only expires after a full TTL with no reuse. Use 5m for bursty, back-to-back calls; 1h for interactive sessions.
Privacy & sharing — a cached prefix is scoped to the API key's owner and is never shared across customers. This gives you a choice of scope: use a key from your personal account to keep caching to yourself, or use one of your organization's keys to share prefix caching across your whole org — any org key can read a prefix that another org key wrote.
Quick start
Put the reusable content in an array-style content block and add the marker. Send the request twice — the second call reads the prefix from cache.
POST https://api.doubleword.ai/v1/chat/completions
{
"model": "{{selectedModel.id}}",
"messages": [
{ "role": "system", "content": [
{ "type": "text",
"text": "<~2,000 tokens of stable instructions>",
"cache_control": { "type": "ephemeral", "ttl": "1h" } } ] },
{ "role": "user", "content": "How do I reset my password?" }
]
}POST https://api.doubleword.ai/v1/messages
{
"model": "{{selectedModel.id}}",
"max_tokens": 256,
"system": [
{ "type": "text",
"text": "<~2,000 tokens of stable instructions>",
"cache_control": { "type": "ephemeral", "ttl": "1h" } } ],
"messages": [ { "role": "user", "content": "How do I reset my password?" } ]
}Read the result back from usage:
// 1st call — writes the prefix
"usage": { "prompt_tokens": 2088, "cache_creation_input_tokens": 2048, "cache_read_input_tokens": 0 }
// 2nd call — reads it; only the new user turn is billed at full price
"usage": { "prompt_tokens": 2096, "cache_read_input_tokens": 2048, "cache_creation_input_tokens": 0,
"prompt_tokens_details": { "cached_tokens": 2048 } }// 1st call — writes the prefix (zero-valued cache fields are omitted)
"usage": { "input_tokens": 2088, "output_tokens": 24, "cache_creation_input_tokens": 2048 }
// 2nd call — reads it; input_tokens counts only the new turn — the cached prefix is in cache_read_input_tokens
"usage": { "input_tokens": 48, "output_tokens": 24, "cache_read_input_tokens": 2048 }Streaming works the same way — the cache fields arrive in the final usage chunk.
Multiple breakpoints
You can place up to 4 breakpoints in one request, and using more than one pays off when your prompt has segments that change at different frequencies.
Take a common case: your tools never change, but you have a small set of system prompts — say one per task or agent mode — and pick one for each request. With a single breakpoint at the end of the system prompt, each system prompt caches tools + system together as one entry — so the identical tools get cached again under every variant, and you pay to write the tools once for each system prompt.
Put two breakpoints instead — one after the tools, one after the system prompt — and each segment is cached on its own cadence: the tools are written once and read by every system-prompt variant, and each system prompt is cached on top of them.
[ tools ]① ← cached once; read by every system-prompt variant
[ system prompt ]② ← cached per distinct system prompt
[ user message ]The rule: put a breakpoint at the end of each segment that changes on its own cadence — most-stable first (tools), then less-stable (system prompt, retrieved documents), then the conversation. Each layer is written once and reused until it changes, so you never re-pay to cache the stable parts underneath.
Adding a breakpoint never costs anything on its own — you're billed only for the tokens actually written to or read from the cache, never per breakpoint. So there's no harm in placing one wherever the prompt might start to change further down: an extra breakpoint can only ever help.
Patterns
System prompt & tools
Tool definitions and a long system prompt are identical on every call — cache them as the stable prefix and vary only the user turn. Tools sit first in the prefix, so a cache_control on the last tool caches every tool before it; a marker on the system block caches the tools and the system prompt.
{
"model": "{{selectedModel.id}}",
"tools": [
{ "type": "function", "function": { "name": "search", "parameters": {} } },
{ "type": "function", "function": { "name": "book_flight", "parameters": {} },
"cache_control": { "type": "ephemeral", "ttl": "1h" } }
],
"messages": [
{ "role": "system", "content": [
{ "type": "text", "text": "<agent instructions>",
"cache_control": { "type": "ephemeral", "ttl": "1h" } } ] },
{ "role": "user", "content": "Book me a flight to Tokyo next Friday." }
]
}{
"model": "{{selectedModel.id}}",
"max_tokens": 512,
"tools": [
{ "name": "search", "input_schema": { "type": "object" } },
{ "name": "book_flight", "input_schema": { "type": "object" },
"cache_control": { "type": "ephemeral", "ttl": "1h" } }
],
"system": [ { "type": "text", "text": "<agent instructions>",
"cache_control": { "type": "ephemeral", "ttl": "1h" } } ],
"messages": [ { "role": "user", "content": "Book me a flight to Tokyo next Friday." } ]
}RAG / document Q&A
Cache a large retrieved document once, then ask many questions about it — each question only pays full price for itself.
{
"model": "{{selectedModel.id}}",
"messages": [
{ "role": "system", "content": [ { "type": "text", "text": "Answer only from the document." } ] },
{ "role": "user", "content": [
{ "type": "text", "text": "<the 50-page contract>",
"cache_control": { "type": "ephemeral", "ttl": "1h" } },
{ "type": "text", "text": "What is the termination notice period?" }
] }
]
}The next question about the same document reads the whole contract from cache; only the new question is billed at full rate.
Growing conversation
Multi-turn chat is layered caching with a moving target: the system and tools stay fixed, any retrieved docs are per-session, and the conversation grows a message at a time. Put a breakpoint on each fixed layer, and — because caching isn't automatic — put a cache_control marker on the latest message in every request. Each turn then reads the whole conversation so far from cache at the discounted rate, and the only tokens that aren't already cached — what you added since your last request (the previous reply plus your new message) — are written at the write rate, ready to read cheaply next turn. You never re-write earlier turns, so a long conversation stays cheap: a discounted read of the history plus a small write on just the new tail.
Turn 1: [sys+tools]①[docs]②[user₁ ●] → mark user₁; writes through user₁
Turn 2: [sys+tools]①[docs]②[user₁][asst₁][user₂ ●] → mark user₂; reads through asst₁, writes the new turn
Turn 3: [sys+tools]①[docs]②…[asst₂][user₃ ●] → mark user₃; reads through asst₂, writes the new turnBecause matching is longest-common-prefix, a follow-up that shares only breakpoint ① still reads that layer and re-caches from there — you don't have to plan reuse perfectly.
Pricing
Cache prices are multipliers of the selected model's standard input price. The model catalog shows model-specific cache-read prices.
| Operation | Current multiplier on supported models |
|---|---|
| Cache read | r × standard input price1 |
| Cache write — 5m | 1.25× standard input price |
| Cache write — 1h | 2× standard input price |
| Uncached input | Model's standard input price |
| Output | Model's standard output price |
These are the current multipliers for cache-enabled models in the public catalog. Availability, minimum prefix length, and multipliers are model-specific and may change.
Cache writes cost more than standard input while cache reads cost less. The precise break-even point depends on the model, TTL, and active multipliers.
What you can cache
cache_control works on content blocks throughout the request, in the tools → system → messages order:
- Tool definitions — objects in the
toolsarray. - System content blocks.
- User and assistant text content blocks.
- Tool results — a
role: "tool"message (Chat Completions) or atool_resultblock (Messages API).
A few things worth knowing:
- Images & documents still benefit from caching when they sit inside a cached prefix (and changing one invalidates everything after it), but the image/document tokens themselves aren't discounted — only the text tokens in the prefix are.
- Empty text blocks and sub-content blocks (like citations) can't be marked directly — cache the top-level block instead.
- Caching is opt-in and best-effort: the marker requests caching, and you confirm it landed by reading the
usagefields (above). On a model that doesn't support caching, the marker is simply ignored and you're billed at standard rates — so it's always safe to include.
Getting the best out of caching
Golden rule: stable content first, volatile content last, breakpoint at the boundary.
[ STABLE PREFIX: tools, system prompt, instructions, examples, documents ] ● breakpoint
[ VOLATILE SUFFIX: this request's actual question ]- Order matters. Everything before the breakpoint must be identical across requests to get a hit. Keep per-request content — the question, timestamps, IDs — after the cached blocks, and send the cached blocks in a consistent order (the same content in a different order is a cache miss).
- Keep prefixes byte-identical. A single changed character before a breakpoint — a different date, a reordered sentence — breaks the match for everything after it.
- Cache the big stuff. Minimum cacheable prefix length is model-specific. Most supported models currently require 1,024 tokens, while some differ; check the selected model's pricing information.
- Don't cache one-offs. A write carries a small premium, so only cache prefixes you'll reuse.
Reference
Marker — add to any content block, or to a tool object in the tools array:
"cache_control": { "type": "ephemeral", "ttl": "5m" }typemust be"ephemeral";ttlis"5m"(default) or"1h".- Up to 4 breakpoints per request.
- Minimum prefix tokens are model-specific; check the selected model's pricing information.
- Markers change the bill, never the output.
Usage fields — the totals field differs by API; the cache fields are the same on both:
prompt_tokens total input tokens (includes the cached ones)
completion_tokens tokens generated by the model
cache_read_input_tokens tokens served from cache — discounted read rate
prompt_tokens_details.cached_tokens same count as cache_read_input_tokens (OpenAI-standard field)
cache_creation_input_tokens tokens written to the cache this request — write rateinput_tokens new (non-cached) input tokens — the cached prefix is reported separately
output_tokens tokens generated by the model
cache_read_input_tokens tokens served from cache — discounted read rate (omitted when zero)
cache_creation_input_tokens tokens written to the cache this request — write rate (omitted when zero)Cache token counts in usage are derived from the content you send and are used for billing; they can differ slightly from a model's internal tokenisation (tool definitions in particular are tokenised from their JSON). cache_read_input_tokens is charged using the selected model's active read multiplier. Cache-creation token fields are charged using the multiplier for the requested TTL. Each multiplier applies to the selected model's standard input-token tariff.
Further information
Doubleword's prompt caching follows the same model and semantics as Anthropic's, so their guidance carries over directly. For deeper background — cache-aware prompt structure, what invalidates a cache, and more worked examples — see Anthropic's prompt caching guide. The available TTLs are 5m and 1h; consult the model catalog for the selected model's authoritative pricing information. And unlike Anthropic there's no automatic-caching option — caching is always driven by your cache_control markers, so place them wherever you want the prefix to be cached (e.g. on your tool definitions and system prompt).
Footnotes
-
r is the selected model's current cache-read multiplier. See the model pricing table for the authoritative rate. ↩