API Error Codes

Stable type URLs for developer API problem+json responses. Full reference in API docs → Error Codes.

CodeHTTPDescription
MISSING_API_KEY401No Authorization header provided
INVALID_API_KEY_FORMAT401Key doesn't start with htai_live_
INVALID_KEY_FORMAT401Alias of INVALID_API_KEY_FORMAT — malformed key shape (hash length / prefix) from key validation RPC
INVALID_KEY401Key not found or has been revoked
KEY_EXPIRED401Key has expired (rotated)
UNKNOWN_ERROR401Rare auth-path failure when key validation did not return a more specific code. Retry once; if it persists, rotate the key or contact support.
UNAUTHORIZED403Caller is not authorized for this operation
NO_ACTIVE_SUBSCRIPTION403No active API plan on the account (gateway auth path)
NO_SUBSCRIPTION403No developer-surface subscription row for this user (billing reservation path; distinct from NO_ACTIVE_SUBSCRIPTION)
PLAN_NOT_FOUND403Subscription plan_key has no matching plan_configs row
BANNED403Account is suspended
RISK_BLOCKED403Account restricted due to unusual activity
TURNSTILE_REQUIRED403Additional verification required before the request can proceed
SCOPE_DENIED403API key missing a required permission (humanize, detect, or tones). Enable it under Permissions or create a new key.
MODE_NOT_AVAILABLE403Requested mode not included in current plan
ENDPOINT_NOT_AVAILABLE403Endpoint not included in current plan
STREAMING_NOT_AVAILABLE403SSE streaming not included in current plan
DETECTION_NOT_AVAILABLE403AI detection not included in current plan
IP_NOT_ALLOWED403Request IP not in key's allowlist
RATE_LIMITED429Rate limit exceeded — respect Retry-After and retry
CONCURRENT_LIMIT429Too many in-flight humanize/detect requests for your plan concurrent cap. Wait for one to finish, then retry.
MISSING_TEXT400No text field in request body
INVALID_TEXT400Text failed validation: under 20 words, empty after normalize, disallowed characters, or blocked injection/code patterns
INVALID_JSON400Request body is not valid JSON
TEXT_TOO_LONG400Text exceeds plan's maximum words per request (see GET /v1/usage → plan.max_words_per_request)
INVALID_MODE400Unknown humanization mode
INVALID_TONE400Tone is malformed. Use a built-in name, the exact custom tone name, or the tone UUID.
INVALID_BEST_OF400best_of is not an integer between 1 and 5
INVALID_ID400Tone id path parameter must be a UUID
NO_FIELDS400Tone PUT body has no updatable fields (name and/or instructions required)
INVALID_WORD_COUNT400Word count argument to billing reservation is missing or ≤ 0
INVALID_MULTIPLIER400Cost multiplier argument to billing reservation is missing or < 1
BEST_OF_NOT_AVAILABLE403best_of above 3 requires the Scale plan
LEGACY_PROMPT_REMOVED400Legacy "prompt" field is no longer supported — use "text"
INVALID_NAME400Custom tone name missing or not 1–50 characters after sanitization
INVALID_INSTRUCTIONS400Custom tone instructions missing or not 1–500 characters after sanitization
INJECTION_DETECTED400Custom tone field contains blocked injection/code patterns
INVALID_IDEMPOTENCY_KEY400Idempotency-Key header is malformed (must be 1–128 chars of A-Z a-z 0-9 _ - : .)
IDEMPOTENCY_KEY_CONFLICT409Idempotency-Key was already used under a different API key, user, or endpoint. Use a unique key per job.
RETRY_REQUIRED409This Idempotency-Key was already consumed but no stored result is available (expired or original attempt refunded). Mint a new key and retry.
INVALID_FREEZE_WORDS400freeze_words is not an array, has more than 100 entries, or an entry exceeds 100 characters.
TONE_NAME_CONFLICT409A custom tone with that name already exists for this account (case-insensitive).
TONE_NAME_RESERVED400Custom tone name collides with a built-in tone (casual, formal, professional, academic, creative).
INSUFFICIENT_WORDS402Not enough word balance — carries words_required and words_remaining extension fields
RESERVATION_FAILED500Word reservation could not complete — retry. Not a payment or balance error.
TONE_NOT_FOUND404No custom tone matches that name or UUID. List tones with GET /v1/tones or copy from the Custom Tones page.
TONE_LIMIT_REACHED403Custom tone quota for the current plan has been reached.
NOT_FOUND404Unknown path
METHOD_NOT_ALLOWED405Path exists; HTTP method not supported (see Allow header)
INVALID_CONTENT_TYPE415Content-Type must be application/json on write requests
PAYLOAD_TOO_LARGE413Request body exceeds the 128 KiB JSON body limit
VALIDATION_FAILED400Request failed validation (generic developer validation path)
CLIENT_CANCELLED499Detect-only on developer API: client disconnected before /v1/detect completed — not charged / refunded. /v1/humanize cancels collapse to AI_GENERATION_FAILED.
AI_TIMEOUT504Not emitted on developer /v1/humanize (collapsed to AI_GENERATION_FAILED 500). Detect timeouts collapse to DETECTION_FAILED. Present in internal classification / consumer paths.
AI_UNAVAILABLE503All AI providers unavailable — not charged / refunded
ABORTED504Request aborted mid-flight (AbortError) before a typed AI failure was classified
INTERNAL_ERROR500Unexpected server error
AI_GENERATION_FAILED500Humanize AI processing failed on /v1/humanize (timeouts, cancels, and generic AI failures collapse here) — not charged / refunded
DETECTION_FAILED500Detection processing failed on /v1/detect (non-cancel AI failures, including timeouts, collapse here) — not charged / refunded

← Back to API documentation