Esc to close · ⌘K / Ctrl-K opens search anywhere
Repeated, identical requests don't need to hit a model twice. Add acache control to a /v1/chat/completions request and BharatRouter will store the response and serve an identical follow-up straight from cache — no upstream call, near-zero latency, and billed at ₹0. It's our parity for Portkey's "simple cache".
Opt-in only — privacy first. Caching stores your response content, so it is a deliberate departure from BharatRouter's zero-retention default. Nothing is ever cached unlessyou ask for it on that specific request. See Privacy & retention.
Send a cache object alongside your normal fields. ttl_seconds is how long the entry lives (default 300s, max 24h):
curl https://api.bharatrouter.com/v1/chat/completions \
-H "Authorization: Bearer br-..." -H "Content-Type: application/json" \
-d '{
"model": "glm-4.6",
"messages": [{"role": "user", "content": "Summarise the DPDP Act in one line."}],
"cache": { "mode": "simple", "ttl_seconds": 600 }
}'Shorthand: "cache": true is the same as mode simple at the default TTL. The cache field is a BharatRouter control — it is stripped from the payload we forward upstream.
| Field | Default | Meaning |
|---|---|---|
mode | simple | simple = exact-match cache (same org, model & request → same answer). semantic = embedding-similarity cache (see below). |
ttl_seconds | 300 | Entry lifetime in seconds (1–86400). Keep it short — a cached answer is stale the moment the world moves on. |
threshold | 0.92 | Semantic only. Minimum cosine similarity (0–1] for a near-neighbour to count as a hit. Higher = stricter (closer paraphrase required). |
A simple cache only hits on a byte-identical request. Semanticcaching instead embeds your prompt and replays a stored answer when a recent, similarprompt from your org is close enough — so paraphrases ("Summarise the DPDP Act briefly" vs "Give me a one-line summary of the DPDP Act") can share one answer:
{
"model": "glm-4.6",
"messages": [{"role": "user", "content": "Give me a one-line summary of the DPDP Act."}],
"cache": { "mode": "semantic", "threshold": 0.95, "ttl_seconds": 600 }
}Your prompt is embedded with a first-party, India-resident model and compared by cosine similarity against your org's recent window for that model. A match at/abovethreshold is replayed; otherwise the request routes normally and its answer joins the window. Everything else — opt-in, org-scoping, short TTL, honest ₹0 accounting, fail-open — is identical to the simple cache. Tune threshold deliberately: too low and you risk a subtly-wrong paraphrase answer; the default is intentionally strict.
x-br-cache headerEvery opted-in response carries an x-br-cache header so you can see what happened:
x-br-cache: miss — served upstream and (if eligible) stored for next time.x-br-cache: hit — served from the simple exact-match cache; no model was called and the request cost ₹0.x-br-cache: hit-semantic — served from the semantic cache on a near-neighbour match; the matched cosine similarity is reported in x-br-cache-similarity. Cost ₹0.A hit replays the original completion verbatim, including its x-br-provider,x-br-model and x-br-residency.
An entry is keyed on a hash of your organisation, the model, and a normalised copy of the request body (messages, temperature,max_tokens, stop, tools, and the other output-shaping fields). Two things follow:
Routing controls (provider, optimize, fallbacks, …) arenot part of the key — they steer how we route, not what a model returns for a given input.
Even with a cache control, a request is only cached when it is safe and deterministic-ish to do so:
stream: true is never cached.2xx completions with real content are stored — errors are never cached (so a transient upstream failure can't be pinned), and neither are empty/degraded responses.upstream_key is never cached — that's your own secret, quota and billing, and its content isn't ours to persist.temperature makes a poor cache candidate; the explicit per-request cache control is your override — if you ask to cache it, we honour it.A cache hit is still logged as a real, attributable request in your Activity — it simply showscost ₹0, is marked cached, and accrues no budget spend(no upstream call happened). Token counts from the original completion are preserved so your usage breakdown still adds up.
BharatRouter is zero-retention by default: we don't store prompt or completion content. The response cache is the one place that deliberately does — so it is strictlyopt-in per request, never a default, and always visible via thex-br-cache header.
ttl_seconds elapses (max 24h), then Redis evicts them automatically.cache control and nothing is stored. Operators can also disable the feature fleet-wide.Because caching stores content, don't opt-in for requests whose responses must not be retained even briefly (e.g. content under a strict data-handling agreement) — leave those on the default zero-retention path.
The cache is an optimisation, never a dependency. If Redis is unavailable or a cache read/write errors, the request falls straight through to normal routing — a cache problem can never fail an inference call.