Help centre
The failures worth recognising on sight. Each row is the literal response the API returns, so you can match what you are looking at against it — but branch your code on the status code, never on the message.
- 401 · Missing KC-APIKey headerThe header is absent. Usually a proxy or client library that drops unknown headers, or an Authorization: Bearer that was never read.Send the key as KC-APIKey. Not a bearer token, and never a query parameter.
- 401 · Invalid or revoked API keyThe key is not recognised, has been revoked, or belongs to a suspended account. A whitespace-padded copy-paste looks identical and fails the same way.Issue a fresh key in the portal. The secret is shown once and stored hashed, so a lost key is replaced rather than recovered.
- 403 · This API key is server-only and cannot be used from a browserA server key sent a request carrying an Origin header — which is to say, from a browser. The key is valid; the place it was used is not.Call the API from your backend, or issue a browser key with your origins listed. This 403 is the feature: it stops a secret key going public silently.
- 403 · Origin not allowed for this API keyA browser key was used from an origin it is not bound to. Origins are matched exactly on scheme://host[:port], so https://app.example.com and https://www.app.example.com are different entries, as are ports in local development.Add the exact origin to the key. Paths and wildcards are rejected at issue time, not silently ignored.
- 429 · Rate limit exceededThe burst limit, counted in requests per key over a rolling window. Retry-After will be seconds.Honour Retry-After. This one clears on its own; a tight retry loop is what turns it into a sustained one.
- 429 · Monthly quota exceededThe monthly unit allowance, counted across every key on the account. Retry-After will be large — it points at 00:00 UTC on the 1st.Upgrade, or wait for the reset. A quota 429 consumes nothing, so there is no charge for hitting it.
- 400 · Unsupported chainId · Unsupported protocol · Invalid poolIdA coverage or format boundary. We serve Uniswap v4 on Ethereum (1) and Avalanche (43114); a v4 poolId is 0x plus 64 hex, a v3 one 0x plus 40.Check coverage before treating it as a bug. Any 4xx is refunded, so a malformed request costs no units.
- 404 · Position not found · Pool not foundNo such id on that chain and protocol. Distinct from an empty list: a filtered search that matches nothing returns 200 with an empty array.Confirm the chainId and protocol in the path. An id from one chain will 404 against another.
Two answers that look wrong
minValueUsd=0&minPoolTvl=0&includeRisky=true&status=all before concluding the data is missing.metrics.priceUnavailable: true rather than a misleading zero. Treat that as unknown, not as worthless — a genuine zero also exists, and the two mean different things.Before you escalate
Check indexing freshness first. It reports the last indexed block against the chain head per chain, which is what separates “this data does not exist” from “this data has not been indexed yet” — and the second one resolves itself.
We do not stamp a request id on responses, so a trace starts from what you can see. Have ready: the full request URL including query string, the UTC timestamp, the status code, the verbatim error string from the body, and the X-RateLimit-* / X-Quota-* headers if it was a 429. Never send the key itself.
Longer form on all of this: errors, authentication and units and limits.