Errors
Errors use a consistent envelope with a machine-readable code:
{ "error": { "code": "not_found", "message": "No public video found at that URL. It may be private or deleted.", "status": 404 }, "request_id": "req_01JZX4M8Q2TE9W"}Always log request_id — quote it in support requests and we can trace the exact
call.
Error codes
| Status | Code | When |
|---|---|---|
| 400 | invalid_request | Missing/malformed url, handle, or query |
| 401 | unauthorized / invalid_key | Bad or missing API key |
| 402 | insufficient_credits | Credit balance too low for the call |
| 403 | forbidden | Key lacks access to the endpoint |
| 404 | not_found | Content is private, deleted, or the URL resolves to nothing |
| 409 | job_conflict | Duplicate async job submission |
| 422 | unprocessable | URL parsed but the content type is unsupported (e.g. transcript of an image post) |
| 429 | rate_limited | Plan rpm exceeded — honor Retry-After |
| 5xx | upstream_error / internal | Transient fetch failure — safe to retry |
Retry guidance
import httpx, time
for attempt in range(3): r = httpx.get(url, headers=headers, timeout=120) if r.status_code == 429: time.sleep(int(r.headers.get("Retry-After", "2"))) continue if r.status_code >= 500: time.sleep(2 ** attempt) continue breakFailed calls that return an error are not charged — credits are only deducted when data comes back.
Next: Rate limits · Output formats