Errors¶
All public errors share the same envelope:
{
"ok": false,
"contractVersion": "v1",
"error": {
"code": "string",
"message": "human-readable"
}
}
Catalog¶
| HTTP | error.code |
When |
|---|---|---|
| 400 | invalid_json |
Request body is not valid JSON |
| 400 | invalid_email |
request-key email is empty or malformed |
| 400 | invalid_schema |
Unknown field, wrong type, or unsupported alias |
| 400 | unsupported_plan |
Public key issuance requested a non-free plan |
| 401 | api_key_required |
A keyed endpoint was called without X-API-Key |
| 401 | invalid_api_key |
X-API-Key is unknown or inactive |
| 404 | not_found |
Endpoint path does not exist |
| 413 | payload_too_large |
Request body exceeds the transport limit |
| 413 | too_many_items |
pieces or sheets exceed hard parser limits |
| 415 | unsupported_media_type |
Request is not application/json |
| 422 | validation_failed |
Domain validation failed after parsing |
| 429 | rate_limit_exceeded |
Hosted daily or monthly quota has been exhausted |
| 500 | internal_error |
Unexpected server-side failure |
Validation errors¶
When error.code is validation_failed, the envelope also includes error.validationErrors.
{
"ok": false,
"contractVersion": "v1",
"error": {
"code": "validation_failed",
"message": "Input validation failed",
"validationErrors": [
{
"code": "InvalidDimension",
"fieldPath": "pieces[0]",
"message": "Piece width must be positive"
}
]
}
}
Quota failures¶
429 rate_limit_exceeded responses include additional quota metadata:
{
"ok": false,
"contractVersion": "v1",
"error": {
"code": "rate_limit_exceeded",
"message": "Current plan quota has been exhausted for this period",
"plan": "free",
"limitKind": "daily",
"limit": 25,
"period": "2026-04-30"
}
}
Retry guidance¶
| Code | Retry? |
|---|---|
| 4xx except 429 | No - fix the request |
| 429 | Yes - retry in a new quota period or with a different valid key |
| 5xx | Yes - exponential backoff, then surface an operational error |