Appearance
Errors
Failed requests return JSON in a consistent envelope:
json
{
"error": {
"code": "unauthorized",
"message": "Authentication required",
"details": null
}
}details is optional and may contain validation or chain context when available.
Common codes
| HTTP | Code | When |
|---|---|---|
| 400 | bad_request | Invalid body, params, or general client error |
| 401 | unauthorized | Missing/invalid session or API key |
| 402 | insufficient_credits | Not enough credits for a paid action |
| 403 | forbidden | Authenticated but not allowed (e.g. upgrade, ownership) |
| 404 | not_found | Unknown route or resource |
| 409 | conflict | Resource conflict (e.g. duplicate) |
| 502 | chain_error | Onchain / RPC failure after the API attempted a write |
Unknown routes also use 404 / not_found with message Route not found.
Validation errors
Request bodies are validated with Zod. Invalid payloads typically surface as 400 with a clear message (and sometimes structured details).
Tips
- Treat
402as a billing signal: top up or wait for plan renewal before retrying paid ops. - Treat
502/chain_erroras retryable only after checking chain status; do not assume credits were spent. - For auth issues, confirm you are sending either
Authorization: Bearer mtk_.../mts_...or themintea_sessioncookie — not both incorrectly (Bearer is tried first). - Sandbox keys (
mts_) never return402for create/mint; live keys on Fuji still do if the (cheaper) balance is too low. See Sandbox.