Specala AIDocs

Errors & rate limits

HTTP status codes the Specala AI API returns (401, 403, 422, 429, 5xx), the JSON error shape, what triggers each one, and how to handle rate limits.

The API uses standard HTTP status codes. 2xx means success; 4xx means something about the request needs fixing.

Status codes

StatusMeaningTypical cause
200OKRequest succeeded.
201CreatedKey created (management).
204No ContentKey revoked (management).
401UnauthorizedMissing/invalid/expired key, or key passed in the URL.
402Payment RequiredNo plan minutes left (uploads).
403ForbiddenPlan without API access (api_access_denied), or key without upload permission (upload_scope_required).
404Not FoundResource doesn't exist in your workspace.
408Request TimeoutUpload stalled or took too long.
409ConflictSame Idempotency-Key still in flight.
411Length RequiredUpload without Content-Length.
413Payload Too LargeFile over the 2 GB upload limit.
422Unprocessable EntityInvalid parameter (e.g. bad format, too many ids).
429Too Many RequestsRate limit or an upload cap exceeded.
5xxServer errorTransient — retry with backoff.

Error shape

Most errors return a JSON body with a detail field. Plan/access errors include a machine-readable code:

403 Forbidden
{
  "detail": {
    "code": "api_access_denied",
    "message": "Your current plan does not include API access. Please upgrade to a plan with API & MCP support."
  }
}
401 Unauthorized
{
  "detail": "Invalid API key"
}

Common cases

What you seeWhyFix
401 on every callKey revoked, expired, or has a trailing spaceCreate a fresh key, copy carefully
401 with a key in the query stringKeys in URLs are rejected by designMove the key to the Authorization header
403 api_access_deniedPlan without API & MCPUpgrade to Pro or Expert
404 on a known IDThe transcription is in another workspaceUse a key for that workspace
422 on exportformat isn't md/txt, or ids is empty/over 100Fix the parameter

Upload & delete errors

Upload a file and Delete transcription return machine-readable codes in detail.code. Branch your code on the code, not the message text:

CodeStatusMeaningWhat to do
unsupported_file_format400Extension not supportedCheck the format list
file_too_small400Under 1 KBNot a real recording
filename_required400No Content-Disposition headerAdd the header
insufficient_balance402No minutes leftTop up, upload again
upload_scope_required403Key has no upload permissionCreate a key with Allow file uploads
delete_scope_required403Key has no delete permissionCreate a key with Allow deleting transcriptions
upload_timeout408Stream stalled / over 90 minCheck the connection, retry
idempotency_conflict409Same Idempotency-Key still uploadingWait Retry-After, retry
length_required411No Content-LengthUse a client that sets it
file_size_limit_exceeded413Over 2 GBSplit or compress the file
too_many_concurrent_uploads429Parallel-upload capWait Retry-After, retry
too_many_queued_files429100+ files awaiting processingQueue is draining — wait, retry
upload_quota_exceeded429Daily anti-abuse capRetry after UTC midnight or contact support
export_quota_exceeded429Daily export volume capRetry after UTC midnight or contact support
uploads_temporarily_disabled503Uploads switched offTemporary — retry later

Transient (408, 429, 5xx) → retry with backoff. Everything else → fix the request; retrying won't help. Never re-send a file after a 201 — that creates a second, billed transcription.

Rate limits

Limits are per key:

SurfaceLimit
Data endpoints (list / get / export / bulk)500 requests / minute
Export volume10 GB / day
File uploads60 requests / minute, 10 concurrent per key
Deletions30 requests / minute
Key management180 requests / minute

When you exceed a limit you get 429. Handle it gracefully:

  • Back off, don't retry immediately. Wait a few seconds and try again.
  • Avoid tight loops. To export many transcriptions, use Bulk export (one request) instead of looping over single exports.
  • Spread work out rather than firing hundreds of calls at once.

Don't auto-retry on 429 instantly

Immediate automatic retries make the limit worse. Use exponential backoff (e.g. 1s, 2s, 4s).

On this page