Saving on repeated requests: caching via X-Zukko-Cache and temperature:0
The same request twice should not cost twice. Here is how response caching works and which scenarios actually benefit from it.
4 min · · Updated · API · экономия
If an application regularly sends the same request over and over — a template status check, classifying repeated text, a test run of a prompt — there is no need to pay full price every time. Response caching on the gateway handles exactly this, and it does not turn on automatically by default; it triggers on one of two conditions.
When caching kicks in
There are two ways to get a cached response instead of a fresh model call:
The X-Zukko-Cache: true header. The primary method: it works with any model and regardless of temperature — the explicit header forces caching even if you never touch temperature.
temperature: 0 in the request body. This also enables caching: at zero temperature the model should already produce a deterministic (or near-deterministic) answer for the same input. But it only works for models that accept the parameter. claude-sonnet-5 and claude-opus-5-5 may reject a temperature other than 1 (and top_p below 0.99) with a 400 — with Claude models, don't pass temperature or top_p, and turn on caching with the header.
curl https://api.zukko.pro/v1/chat/completions \
-H "Authorization: Bearer fetch_your_key" \
-H "X-Zukko-Cache: true" \
-H "Content-Type: application/json" \
-d '{"model":"claude-sonnet-5","messages":[{"role":"user","content":"Translate the word table to Russian"}]}'The cache is scoped per user — identical requests are cached within one account, not globally across different gateway users. The retention period for chat requests is up to 7 days, after which the cache expires and the next identical request goes back to the model.
How to tell a response came from cache
The response carries an X-Zukko-Cache header, with a value of hit on a cache hit:
curl -i https://api.zukko.pro/v1/chat/completions \
-H "Authorization: Bearer fetch_your_key" \
-H "X-Zukko-Cache: true" \
-H "Content-Type: application/json" \
-d '{"model":"claude-sonnet-5","messages":[{"role":"user","content":"What is HTTP 404?"}]}' \
| grep -i x-zukko-cacheA cached response returns instantly and for free — the X-Zukko-Cost-Micros header in this case will be zero or absent, since no charge occurs. Cache hits do not show up in the /v1/usage history either.
Where this actually saves money
Repeated prompt testing. While debugging a system prompt, a developer typically runs the same input text dozens of times, changing only the model's system-role instruction. If the test input stays fixed and caching is on via the X-Zukko-Cache: true header, every repeat run with an identical request body costs nothing after the first.
Classifying repeated values. If a service classifies a data stream where values repeat (say, the same product category names, the same statuses), caching removes duplicate model calls for values already seen — as long as the surrounding prompt also stays unchanged.
Demos and CI tests. In automated tests where the scenario is fixed and runs on every push, the X-Zukko-Cache: true header gives you free repeat runs until the cache expires, and for models that accept temperature: 0 it adds determinism too (important for catching regressions).
What caching does not do
Caching only triggers on an exact match of the request — model, temperature, messages, and other body parameters. The smallest change (an extra space in the prompt, a different max_tokens, an added system message) makes it a different request, and caching does not apply. This is not semantic caching by meaning — it is an exact match on the request body.
Caching also does not replace Idempotency-Key. These are different mechanisms: Idempotency-Key protects against double billing on a retry of the same request within 24 hours (useful for network drops), while response caching is a separate feature about reusing a result for up to 7 days when the body matches. You can use both at once, but do not confuse them — idempotency is about reliability, caching is about repeatability and savings.
curl https://api.zukko.pro/v1/chat/completions \
-H "Authorization: Bearer fetch_your_key" \
-H "Idempotency-Key: batch-42-item-7" \
-H "X-Zukko-Cache: true" \
-H "Content-Type: application/json" \
-d '{"model":"glm-5.3-flash","messages":[{"role":"user","content":"Classify: iPhone 15 Pro"}]}'In this example both mechanisms work together: X-Zukko-Cache: true opens the door to caching on a repeated request, and Idempotency-Key protects this specific call from being billed twice on a network failure.
Checking cost before and after caching
To confirm caching is actually saving money, it helps to compare the headers of a first and second identical call:
import requests
url = "https://api.zukko.pro/v1/chat/completions"
headers = {"Authorization": "Bearer fetch_your_key", "Content-Type": "application/json", "X-Zukko-Cache": "true"}
body = {
"model": "claude-sonnet-5", # no temperature for Claude
"messages": [{"role": "user", "content": "What is 17 * 24?"}],
}
first = requests.post(url, headers=headers, json=body)
second = requests.post(url, headers=headers, json=body)
print("first cache:", first.headers.get("X-Zukko-Cache"), "cost:", first.headers.get("X-Zukko-Cost-Micros"))
print("second cache:", second.headers.get("X-Zukko-Cache"), "cost:", second.headers.get("X-Zukko-Cost-Micros"))The first call hits the model and gets billed; the second one — with an identical body and the X-Zukko-Cache: true header — should come back with X-Zukko-Cache: hit and zero cost.
When caching is the wrong tool
If the task needs variety in the answer to the same input — generating text variants, creative work where a repeat request should sound different each time — caching and temperature: 0 work against the actual goal. In these scenarios, do not enable caching (do not set X-Zukko-Cache: true and do not zero out temperature), or the user will keep getting the same variant instead of a new one.
Bottom line
Response caching is a free way to remove repeated spend on identical requests, but it requires a deliberate choice. The primary method is the explicit X-Zukko-Cache: true header: it works with any model. temperature: 0 is an alternative where determinism is already needed, but only for models that accept that parameter (not Claude). Checking for X-Zukko-Cache: hit in the response is the fastest way to confirm the saving is actually happening, not just assumed.
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.
Related articles
- opencode agents: setting up roles, models and toolsA custom agent in opencode is a role, a model and a set of permissions. A working config where a cheap model handles routine work and a stronger one edits code.
- Plan mode in Claude Code: plan first, then edit the codeIn plan mode Claude Code reads your code and proposes a plan but edits nothing until you agree. How to enable it, use it and what it costs.
- Buying AI tokens: how a dollar balance works and what $5 gets youTokens at a gateway are not a package but a dollar balance. We look at what is charged to it and calculate how many requests $5 covers.
- Paying for AI without a fee: is it possible and how to calculate the overpaymentThere is almost always a fee when you top up. We show what it consists of, calculate it for SBP and card, and give a formula for how many rubles you need for N dollars.