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