Resources
Errors
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
{ "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 returnslast, 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:
| Endpoint | What to check |
|---|---|
POST /api/tx | The 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/quote | error 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
| Status | Meaning | Where it comes from |
|---|---|---|
| 400 | The request is wrong | A 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. |
| 401 | The request isn't signed, or the signature doesn't check | POST /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". |
| 403 | Signed, but not allowed | A 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). |
| 404 | Nothing there | A 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". |
| 409 | It conflicts with what already happened | MLX 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. |
| 413 | The body is too large | MLX Node's routes and wallet-signed routes refuse bodies over their size cap. |
| 429 | Too many requests | A rate limit. Wait and retry; see Rate limits. |
| 500 | Something failed on the server | Anything 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. |
| 503 | A source is down | GET /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.