error.code field gives you a stable identifier to branch on in your code.
The error envelope
Every error response shares the same shape: anerror object with a machine-readable code and a human-readable message.
error.code, not on message. Messages are written for humans and may change; codes are part of the contract.
Some errors add fields alongside error at the top level of the body. For example, a 402 insufficient_words response includes your current balance and the words_required for the request:
Error reference
| Status | Code | When it happens | Extra fields |
|---|---|---|---|
400 | bad_request | The request body was not valid JSON. | — |
400 | validation_error | A field failed schema validation, including a rejected webhook_url. | — |
400 | word_limit_exceeded | text exceeds the 2,000-word limit. | — |
401 | unauthorized | The API key is missing, invalid, expired, or revoked, or lacks the humanize scope. | — |
402 | insufficient_words | Your word balance cannot cover the request. | balance, words_required |
404 | not_found | No job with that id exists on your account. | — |
409 | idempotency_conflict | An Idempotency-Key was reused with a different request body within 24 hours. | existing_job_id, expires_at |
413 | payload_too_large | The request body is over 128,000 bytes. | — |
429 | rate_limited | You exceeded the per-key rate limit (20 POST/min, 120 GET/min). | retry_after_seconds, reset_at |
429 | too_many_concurrent_jobs | You have more than 5 active jobs at once. | active_jobs, limit |
500 | enqueue_failed | The job was created but could not be enqueued. Reserved words are refunded automatically. | — |
429 codes also send a Retry-After header. The 401 unauthorized response does not include rate-limit headers.
Per-code detail
400 bad_request
400 bad_request
The request body could not be parsed as JSON. Check for trailing commas, unquoted keys, or a missing
Content-Type: application/json header. Fix the body before resending; retrying the same payload returns the same error.400 validation_error
400 validation_error
A field is missing or has the wrong type or value. This also covers a
webhook_url that is rejected for not being HTTPS, not being publicly reachable, containing embedded credentials, or resolving to a private or loopback address. Correct the field and resend.400 word_limit_exceeded
400 word_limit_exceeded
text is over the 2,000-word limit for a single request. Split the input into smaller chunks and submit them as separate jobs.401 unauthorized
401 unauthorized
402 insufficient_words
402 insufficient_words
Your balance cannot cover the request. The body includes your current
balance and the words_required. Buy more API words, then resend. See Words and billing.404 not_found
404 not_found
No job with the given id exists on your account. Check the id, and confirm you are using the same account that submitted the job. Job ids are scoped to the account that created them.
409 idempotency_conflict
409 idempotency_conflict
You reused an
Idempotency-Key with a different request body within the 24-hour retention window. The body includes the existing_job_id that the key is already bound to and its expires_at. Use a fresh key for a new request, or resend the original body. See Idempotency.413 payload_too_large
413 payload_too_large
The request body is over the 128,000-byte limit. This can happen before the word limit is reached if the text contains many multi-byte characters. Reduce the body size and resend.
429 rate_limited
429 rate_limited
You exceeded the per-key rate limit (20 POST per minute, 120 GET per minute). The body includes
retry_after_seconds and reset_at, and the response carries a Retry-After header. Wait, then retry. See Rate limiting.429 too_many_concurrent_jobs
429 too_many_concurrent_jobs
You have more than 5 active jobs at once. The body includes
active_jobs and limit, and the response carries a Retry-After header with a value of 10. Wait for jobs to finish, then submit again.500 enqueue_failed
500 enqueue_failed
The job was created but could not be enqueued for processing. Reserved words are refunded automatically, so you are not charged. This is transient; retry the submission after a short delay.
Handling guidance
Sort errors into two groups: those that are safe to retry as-is, and those that need a change to the request before it can succeed.Safe to retry
These are transient. Retry the same request after waiting.429 rate_limitedand429 too_many_concurrent_jobs— back off and retry. Honor theRetry-Afterheader. See Rate limiting.500 enqueue_failed— the reserved words were refunded, so a retry does not double-charge you. Retry after a short delay.
Needs a change
Retrying these without changing the request returns the same error. Fix the cause first.400 bad_request/validation_error/word_limit_exceeded— correct the body: fix the JSON, the failing field, or split text that is over 2,000 words.401 unauthorized— fix authentication: use an active key with thehumanizescope.402 insufficient_words— buy more API words, then resend. See Words and billing.409 idempotency_conflict— use a freshIdempotency-Key, or resend the original body for that key. See Idempotency.404 not_found— check the job id and the account.413 payload_too_large— reduce the request body below 128,000 bytes.
Rate limiting
The API enforces 20POST /humanize requests per minute and 120 GET /humanize/{id} requests per minute, per key. A separate limit caps you at 5 active jobs at once.
When you exceed a limit, the response is 429 with a Retry-After header giving the number of seconds to wait before retrying. Rate-limited responses also include these headers:
| Header | Meaning |
|---|---|
Retry-After | Seconds to wait before the next request. |
X-RateLimit-Limit | The request ceiling for the current window. |
X-RateLimit-Remaining | Requests left in the current window. |
X-RateLimit-Reset | When the window resets, as an ISO 8601 timestamp. |
Recommended backoff
ReadRetry-After and wait at least that long before retrying. If the header is absent, fall back to exponential backoff with jitter — for example, start at one second and double the delay on each attempt, adding a small random offset so concurrent clients do not retry in lockstep. To stay under the limit in the first place, watch X-RateLimit-Remaining and slow down as it approaches zero.
Reading rate-limit headers
Example bodies
Related
Words and billing
How reservations, charges, and refunds work, and what
insufficient_words means for your balance.Idempotency
Retry submissions safely and avoid
idempotency_conflict.