This page documents the error format, the full list of response codes, request limits, and how plan usage affects translation.
Response envelope
Every response, success or error, uses the same JSON envelope:
{
"success": false,
"data": null,
"message": "Invalid source URL format.",
"code": "TRANSLATION_INVALID_SOURCE_URL"
}
On error, success is false and data is null. Branch on the code field rather than the human-readable message, which may change.
Error codes
| Code | HTTP | Meaning |
|---|---|---|
API_KEY_MISSING | 401 | No X-API-Key header was provided. |
API_KEY_INVALID_FORMAT | 401 | The key is not a recognized format. |
API_KEY_MALFORMED | 401 | The key could not be parsed. |
API_KEY_INVALID | 401 | The key is well-formed but not recognized. |
API_KEY_PROJECT_INCOMPLETE | 500 | The site tied to this key is misconfigured. Contact support. |
PROJECT_NOT_FOUND | 404 | No site matches this key. |
PROJECT_IS_DELETED | 404 | The site has been deleted and is no longer accessible. |
TRANSLATION_INVALID_SOURCE_URL | 400 | sourceUrl is not a valid URL. |
TRANSLATION_SOURCE_URL_DOMAIN_MISMATCH | 403 | sourceUrl does not match your site’s domain. |
TRANSLATION_SAME_LANGUAGE | 400 | The target language equals the source language. |
TRANSLATION_TARGET_LANGUAGE_NOT_ALLOWED | 403 | The target language is not enabled for your site. |
TRANSLATION_NO_LANGUAGES_CONFIGURED | 400 | No target languages are configured for the site. |
TRANSLATION_SERVICE_UNAVAILABLE | 503 | The translation service is temporarily unavailable. Retry with backoff. |
TRANSLATION_SERVICE_FAILED | 500 | The translation service failed to process the request. |
NO_TRANSLATABLE_CONTENT | 400 | No translatable content was found in the HTML. |
PLAN_LIMIT_REACHED | 403 | Your plan’s word allowance is exhausted. |
VALIDATION_ERROR | 400 | The request body failed schema validation. |
INVALID_JSON | 400 | The request body is not valid JSON. |
DECOMPRESSION_ERROR | 400 | A gzip body could not be decompressed. |
REQUEST_TOO_LARGE | 413 | The request body exceeds 5 MB. |
NOT_FOUND | 404 | Unknown route. |
Request limits
| Limit | Value |
|---|---|
| Maximum request body | 5 MB |
| Maximum strings per request | 500 (strings endpoint) |
| Allowed methods | GET, POST, OPTIONS |
If the body exceeds 5 MB you receive REQUEST_TOO_LARGE (413). For large pages or large string sets, split the work across multiple requests.
Compressed request bodies
The Translator accepts gzip-compressed request bodies. Set the Content-Encoding header to gzip and send the compressed JSON; the body is decompressed before parsing. This is useful for large HTML documents that approach the 5 MB limit.
Content-Type: application/json
Content-Encoding: gzip
If decompression fails, the response is DECOMPRESSION_ERROR (400).
Cross-origin requests
The Translator returns permissive CORS headers, allowing requests from any origin with the Content-Type, X-API-Key, and Content-Encoding headers. Even so, requests carry your API key and should be sent server-side. See Authentication.
Plan usage and partial translations
Translation consumes your plan’s word allowance, shared across the HTML and strings endpoints. Usage is enforced per request rather than by rejecting the whole call:
- If your allowance is exhausted before a request arrives, the request fails with
PLAN_LIMIT_REACHED(403). - If the allowance runs out partway through a request, Universally translates as much as it can, returns a successful response, and reports the shortfall in the metadata.
Two metadata fields describe this:
| Field | Meaning |
|---|---|
limitReached | true when the word allowance was hit during the request. |
skippedStrings | The number of strings left in the source language because the limit was reached. |
When limitReached is true, treat the response as partial: translated content is returned where possible, and untranslated strings fall back to their original text. Upgrade your plan to raise the allowance.
Retries
For transient errors (TRANSLATION_SERVICE_UNAVAILABLE at 503, or any 5xx), retry with exponential backoff. Translations are cached, so retried requests that previously partially succeeded reuse existing work and only translate what is still missing. Do not retry 4xx errors; they indicate a problem with the request that will not resolve on its own.