본문으로 건너뛰기

Error Reference

This is the single source of truth for every error the Theta One API can return. All endpoints — /transcribe, /analyze-native, /pronunciation, /pronunciation-simple — share the codes below.

On failure, the API returns:

  • an HTTP status code from the table below, and
  • a JSON body containing an error message.

Error code summary

HTTPCode stringRetry?CategoryWhen it happens
400Bad RequestNoClientMalformed request: invalid JSON in options, missing gold_text, invalid audio, NotAllWordsSpokenError, etc.
401UnauthorizedNoClientMissing / incorrect / inactive / expired API key.
402PAYMENT_REQUIREDNoBillingOut of credits or plan doesn't include the endpoint being called.
429RATE_LIMIT_EXCEEDEDYes — with backoffQuotaPer-key RPM exceeded.
500INTERNAL_SERVER_ERRORYes — limited retriesServerUnexpected server-side failure.

Detailed entries below.


400 — Bad Request

The server could not accept the request as sent. Not retryable until the request is fixed.

The response body is always {"detail": "<message>"}. Branch on the message string:

detail stringRoot causeFix
"Invalid options format. Must be a valid JSON string."options / transcribe_options was not valid JSONWrap the object with json.dumps(...)
"Invalid options: <...>"JSON parsed but failed Pydantic validationCheck option field names and types
"gold_text is required"options did not include gold_text (pronunciation endpoints)Add gold_text to the options JSON
"Invalid native_speech_components_json format. Must be a valid JSON string."native_speech_components_json was not valid JSONPass json.dumps(speech_components_array)
"Invalid native_speech_components format"JSON parsed but shape didn't match the FormattedWord | FormattedPause schemaUse the exact speech_components returned by /analyze-native; don't mutate fields
"Not all words are spoken."NotAllWordsSpokenError — student's audio does not cover every word in gold_textRe-prompt the user to re-record
"Invalid audio format"Audio file is missing, empty, or not decodableSend a real .wav or .mp3

Agent tip: Do not auto-retry any 400. For "Not all words are spoken.", re-prompt the user rather than retrying silently.


401 — Unauthorized

The API key was rejected. Response body is {"detail": "<message>"}.

Possible detail strings:

detailRoot cause
"Invalid API key"x-api-key header missing, malformed, not prefixed sk-theta-, or not found in the database
"API key is not active, please check your API key..."Key exists but has been deactivated or its Expires At has passed

Fix: Verify the key in the API Console. If you suspect a leak, deactivate it immediately and issue a new key.

Do not auto-retry 401 — you will just waste quota.


402 — PAYMENT_REQUIRED

Billing-related refusal. Two distinct root causes share this code — branch on the detail string:

detailRoot causeFix
"Insufficient credits, please check your credit balance"Prepaid credit balance is zero (or would go negative)Top up, or move to an Enterprise postpaid contract
"This feature requires a Starter plan or higher..."Pronunciation endpoint called from a Free-plan accountUpgrade the plan at console.thetaone.co/billing

Pronunciation endpoints (/analyze-native, /pronunciation, /pronunciation-simple) are allowed only on starter, pro, enterprise plan tiers.

Agent tip: Don't retry 402. Surface the billing reason to the user and link them to Pricing or Prepaid Credits.


429 — RATE_LIMIT_EXCEEDED

You exceeded the per-API-key RPM quota. Response body: {"detail": "Rate limit exceeded. Please try again later."}.

PlanRPM
Free30
Starter100
Pro500
EnterpriseUnlimited (by contract)

The limit resets within a short time window, so a few seconds of backoff is usually enough to recover.

Recommended reaction: Exponential backoff with jitter. Full guidance: Rate Limits & Retries.


500 — INTERNAL_SERVER_ERROR

Server-side failure, not caused by your request. Response body: {"detail": "Internal server error"}.

Recommended reaction:

  • Retry up to 2–3 times with exponential backoff.
  • If the error persists, email support@thetaone.co with:
    • the timestamp (UTC) of the failing request,
    • the API key you used (the sk-theta- prefix is enough — never send the full key outside of HTTPS support),
    • a minimal reproduction if possible.

Related statuses you may occasionally see:

  • 413 Payload Too Large — the upload is too big. Shrink the file.
  • 504 Gateway Timeout — upload + processing did not complete within the request timeout. Shorten the audio or check network throughput.

Named errors

NameEndpoint(s)Detail stringMeaning
NotAllWordsSpokenError/analyze-native, /pronunciation, /pronunciation-simple"Not all words are spoken."The audio does not cover every word in gold_text. Ask the speaker to re-record the full sentence.

Minimal error-handling recipe (Python)

import time
import requests

def post_with_retry(url, *, headers, files=None, data=None, max_retries=3):
backoff = 1.0
for attempt in range(max_retries):
r = requests.post(url, headers=headers, files=files, data=data, timeout=30)

if r.status_code == 200:
return r.json()

# Non-retryable client errors — fail fast.
if r.status_code in (400, 401, 402):
raise RuntimeError(f"{r.status_code} {r.text}")

# Retryable.
if r.status_code in (429, 500, 502, 503, 504):
if attempt == max_retries - 1:
raise RuntimeError(f"{r.status_code} after {max_retries} attempts: {r.text}")
time.sleep(backoff)
backoff *= 2
continue

# Anything else — don't retry silently.
raise RuntimeError(f"Unexpected {r.status_code}: {r.text}")