API error codes
Every error code of the Femtos API (REST, WebSocket, MCP, x402): its HTTP status, what it means and what the caller should do to fix its call.
Every error body, REST, WebSocket frame or MCP tool error, has the same fields: error (the text older clients match on), code (stable: branch on it), message, param (an invalid_param's parameter, when known), docs_url (this page, at the code) and request_id.
{"error": "limit must be 1..500", "code": "invalid_param", "message": "limit must be 1..500", "param": "limit",
"docs_url": "https://femtos.xyz/errors#invalid_param", "request_id": "6f1c2a9e-3b7d-4e2f-9a51-0c8d7e6b5a43"}request_id is the X-Request-Id header every answer carries, success too: send your own (up to 128 characters of A-Z a-z 0-9 _ . : / + = -) to follow a call, and quote it to support. 429 and the 503s that know when carry Retry-After. WebSocket error frames add channel and filter; their request_id is the upgrade's.
Codes
| Code | HTTP | Meaning | What to do |
|---|---|---|---|
| invalid_request | 400 | The request itself is malformed: a body that is not JSON, an unknown WebSocket op, a URL that does not parse. | Fix the request (JSON body, op subscribe / unsubscribe / ping) and send it again. |
| invalid_param | 400 | A parameter is missing or has a value the route does not accept; param names it when known. | Read message (the accepted values or range), fix param and send the call again. Never retry it unchanged. |
| invalid_payment | 400 | x402: the payment header does not decode (base64 JSON, fields, version). | Rebuild the payment from an accepts entry of this answer (reason says what is wrong) and send the request again. |
| 401 | No API key, or an unknown, disabled or expired one. | Send Authorization: Bearer <key>. No key yet: a free one at https://femtos.xyz/accounts/ or, for an agent, https://femtos.xyz/agents.md#agent-onboarding. | |
| invalid_ticket | 401 | WebSocket: the ticket is unknown, already used or older than 30 s. | POST /v1/ws-ticket with your key for a new ticket and open /v1/ws?ticket=<ticket> at once. |
| demo_pass_expired | 401 | The portal demo pass of this visitor expired. | Reload the page for a new pass, or use a free key. |
| payment_required | 402 | Payment needed: a heavy call of a key with no credits left (billing on), or, x402 on, a request with no key. | Top up (checkoutUrl), or pay one x402 entry of accepts and send the same request again with the payment header. |
| payment_refused | 402 | x402: the payment was refused before settlement (reason: signature, amount, nonce, balance…). | Fix what reason names, sign a new payment from this answer's accepts and send the request again. |
| payment_failed | 402 | x402: the settlement transaction failed on chain; nothing was charged. | Sign a new payment from this answer's accepts (another network if it keeps failing). |
| forbidden | 403 | The request is not allowed for this caller. | Check message; another key or another call is needed. |
| account_frozen | 403 | x402: the paying wallet's account is frozen by its owner: the payment was credited, no key was issued. | The account owner unfreezes it at https://femtos.xyz/accounts/. |
| demo_pass_refused | 403 | The portal demo pass does not allow this call (GET only, femtos.xyz only, the sample's addresses only). | Use a free key to ask about anything else. |
| not_found | 404 | The route exists, the thing asked does not: unknown token, coin, market, launch, pool, collection or entity. | Check the identifier (layer, address, coin name); list endpoints (/v1/coins, /v1/markets, /v1/launches) give valid ones. |
| route_not_found | 404 | No route at this path. | Check the path against https://api.femtos.xyz/v1/openapi.json (REST lives under /v1/). |
| payload_too_large | 413 | The request body is over 64 KiB. | Send a smaller body. |
| rate_limited | 429 | Over the rate limit: the key's rps / burst (X-RateLimit-*), a keyless IP's, or a paying wallet's. | Wait retryAfter seconds (Retry-After) and retry; a key of a higher tier has higher limits. |
| too_many_connections | 429 | WebSocket upgrade refused: this key already holds its maxConns open connections. | Close a connection, or subscribe to more channels on one (64 per connection). |
| too_many_subscriptions | WS frame | WebSocket: this connection already holds 64 subscriptions. | Unsubscribe from one first, or open another connection. |
| demo_pass_exhausted | 429 | The portal demo pass is used up (calls, WebSockets) or no pass is left for now. | Get a free key; retryAfter, when present, says when a pass is available again. |
| internal_error | 500 | An unexpected error on our side. | Retry later; if it persists, quote request_id to support. |
| upstream_error | 502 | A source behind the API (database, node, stream) answered with an error. | Retry with backoff; if it persists, quote request_id to support. |
| 503 | The source of this layer cannot answer now (database, table or snapshot missing, server down, layer not configured). | Retry later; GET /v1/status shows each layer. | |
| syncing | 503 | The source is still syncing and cannot answer this call yet (order book syncing). | Retry after Retry-After seconds. |
| not_ready | 503 | An answer computed in the background is not there yet (the process just started). | Retry after retryAfter seconds (Retry-After). |
| server_busy | 503 | Too many heavy queries or WebSocket tickets waiting: the request was not queued. | Retry after retryAfter seconds (Retry-After). |
| 503 | x402: our payment verification could not run (chain or facilitator unreachable); nothing was charged. | Send the same request with the same payment header again after Retry-After. | |
| payment_pending | 503 | x402: the payment was broadcast or settled, its crediting is not finished (error: settlement_pending or credit_pending). | Send the same request with the same payment header again after Retry-After: it is never charged twice. |
Markdown: this page as Markdown · JSON: errors.json · agents.md.