MLXDocs
Resources

Errors

Markdown

Every public endpoint reports an error the same way, a JSON object with an error message and an HTTP status. This page lists the statuses the API uses and where each one comes from.

The format

json
{ "error": "Block not found" }
  • One field, error: a short English sentence meant to be shown to a person. A few errors add a field that helps you recover (a witness cosignature refused as too old also returns last, the size it last cosigned).
  • The status code carries the meaning. Branch on the status, not on the text: messages are reworded from time to time.
  • Never cached. Error responses carry Cache-Control: no-store, so a retry always reaches the server.
  • CORS headers are set on errors too, so a page on another site can read them.

A path that matches no route isn't an API error: it gets the site's HTML 404 page. Check the Content-Type before parsing.

When a 200 still means no

Some answers are successful requests that say something didn't or wouldn't happen. Check for these in the body:

EndpointWhat to check
POST /api/txThe record's status. A transaction that was valid enough to sequence but broke a ledger rule is sealed with status: "failed" and an error, and the call answers 200. See Submitting.
GET /api/market/quoteerror is not null: the ledger would refuse that swap (too small, not enough balance, not enough liquidity). See Market.
GET /api/name/{name}available: false with a reason.
GET /api/search{ "to": null }: nothing matched.

Status codes

StatusMeaningWhere it comes from
400The request is wrongA path or query value that can't be used: a block height that isn't a whole number, a quote without side or with an amount that isn't whole base units. A body that isn't JSON (POST /api/tx says "Body must be JSON: { tx }"). A transaction the sequencer rejects before sequencing it: malformed, too large (this is a 400, not a 413), a wrong chain, a timestamp too far from network time, a wrong nonce, a name that can't be registered, and the other checks on Submitting. On MLX Node's routes: an unknown job or a result without its output hash.
401The request isn't signed, or the signature doesn't checkPOST /api/tx: a transaction not signed by its wallet's own key ("This transaction isn't signed by luca.mlx's key."). MLX Node's routes (/api/worker/*, /api/log/cosign) need the x-mlx-device header: missing, malformed, a bad signature, or a Mac clock too far from the server's. Wallet-signed routes (the MLX.app companion API and the distributor portal) need x-mlx-auth: "Unlock your wallet to continue".
403Signed, but not allowedA Mac that isn't linked to a wallet sending a result ("Link this Mac to your wallet first"); a witness cosignature whose signature doesn't match; a checkout refusing a request (checkout not open on this network).
404Nothing thereA block, transaction, account, key, seat or checkpoint that doesn't exist: "Block not found", "Transaction not found", "Account not found", "No account uses this key", "Seat not found".
409It conflicts with what already happenedMLX Node's routes: a signed request sent twice ("Request already used"), a result for a job this Mac wasn't handed, a second result for the same job, a result faster than the job can run, a cosignature older than the Mac's last one.
413The body is too largeMLX Node's routes and wallet-signed routes refuse bodies over their size cap.
429Too many requestsA rate limit. Wait and retry; see Rate limits.
500Something failed on the serverAnything unexpected while reading or writing the ledger. The message is the underlying error (on /api/token, /api/compute and /api/compute/work cut to a short line; MLX Node's routes just say "Server error"). Safe to retry.
503A source is downGET /api/market/aapl when market data can't be fetched.

Retrying

  • 400, 401, 403, 404, 413: don't retry the same request; fix it first.
  • 409: read the message. A replayed signed request needs a fresh signature; a withdrawal that can't be paid now can be tried again later.
  • 429: wait until the limit's window has passed (most are per minute).
  • 500, 503: retry with a backoff.
  • Transactions are safe to resend: the ledger keys a transaction by its hash, so sending the same signed transaction again returns the record it already has and changes nothing.