# API error codes · Femtos

> 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.

- Base URL: `https://api.femtos.xyz/v1` (REST) · `wss://api.femtos.xyz/v1/ws` (WebSocket) · MCP: `https://api.femtos.xyz/mcp`
- Auth: `Authorization: Bearer $FEMTOS_KEY`. Free key: https://femtos.xyz/accounts/ (browser), or with
  no browser: `GET https://femtos.xyz/accounts/agent/challenge`, solve its proof of work, then `POST https://femtos.xyz/accounts/agent/signup`
  (https://femtos.xyz/agents.md#agent-onboarding)
- Decimals are exact strings, times Unix milliseconds, addresses lowercase `0x`
- Whole API in one file: https://femtos.xyz/agents.md · OpenAPI: https://api.femtos.xyz/v1/openapi.json · Index: https://femtos.xyz/llms.txt
- Page with live calls: https://femtos.xyz/errors

## Errors

Every error body, REST, WebSocket frame or MCP tool error, is JSON with the same fields:

```json
{"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"}
```

- `code`: stable, branch on it (the table below). `error` keeps the text older clients match on (`unauthorized`,
  `rate limit exceeded`…); `message` says what is wrong; `param` names the parameter of an `invalid_param` when known.
- `request_id`: 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 in your logs; quote it to support.
- `429` and the `503`s that know when carry `Retry-After` (seconds) and `retryAfter` in the body: wait that long, then
  retry. Never retry a `400` unchanged: fix the call.
- WebSocket: error frames carry the same fields (plus `channel`, `filter`), `request_id` being the upgrade's; the
  connection stays open. A refused upgrade answers the HTTP body. MCP: a tool error (`isError`) carries the REST body.
- x402: `error` is the x402 reason (`invalid_exact_evm_signature`…) as the protocol wants; `code` says
  `payment_required`, `payment_refused` or `payment_failed`.

| Code | HTTP | Meaning | What to do |
| --- | --- | --- | --- |
| <a id="invalid_request"></a>`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. |
| <a id="invalid_param"></a>`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. |
| <a id="invalid_payment"></a>`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. |
| <a id="unauthorized"></a>`unauthorized` | 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. |
| <a id="invalid_ticket"></a>`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. |
| <a id="demo_pass_expired"></a>`demo_pass_expired` | 401 | The portal demo pass of this visitor expired. | Reload the page for a new pass, or use a free key. |
| <a id="payment_required"></a>`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. |
| <a id="payment_refused"></a>`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. |
| <a id="payment_failed"></a>`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). |
| <a id="forbidden"></a>`forbidden` | 403 | The request is not allowed for this caller. | Check `message`; another key or another call is needed. |
| <a id="account_frozen"></a>`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/. |
| <a id="demo_pass_refused"></a>`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. |
| <a id="not_found"></a>`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. |
| <a id="route_not_found"></a>`route_not_found` | 404 | No route at this path. | Check the path against https://api.femtos.xyz/v1/openapi.json (REST lives under /v1/). |
| <a id="payload_too_large"></a>`payload_too_large` | 413 | The request body is over 64 KiB. | Send a smaller body. |
| <a id="rate_limited"></a>`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. |
| <a id="too_many_connections"></a>`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). |
| <a id="too_many_subscriptions"></a>`too_many_subscriptions` | WS frame | WebSocket: this connection already holds 64 subscriptions. | Unsubscribe from one first, or open another connection. |
| <a id="demo_pass_exhausted"></a>`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. |
| <a id="internal_error"></a>`internal_error` | 500 | An unexpected error on our side. | Retry later; if it persists, quote `request_id` to support. |
| <a id="upstream_error"></a>`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. |
| <a id="source_unavailable"></a>`source_unavailable` | 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. |
| <a id="syncing"></a>`syncing` | 503 | The source is still syncing and cannot answer this call yet (order book syncing). | Retry after Retry-After seconds. |
| <a id="not_ready"></a>`not_ready` | 503 | An answer computed in the background is not there yet (the process just started). | Retry after `retryAfter` seconds (Retry-After). |
| <a id="server_busy"></a>`server_busy` | 503 | Too many heavy queries or WebSocket tickets waiting: the request was not queued. | Retry after `retryAfter` seconds (Retry-After). |
| <a id="payment_unavailable"></a>`payment_unavailable` | 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. |
| <a id="payment_pending"></a>`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. |

Also as a page: https://femtos.xyz/errors · Markdown: https://femtos.xyz/errors.md · JSON: https://femtos.xyz/errors.json
