Skip to main content
Every error response from the API is JSON. There are two shapes: Catcher errors (auth, billing, routing, body parsing) return a structured object:
Endpoint-specific failures (a contract revert, an execution error) return a JSON string with the error message and the matching HTTP status:
Robust clients should branch on the HTTP status code first and treat the body as diagnostic detail.

Status codes

Billing guarantees on errors

  • Failed requests are not charged. The flat $0.01 management charge settles only after the operation succeeds. A request rejected for a bad body (400/422), missing permission (403), or a server error (5xx) costs nothing.
  • An invalid key is a 401, not a 402. You will only ever see 402 Payment Required for an account that actually exists and is short on credits.
  • Billing outages are a 503, not a 402. If Stripe or the chain RPC is unreachable, the API tells you to retry — it does not tell you to pay.

Failed actions return 500

If your Lit Action throws, /lit_action returns 500 with the action’s error in the message, even though retrying the same request won’t fix it. A successful response always has has_error: false, so check the status code to detect a failed action. When the contract refuses a management call because the key lacks permission, every write endpoint returns 403 with the body "Permission denied". Check the key’s scopes with GET /core/v1/list_api_keys before you retry.

Common sequences

“/lit_action returns 403.” The message is “The provided API key is not authorized to execute the specified action”. The key needs execute permission in a group that lists this exact code’s CID, or a wildcard ([0]) execute grant. Check three things: that you sent a usage key (the account key can’t run actions), that the key’s execute_in_groups includes the group, and that the CID you registered matches the code you sent. Changing the code by one character changes its CID. See Run lit-action. “/lit_action returns 400 with ‘No cached code found’.” You sent ipfs_id without code. The server runs code by CID only if it has already received that code and still has it cached. It does not fetch code from IPFS. Send the code itself. “I created an account but every call says 402.” New accounts start with no credits. Running Lit Actions and write/metered management calls (creating wallets, groups, usage keys) consume credits; read-only calls (list_*, account_exists, billing/balance) are free. Add funds to proceed. “My key worked yesterday and now I get 401.” The key was removed (remove_usage_api_key) or you’re sending a truncated value. Keys are shown once at creation; verify with GET /core/v1/account_exists and mint a new usage key from your account key if needed. “The error body isn’t JSON.” It is, as of API version v1.2. If you see an HTML error page you are talking to something other than the API (a proxy, a wrong URL) — check the host and path.