Reference

Errors

Errors are JSON with an error string. Branch on the status code, never on the message — the prose is written for humans and we reserve the right to reword it.

json
{"error":"Monthly quota exceeded","retryAfterSec":1738368000}

Status codes

CodeMeaningRetry?
400A parameter is malformed or unrecognised — a bad sort, an unsupported protocol, a poolId that is not 0x-prefixed hex.No. Fix the request. Costs no units.
401The KC-APIKey header is missing, unknown, revoked, or belongs to a suspended account.No.
403The key is valid but not allowed here. Almost always one of two things: a server key used from a browser (any request carrying an Origin header), or a browser key used from an origin it is not bound to.No — see Authentication.
404No such position, pool or route.No.
429Burst rate limit or monthly quota. Retry-After tells you which by how long it is: seconds for a burst, up to a month for a quota.Yes, after Retry-After.
5xxOur problem.Yes, with backoff.

Retrying well

Honour Retry-After when it is present; otherwise back off exponentially from about a second, with jitter, and give up after a handful of attempts. Do not retry a 4xx other than 429 — the answer will not change, and a tight loop against a 400 is the fastest way to look like an attack.

Two responses that are not errors

An empty list is a valid answer. The list endpoints apply visibility filters — minimum value, minimum pool TVL, and an exclusion of positions whose token has no corroborated on-chain market. A wallet with only small or spam-token positions returns { "data": [], "pagination": { "total": 0 } } and a 200. Widen the filters (minValueUsd=0&minPoolTvl=0&includeRisky=true&status=all) if you want everything.

A missing price is reported, not faked. When a token genuinely cannot be priced from any independent source, the position carries metrics.priceUnavailable: true rather than a misleading 0. Treat that as “unknown”, not as “worthless” — the two are different, and a valid 0 also exists.

Coverage

We serve Uniswap v4 on Ethereum (1) and Avalanche (43114). Any other chain or protocol is a 400, and that is a coverage statement rather than a bug — no v3, no Arbitrum, no Optimism today.

Still stuck

Check GET /health for indexing status: it reports the last indexed block against the chain head, so you can tell “the data is missing” apart from “the data has not been indexed yet”.