Skip to main content

The KnoxCall response block

When you call a route through KnoxCall, the status, headers and body you get back are your upstream’s, forwarded verbatim. That is deliberate: your code should see what your provider actually said, byte for byte. It leaves one question the response alone cannot answer. A 429 came back — was that your provider’s rate limit, or ours? A 502 — did the call reach them at all? The KnoxCall response block answers it, on every response, without touching the body your provider sent.
The whole x-knox- response namespace is reserved. If your upstream sends a header in it, KnoxCall drops it rather than relaying it. Everything below is always KnoxCall speaking, never something an upstream can forge.

The one check that matters

X-Knox-Upstream-Status is present if and only if a real upstream response was received.
If you wrap a provider SDK, branch on that absence. Without it, a client library reads our 429 as the provider’s and retries against a limit that is not the one refusing it — backing off in the wrong place, for the wrong reason, until the provider’s own limiter finally trips.
X-Knox-Origin says the same thing in a word, for when you are reading curl -i rather than writing code.

Every header

Latency, and what it measured

X-Knox-Latency-Ms cannot mean the same thing on a buffered and a streamed response, so it is labelled rather than left ambiguous:
  • X-Knox-Latency-Phase: complete — the whole body was in hand. The number is the full round trip.
  • X-Knox-Latency-Phase: first-byte — the response is streaming. Headers must be sent before any body byte, so this is time-to-first-byte and the total is not knowable yet.
X-Knox-Upstream-Ms and X-Knox-Overhead-Ms split that time between your provider and us. Both are omitted when the split was not measured rather than estimated — if you see them, they were timed.

Rate limits

Each limiter reports its own window, so three different ceilings do not collapse into one ambiguous pair of numbers:
reset is an ISO-8601 instant. It is absent on the monthly window, which rolls over with your billing period rather than on a fixed clock.
The older X-RateLimit-Limit, X-RateLimit-Tenant-* and X-API-Usage-* headers are still sent and still correct. They are deprecated in favour of the block above — the three families used different names, units and reset formats, and none of them said whether the limit that refused you was KnoxCall’s or your provider’s. Nothing that reads them today needs to change yet.

On errors KnoxCall itself returns

When KnoxCall refuses a call, the body is ours, so the block is repeated there as a knoxcall object alongside the usual error envelope:
The knoxcall key is a sibling of error, not nested inside it, so the existing error envelope is unchanged and a client that does not know about the block simply ignores it. On a forwarded response the block stays in the headers only. Your upstream’s body is passed through untouched — it may be JSON, a PDF, an image or a stream, and KnoxCall does not rewrite any of them.