Reference

Gateway headers.

Every x-gateway-* header the Leanroute API emits (and the ones it accepts), with direction, example values, and when to look for each.

All headers are ASCII (RFC 7230 §3.2.4 enforced by CI). Header names are case- insensitive per HTTP spec, but we emit them lower-case. Cmd/Ctrl+F within the page works fine — headers are alphabetical within each direction group.

Request headers

Headers you send to Leanroute on the way in.

Appears: Every authenticated endpoint. Required.

Bearer token authenticating a Leanroute gateway API key. Get one at /dashboard/keys. Test-key format gw_live_* — never expose in client-side code.

Example

Authorization: Bearer gw_live_...

JavaScript

fetch("https://api.leanroute.dev/v1/chat/completions", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${process.env.LEANROUTE_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ model, messages }),
})

Python

from openai import OpenAI

client = OpenAI(
  base_url="https://api.leanroute.dev/v1",
  api_key=os.environ["LEANROUTE_API_KEY"],
)

Appears: Optional. Send on requests you want pinned to a specific model.

Set to "explicit" to disable cheaper-model swaps and provider arbitrage for this single request, even when your org has them enabled. Used when you want deterministic routing to the exact model you named — e.g., you're benchmarking, or the request needs a specific model's tool-calling behavior.

Example

x-gateway-routing: explicit

JavaScript

fetch("https://api.leanroute.dev/v1/chat/completions", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${key}`,
    "Content-Type": "application/json",
    "x-gateway-routing": "explicit",
  },
  body: JSON.stringify({ model: "anthropic/claude-sonnet-4-6", messages }),
})

Python

# With openai SDK, use extra_headers on the create call:
client.chat.completions.create(
  model="anthropic/claude-sonnet-4-6",
  messages=[...],
  extra_headers={"x-gateway-routing": "explicit"},
)

Response headers

Headers Leanroute emits on the way back — cost, provider, routing decisions, cache state, failover, and throttling.

Appears: Every successful response where the served model is in PRICING.

Comma-separated list of the public benchmarks that place the SERVED model in its quality tier. Auditable signal: if we swapped Sonnet → DeepSeek-V4 for cost, this header names the benchmarks (MMLU / GPQA / HumanEval) that justify the pairing. See /tiers for the full mapping.

Example

x-gateway-benchmark-basis: MMLU,GPQA,HumanEval

Appears: Every successful response.

The canonical model id that actually answered your request. Useful when arbitrage or failover changed the model — this is authoritative for what got billed and what generated the tokens.

Example

x-gateway-model: deepseek/deepseek-v4-flash

Appears: When we auto-rewrote a request from a deprecated model id to its current canonical name.

Original model id you sent, when it was in our DEPRECATED_MODELS table. We transparently rewrite to the replacement so your code keeps working — but you should update your code to the current model id. Example rewrites: claude-sonnet-4.6 → claude-sonnet-4-6 (dotted to hyphenated), google/gemini-2.5-flash → google/gemini-3.1-flash-lite (upstream soft-deprecated).

Example

x-gateway-model-deprecated: google/gemini-2.5-flash

Appears: Every successful response.

Provider name that actually served the request. When arbitrage or failover changed the provider, this reflects the final choice, not the originally-requested one. Values: openai, anthropic, google, deepseek, xai, qwen, glm, doubao, kimi, sarvam, krutrim.

Example

x-gateway-provider: anthropic

JavaScript

const res = await fetch(url, opts);
console.log("served by:", res.headers.get("x-gateway-provider"));

Python

resp = client.chat.completions.with_raw_response.create(...)
print("served by:", resp.headers.get("x-gateway-provider"))

Appears: When the gateway swapped from the requested model to a cheaper same-tier alternative (cheaper-model-swap opt-in).

The canonical model id you originally requested, before the swap. If you sent anthropic/claude-sonnet-4-6 with cheaper-model-swap on, we may serve you deepseek/deepseek-v4-flash and this header carries the original id. Format: "<original> -> <served>".

Example

x-gateway-routed-from: anthropic/claude-sonnet-4-6 -> deepseek/deepseek-v4-flash

Appears: When a swap occurred (cheaper-model swap or failover).

Why we swapped models. Named values documented in the routing decider (apps/api/src/routing/decide.ts SwapReason). Absent when no swap happened. Combine with x-gateway-benchmark-basis for a full audit trail.

Example

x-gateway-swap-reason: cheaper_same_tier

Appears: When the originally-routed provider returned 5xx and we retried on an alternative.

Set to "true" when the customer's request succeeded via failover after the first-choice provider returned 5xx. Together with x-gateway-failover-from, this lets your monitoring detect provider-side incidents even though your customer got a clean 200.

Example

x-gateway-failover: true

Appears: Only present when x-gateway-failover is set.

Provider name that returned 5xx and triggered failover. Correlate this with your monitoring for provider-outage detection.

Example

x-gateway-failover-from: anthropic

Appears: When the response came from cache instead of the upstream provider.

Cache tier that served the response. Two values: "exact" (SHA-256 hash match on request bytes — free, zero false positives) or "semantic" (embedding-based nearest-neighbor at ≥0.85 cosine similarity — paid tiers, uses OpenAI text-embedding-3-small). Cache hits are billed at $0.

Example

x-gateway-cache: exact

Appears: Only present when x-gateway-cache: semantic.

Cosine similarity score of the semantic-cache match, four decimal places. Useful for debugging cache-hit accuracy — if you're seeing wrong answers on semantic hits, look for scores clustering right at the threshold and tune GATEWAY_SEMANTIC_CACHE_THRESHOLD.

Example

x-gateway-cache-similarity: 0.9412

Appears: When your request was dispatched using your own BYOK key for that provider.

Set to "true" when the gateway used your stored BYOK provider key instead of our managed one. Useful for confirming that traffic you expect to be BYOK actually is — e.g., you added a Krutrim BYOK key and want to verify it's being used, not our managed budget.

Example

x-gateway-byok: true

Appears: Every successful response where cost is computable.

USD cost of this single request. Six-decimal precision. Reflects the actual upstream cost — no per-request markup on inference. Cache hits show 0.000000 (billed at $0).

Example

x-gateway-cost-usd: 0.000823

Appears: Credits-plan customers, every response.

Remaining prepaid credit balance after this request debited its cost, in USD with 6-digit precision. Not present on BYOK-subscription plans.

Example

x-gateway-credit-balance-usd: 47.324180

Appears: Every successful response.

End-to-end request latency in milliseconds, measured at the gateway. Includes upstream provider dispatch + our routing + cache checks. Useful for client-side monitoring without needing your own timer.

Example

x-gateway-latency-ms: 847

Appears: Every successful response.

Values: "true" (prompts may have entered the prompt cache) or "false" (org has enabled no-persistence mode via /dashboard/settings and this request bypassed the cache entirely). Auditable signal for compliance-sensitive customers to verify their setting actually applied.

Example

x-gateway-prompts-persisted: false

Appears: On 402 (insufficient credit) / 429 (rate limited) error responses.

Which specific limit fired. Values: credit_balance, spend_cap_daily, spend_cap_monthly, rpm, tpm. Use this to route retry logic on the client — a spend_cap_daily failure retries at midnight UTC; an rpm failure retries in ~60s.

Example

x-gateway-throttle-scope: spend_cap_daily

Related

  • Developer Guide — endpoints, request shapes, error codes.
  • Quality tiers — the model-to-tier mapping that governs when x-gateway-swap-reason fires.
  • Compliance posture — details behind x-gateway-prompts-persisted and no-persistence mode.
  • Live sandbox — send a request and see these headers on a real response. No signup.