Errors and retries
Every non-2xx response is JSON with a stable machine code and a human message:
{ "error": "INSUFFICIENT_LIQUIDITY", "message": "no route at this size — try a smaller amount" }Branch on error, never on message. Some older routes add statusCode; ignore it.
| Status | error |
Where | Meaning and what to do |
|---|---|---|---|
| 400 | INVALID_PARAMS |
everywhere | A parameter is missing or malformed. The message names it. |
| 400 | BAD_ADDRESS · BAD_LIMIT · BAD_HOURS · BAD_DAYS · BAD_SORT · BAD_QUERY · BAD_POOL |
reads | The named check failed. |
| 400 | UNSUPPORTED_CHAIN · BAD_CHAIN |
quote, swap, boards | The chain id is not one the API serves. |
| 400 | BAD_SOURCE |
smart money | source=onchain is required on 5042 / 4663. |
| 400 | SLIPPAGE_MISMATCH |
swap | The slippageBps you sent differs from the quote’s. Re-quote at the slippage you want. |
| 400 | ROUTE_MISMATCH |
swap | The quote body was edited. Send it back unmodified. |
| 400 | ONLY_REQUIRES_KEY |
quote | ?only= needs an API key. |
| 401 | UNAUTHORIZED |
ask, me | No key or session, or an unknown one. |
| 404 | UNKNOWN_TOKEN |
charts, trades, stats | Not on a curated list and not a side of an indexed pool. |
| 404 | NOT_FOUND |
pool, position, report | Nothing at this identity. |
| 404 | NO_ROUTE |
swap calldata | No route for this pair and size. |
| 404 | NOT_ENOUGH_HISTORY |
LP plan, simulate | Fewer than 24 hourly candles or no anchored pool. |
| 409 | ROUTE_STALE_GRADUATED |
quote | A bonding-curve token graduated mid-route (Monad). Re-quote. |
| 409 | NOT_ATTESTED · IN_FLIGHT |
bridge relay | Circle has not attested the burn yet, or a relay is already running. Poll /bridge2/status. |
| 429 | RATE_LIMIT_EXCEEDED |
everywhere | Read X-RateLimit-Reset and back off. |
| 429 | RATE_LIMITED |
ask | Over 8 questions a minute. |
| 502 | ENGINE_ERROR · ROUTE_ERROR |
quote, swap | The routing engine did not answer. Retry once after a second. |
| 503 | NOT_READY |
arc, rh, launchers | The rollup or index has not run on this deployment yet. |
| 503 | CHAIN_NOT_ENABLED |
quote, smart money | The chain’s routing or board is not published here. |
| 503 | HOLDERS_PENDING |
holders | The token was just pinned for tracking. Retry in a few minutes. |
| 503 | NOT_ENABLED |
points | The points program is off on the deployment. |
| 503 | ARC_DATA_UNAVAILABLE · RH_DATA_UNAVAILABLE · SIMULATION_UNAVAILABLE · IRIS_UNAVAILABLE · SESSION_STORE_UNAVAILABLE · DISABLED |
various | A dependency did not answer. Retry with backoff. |
Empty is not an error
Section titled “Empty is not an error”Some answers are honest empties, not failures:
- A quote with
routePlan: []andoutputAmount: "0"— no route at this size. ReadnoRouteReason(INSUFFICIENT_LIQUIDITYorNO_POOLS). - A token on
/arc/token/{address}that comes back as{ address, listed: false }— no trades in the last 24 hours. - Portfolio routes answer an empty 200 shape (
tokens: []) when the tape read fails, never a 5xx. Treat it as “nothing yet” and retry later. - A holder ledger with
complete: false— the backfill has not reached the token’s creation block; balances are partial and say so.
Retrying
Section titled “Retrying”Retry 502 and 503 with exponential backoff starting at one second, at most three times. Do not retry 400, 401, 404 or 409 — the request will not become valid on its own (a 409 NOT_ATTESTED is a poll, not a retry). Retry 429 after X-RateLimit-Reset.
Quotes are live and expire: a 502 on /swap after a successful quote usually means the route changed. Quote again rather than resubmitting the old body.