Hear2Text

Errors

One envelope for every refusal, a stable code to branch on, and a request id to quote when you ask us about it.

The envelope

Every refusal on this surface has the same two keys, whatever raised it. There is no second error shape to handle.

Any 4xx or 5xx
{
  "error": "insufficient_scope",
  "message": "This key does not carry the scope this endpoint needs.",
  "required": "transcriptions:write"
}
  • error is the stable, machine-readable code. Branch on this.
  • message is written for a person reading a log. Do not parse it — the wording may change at any time.
  • Some refusals add a field: errors on a validation failure, required on a scope refusal, docs on the gating 403s.

The catalogue

Every code the API can answer with. This list is generated from the same OpenAPI document the API is tested against, so it cannot drift from the running code.

HTTPerrorMeaning
401missing_api_keyNo Authorization header. Send `Authorization: Bearer h2t_live_…`.
401invalid_api_keyUnreadable, unknown or revoked key — or a credential from another surface. Not retryable.
403subscription_requiredThe account has no active subscription. The key is kept and will work again once it does.
403insufficient_scopeThe key does not carry the scope this route needs. The body names it. Create a key with the scope.
403account_restrictedThe account has been restricted. Contact support.
403guest_account_not_supportedA guest account cannot use the API.
403workspace_scope_mismatchThis key is pinned to one workspace and the recording lives in another.
403forbiddenAllowed to ask, not allowed to do this to this recording.
404not_foundNo such recording, or not one this key can see. The two are deliberately indistinguishable.
409concurrency_limitToo many recordings running at once for this plan. Wait for one to finish and retry.
409idempotency_key_reusedThis Idempotency-Key was used for a different request body. Use a new key.
409idempotency_request_in_progressThe first request with this key has not answered yet. Retry in a few seconds.
409transcription_still_processingA recording that has not finished — still queued or processing — cannot be deleted. Wait for it to complete or fail.
409transcription_is_not_readyOnly a completed recording can be exported.
413file_too_largeThe request body is over what the server accepts at all. Compress the recording, or split it. A file that arrives but is over the per-file ceiling is a `validation_failed` naming `file` instead.
400bad_requestThe request could not be read as HTTP we understand. Not retryable as sent.
405method_not_allowedThat path exists, but not for this HTTP method. Check the reference.
422validation_failedThe request could not be accepted as sent. `errors` names each field.
422uploaded_file_cannot_be_processedThe upload did not reach storage intact. Retry with a fresh Idempotency-Key.
422playlist_not_acceptableThat link is a playlist. Send one recording at a time.
429rate_limitedToo many requests, or today’s create allowance is spent. Wait Retry-After seconds.
500internal_errorOur fault. Retry with backoff; if it persists, quote the X-Request-Id.
503service_unavailableThe API is briefly down, usually for a deploy. Retry after Retry-After seconds, or shortly.

Validation errors

A 422 carries an errors map: the field, and every message about it.

422 Unprocessable Entity
{
  "error": "validation_failed",
  "message": "The request could not be accepted as sent.",
  "errors": {
    "url": ["Send either a `file` or a `url`."],
    "language": ["Unknown language code. GET /languages lists the ones we accept."]
  }
}

Request ids

Every response — including every error — carries X-Request-Id. Send your own and we echo it; send nothing and we generate one. It is in our logs beside the request, so quoting it in a support conversation saves everybody a day.

What to retry

StatusRetry?
401, 403, 404, 413, 422No. Nothing about waiting changes the answer — fix the request or the key.
409Yes, after a pause. A concurrency ceiling clears as recordings finish; an in-flight idempotency key resolves in seconds.
429Yes, after Retry-After seconds. Not sooner.
5xxYes, with exponential backoff — and with the same Idempotency-Key if it was a create, so you do not pay twice for one recording.