Universally Documentation

Step-by-step guides, multilingual SEO tips, and best practices to help you translate and scale your WordPress website.

API errors and limits

Full API reference: developer.universally.com carries the live specification for both the Translator API and the Platform API, with every field, status code and response example. This page covers what is worth knowing around it.

Every response uses the same envelope, so a client branches on the code field rather than on the HTTP status alone.

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 configured for your site, or you sent a region code where a variant code is required.
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.
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.
INTERNAL_SERVER_ERROR 500 Unexpected server error. Safe to retry with backoff.

Request limits

Limit Value
Maximum request body 5 MB
Maximum strings per request 500 (strings endpoint)
Allowed methods GET, POST, OPTIONS

The 5 MB limit applies to the bytes you send, so a gzipped body is measured compressed. If it is exceeded you receive REQUEST_TOO_LARGE (413). For large pages or large string sets, compress the body or 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. Because the size limit counts the bytes you send, compressing is what lets a document several times larger than 5 MB through.

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 draws down your plan's word total, shared across the HTML and strings endpoints.

Being over the limit is not an error. There is no status code for it: an over-limit workspace still gets a 200, with the shortfall reported in the metadata. The limit is checked once, when the request arrives, so a request that starts under the limit finishes everything it needs, even if that takes it past the total.

Field Meaning
limitReached true when the workspace was already at or over its word total when the request arrived.
skippedStrings The number of strings left untranslated because of that.

When limitReached is true, treat the response as partial. Anything already translated is still returned from storage; anything that would have needed a new translation is not. On the HTML endpoint that text stays in the source language in the returned document. On the strings endpoint those keys are absent from the translations map, so fall back to your own source text for any key you do not get back. See Translate strings.

Raise the total with a word add-on or a larger plan. See Usage limits.

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.

Was this helpful?