Error reference
All error responses follow a standard JSON envelope with a detail field.
Error envelope
{ "detail": "Human-readable error message" }For validation errors (FastAPI 422), the response body contains an array:
{
"detail": [
{
"loc": ["path", "language"],
"msg": "field required",
"type": "value_error.missing"
}
]
}HTTP status codes
| Status | Name | When it occurs |
|---|---|---|
200 OK | Success | Request processed successfully |
401 Unauthorized | Invalid API key | Key missing, malformed, or revoked |
403 Forbidden | Wrong project | Key is valid but belongs to a different project |
404 Not Found | Resource not found | Language, group, or key doesn't exist |
402 Payment Required | Plan limit reached | Project/key/language limit or monthly translation-unit quota exceeded |
422 Unprocessable Entity | Validation error | Path or query parameter validation failed |
429 Too Many Requests | Rate limit exceeded | Daily quota exhausted (beyond grace zone) |
500 Internal Server Error | Server error | Unexpected error; safe to retry once |
503 Service Unavailable | Dependency failure | DB or Redis unreachable |
401 Unauthorized
{ "detail": "Invalid API key" }Common causes:
X-API-Keyheader missing or misspelled- Key was revoked in the portal
- Key copied with leading/trailing whitespace
404 Not Found
{ "detail": "Translation not found" }Common causes:
- Language code doesn't match any published language (check
/v1/manifest) - Group or key doesn't exist, or it exists but is in
draftstatus (notapproved) - S3 cache hasn't been rebuilt yet after adding a new language
402 Payment Required
Two distinct causes share this status code:
Plan limit reached (projects, keys per project, or languages per project) — thrown by the portal API when creating a resource would exceed your plan's limits:
{ "detail": "Project limit reached for your plan" }Monthly translation-unit quota exceeded — thrown by POST /cli/sync and the portal's AI-translate endpoints once you've used up to 2x your plan's monthly quota:
{
"detail": {
"code": "QUOTA_EXCEEDED",
"used": 42000,
"limit": 20000,
"reset_date": "2026-09-01",
"upgrade_url": "https://app.i18nme.com/billing"
}
}Translation memory hits (unchanged strings) never count against quota — see the CLI guide for how sync diffs against what's already been translated. Resolution: upgrade your plan, or wait for the quota to reset at the start of your next billing cycle.
429 Too Many Requests
{ "detail": "Rate limit exceeded: 11100/10000 requests today" }Response headers:
| Header | Example value | Description |
|---|---|---|
Retry-After | 86400 | Seconds until midnight UTC reset |
X-RateLimit-Limit | 10000 | Your plan's daily limit |
Resolution: Switch to cached endpoints to share quota more efficiently, or upgrade your plan.
503 Service Unavailable
{ "status": "degraded", "db": "error", "redis": "ok" }This is only returned from the /health endpoint. All other endpoints return 500 when a dependency is degraded.
Retry guidance
| Status | Retry? | How |
|---|---|---|
401 | No | Fix the API key |
403 | No | Check you're using the right key for this project |
404 | No | Check key/group/language exists and is approved |
429 | After reset | Use Retry-After header to know when |
500 | Yes, once | Wait 1–2 s, then retry once |
503 | Yes, with backoff | Exponential backoff, 3 attempts |