An error is JSON with a stable code and a detail, one plain sentence that says what happened. Branch on code; the sentence may be reworded.
{"detail": "That is not a live RandomTranslator API key. Send the whole key, which starts with rtk_, as the header \"Authorization: Bearer <key>\".", "code": "invalid_key"}
Some carry more: a 429 adds scope, retry_after_seconds, resets_at, limit and used; a merged novel adds the novel_id that replaced it. A 422 for a malformed parameter is the framework's own shape, {"detail": [{"loc": [...], "msg": "...", "type": "..."}]}, with no code.
| Status | Code | Meaning | What to do |
|---|---|---|---|
| 401 | invalid_key |
The bearer is not a live key or token: unknown, mistyped, revoked, expired, or the account signed out everywhere or was suspended. Comes with WWW-Authenticate: Bearer. |
Check the header is Authorization: Bearer rtk_.... If it is, create a new key. An OAuth app refreshes its token, or signs the reader in again. |
| 401 | auth_required |
Creating, listing or revoking a key without being signed in to the site. | Sign in on the site; key routes take the session cookie, never a key. |
| 403 | membership_required |
The key's account is not on the Reader membership or higher, or its pledge is not active. | Renew the membership. The key works again within a minute, unchanged. |
| 403 | insufficient_scope |
An OAuth app's token was not granted this route's permission. | Ask the reader to connect again with the permission. Personal keys never get this. |
| 403 | account_too_new |
Creating a key: the account is less than a day old. | Try again tomorrow. |
| 404 | none | No such novel or record. | Check the id. It still costs its units. |
| 404 | not_found_merged |
The novel was merged into another; the answer carries its novel_id. |
Use the new id from now on. |
| 404 | not_found_taken_down |
The novel was taken down. | Drop it. |
| 409 | key_limit |
Creating a key: the account already has 3 live keys. | Revoke one first. |
| 410 | not_found_deleted |
The novel was deleted for good. | Drop it. |
| 422 | none, or invalid_name |
A parameter is out of range or malformed (limit=500), or a key name is empty or over 40 characters. |
Fix the request. It cost nothing. |
| 429 | rate_limited |
Over the key's units for this minute (or too many bad keys from one address). | Wait Retry-After seconds. |
| 429 | daily_limit |
The key's units for the day are spent, or 10 keys were created today. | Wait for resets_at (00:00 UTC). |
| 503 | none | Creating a key: keys are switched off for now ("API keys are switched off for now"), with Retry-After: 300. |
Try again later. |
| 503 | api_disabled |
The API is paused to protect the site. | Wait Retry-After seconds and try again. |
| 500 | internal_error |
A fault on our side. | Wait a moment and retry a few times with a growing pause. It cost nothing. |
| 5xx | none | Another fault on our side, or the site in front of us. | The same: retry with a growing pause. It cost nothing. |
A request refused with 401, 403, 422, 429 or 503 costs no units.
Connector errors#
The connector answers a tool error as one sentence with isError: true, which the assistant reads and acts on: an unknown novel, a bad input, a missing permission, a limit, or a lapsed membership ("RandomTranslator's connector needs the Reader membership or higher"). Without a token, /mcp answers 401 with WWW-Authenticate: Bearer resource_metadata="https://randomtranslator.com/.well-known/oauth-protected-resource/mcp", which is what starts the sign-in. A paused connector answers 503.