The X-Zukko-Cache response cache: when a request is free

The same request from the same user shouldn't be billed twice. Here is how the cache turns on and how to check whether it actually fired.

5 min · · Updated · API · экономия

If the same request from the same user repeats — in tests, in CI, during repeated runs of the same prompt while developing — paying for it twice makes no sense. That's what the built-in response cache is for.

When a request gets cached

Caching kicks in in two cases:

  • the request carries the header X-Zukko-Cache: true — the primary, universal option that works for any model;
  • the request is sent with "temperature": 0 — only for models that accept that value. Claude models (claude-opus-5-5, claude-sonnet-5) may reject a temperature other than 1 and a top_p below 0.99 with a 400 error, so don't pass temperature/top_p to them — use the header instead.

In both cases, identical requests from the same user are cached — for chat, the cache lives for up to 7 days. A repeated identical request within that window comes back instantly and free. The cache works for POST /v1/chat/completions, /v1/messages and /v1/responses.

bash
curl https://api.zukko.pro/v1/chat/completions \
  -H "Authorization: Bearer fetch_your_key" \
  -H "Content-Type: application/json" \
  -H "X-Zukko-Cache: true" \
  -d '{
    "model": "claude-sonnet-5",
    "messages": [{"role": "user", "content": "Explain the difference between 401 and 403"}]
  }'

A second call with the exact same body from the same key/account hits the cache.

How to confirm it fired

The response carries X-Zukko-Cache: hit when it was served from cache. If the header is missing, the request reached the model and was billed as usual.

bash
import requests

resp = requests.post(
    "https://api.zukko.pro/v1/chat/completions",
    headers={
        "Authorization": "Bearer fetch_your_key",
        "X-Zukko-Cache": "true",
    },
    json={
        "model": "claude-sonnet-5",
        "messages": [{"role": "user", "content": "Explain the difference between 401 and 403"}],
    },
)

print("cache:", resp.headers.get("X-Zukko-Cache", "miss"))
print("cost micros:", resp.headers.get("X-Zukko-Cost-Micros"))
print("balance micros:", resp.headers.get("X-Fetch-Balance-Cents"))  # despite the name, microdollars

X-Zukko-Cost-Micros shows the cost of the request in micro-dollars (1,000,000 = $1); X-Fetch-Balance-Cents, despite its name, is in microdollars too. On a cache hit the cost should be zero or absent — it's worth checking both headers together rather than relying on X-Zukko-Cache alone. Cache hits aren't written to /v1/usage.

Why temperature: 0 also triggers caching (on models that accept it)

temperature: 0 means deterministic, maximally predictable output — with identical input, the model already tends to return the same answer anyway. Since the result barely changes from call to call without caching either, caching it is safe by construction: the user gets the same answer they'd get from a live call, just faster and free.

If you need variety in the output (creative-writing prompts, chat with randomness), don't set temperature: 0 purely to save money — you'll get identical answers where you wanted different ones. In that case, use X-Zukko-Cache: true deliberately, only on prompts where a repeated answer is the expected and desired behavior.

Where it actually saves money

CI and automated tests. A pipeline that fires the same test prompt at a model on every push (say, checking the integration answers at all) can run it on every commit — as long as the request body doesn't change, only the first run within the cache window gets billed.

Repeated runs during development. Debugging a prompt locally often means dozens of reruns of the same code with the same input while you fix the rest of the app's logic. As long as the prompt itself doesn't change, every rerun after the first is free.

Demos and presentations. If a demo script is known in advance and repeated verbatim, the first run is billed and every subsequent run that week is not.

What doesn't get cached

The cache is tied to the user (account/key) and to the exact request body. It's not a shared "same prompt from anyone" cache — if two different clients send identical text, each gets its own billed generation unless they're using the same key. The cache only fires on a fully identical request body — not on "nearly identical" requests and not on a shared prefix. The smallest difference in the body — a different system prompt, a different message order, an extra space in the text, a different max_tokens value — counts as a different request; the cache misses and the full cost gets charged (the metadata, user and stream_options fields don't count toward the comparison).

Image generation through Zukko is temporarily unavailable, so everything here applies to text requests.

Cache versus Idempotency-Key — not the same thing

Easy to mix up, since both guard against paying twice. The difference is what they guard against: Idempotency-Key prevents paying twice for the same request on a retry after a failure (network dropped, the client never got the answer). Caching via X-Zukko-Cache is about intentionally repeated requests you send again and again on purpose, because the input doesn't change. One is about reliability, the other about saving money on predictable load. They can be used together on the same request without conflicting.

A practical example: a test prompt suite

Say you have a set of twenty reference prompts for regression-testing answer quality after a model version change, and a nightly CI job runs them every night. Adding X-Zukko-Cache: true to every request except the first run after the prompts actually change turns most nightly runs free. You get billed only when the prompt text or system prompt genuinely changes — exactly when the result is worth checking again.

Bottom line

The cache isn't a dashboard toggle — it's two ways to mark a specific request as cacheable: the X-Zukko-Cache: true header (primary, works for any model) or temperature: 0 (only on models that accept it — not Claude). Check X-Zukko-Cache: hit in the response to confirm it fired, and X-Zukko-Cost-Micros to see the actual cost (or lack of one) for a given call.

zukko

Pay 25×
less

for Claude Code & ChatGPT

One fetch_* key and base URL api.zukko.pro — for Cursor, Claude Code, Codex, and any SDK.

Get API keyDocumentation

api.zukko.pro · fetch_*

X-Zukko-Cache: how the free response cache works · Zukko