Errors
Every error has a stable code. Build against the code, not the message.
The error envelope
When /v1 can't handle a request, it returns a 4xx or 500 status with this body:
JSON
{
"error": {
"code": "rate_limited",
"message": "Rate limit exceeded",
"request_id": "REQUEST_ID",
"doc_url": "DOC_URL"
}
}| Field | Meaning |
|---|---|
code | A stable code from the table below. |
message | A sentence for people to read. It can change. |
request_id | This request's ID. |
doc_url | A link to this code's row in the table below. |
When a run fails
A run that starts and then fails isn't an envelope. Its code reaches you in one of these places:
| Where | Field |
|---|---|
A 200 from POST /v1/extract | error.code, with ok: false |
A failed job from GET /v1/extract/:jobId | error_code |
An item from GET /v1/batch/:batchId | error_code |
A job.failed webhook | data.error.code |
So check ok on a 200, and status on a job. See Extraction for the full error object, including error.retryable.
Every code
A row that gives a status arrives in the envelope. A row with no status reaches you as a failed run, as above. A row marked Dashboard only comes from the dashboard's own pages and never from /v1.
| Code | What it means | What to do |
|---|---|---|
invalid_url | The url isn't a YouTube video URL or video ID, the formats list is empty, or lang is malformed. | Fix the request. Sending it unchanged returns the same code. |
video_not_found | The video doesn't exist, or it's no longer on YouTube. | Check the video ID. |
video_access_restricted | The video is private, age-restricted, limited by region or for members only. | Use a video that's publicly available. |
unsupported_media | The video is a live stream or a broadcast still in progress. | Try again after the broadcast ends, or use a different video. |
no_captions | Clypso found no captions for this video, and it doesn't transcribe audio. | Use a video with captions. error.retryable can be true here, but don't retry in a loop. |
provider_unavailable | Clypso couldn't fetch the transcript, because the services it gets captions from failed or timed out. | Try again in a few minutes. |
llm_output_truncated | The generated result was cut off before it finished, so none of it is returned. | Don't retry in a loop, since error.retryable is false. You can try the video again later. |
llm_output_invalid | The generated result failed validation, so none of it is returned. | Don't retry in a loop, since error.retryable is false. You can try the video again later. |
spend_ceiling_reached | Daily capacity, shared by everyone using the service, has been reached. New extractions pause until 00:00 UTC. | Try again after 00:00 UTC. Cached results keep working. See Usage and quota. |
internal_error | Something went wrong on Clypso's side. The message is a fixed sentence with no details. It can also arrive as a 500, and a job whose attempts ran out reports it. | Try again. If it keeps happening, check Status. |
video_too_long | The video is longer than the maximum length. | Use a shorter video. |
quota_exceeded | Your account has used its monthly limit. A batch that needs more videos than you have left gets a 429. | Wait for the monthly reset. Cached results keep working. |
invalid_api_key | A 401: the API key is missing, malformed, unknown or revoked. | Send a valid key as a Bearer token. Manage your keys at API Keys. |
rate_limited | A 429: this key went over its request limit, or a batch would put too much queued work on your account. | Wait the number of seconds in Retry-After. See Rate limits. |
invalid_request | A 400: the body is malformed JSON, has an unknown field, or a value failed validation. | Fix the request. Sending it unchanged returns the same code. |
idempotency_key_reused | A 409: this Idempotency-Key was already used with a different body. | Use a new key for a different request. |
request_in_progress | A 409: the first request with this Idempotency-Key is still running. | Wait, then send it again with the same key. |
job_not_found | A 404: no job with this ID exists on your account. Another account's job looks the same. | Check the job_id, and that the key is from the account that created the job. |
transcript_not_found | A 404: the token is valid, but no transcript text is stored for this ID. | Use the result without its transcript. The rest of it isn't affected. |
invalid_signed_url | A 401: the transcript link's token is expired, altered or for another transcript, or your key is from another account. | Get a new link. |
batch_too_large | A 400: the batch has more URLs than your limit, so all of it is rejected. | Split it into smaller batches. |
invalid_batch_item | A 400: at least one URL isn't a YouTube video, so all of the batch is rejected. The message lists the indexes. | Fix or remove those URLs, then send the batch again. |
batch_not_found | A 404: no batch with this ID exists on your account. Another account's batch looks the same. | Check the batch_id, and that the key is from the account that created the batch. |
watch_limit_reached | Dashboard only: adding this channel would go over your watch list limit. | Remove a channel first. |
webhook_limit_reached | Dashboard only: adding this endpoint would go over your webhook endpoint limit. | Delete an endpoint first. |
channel_not_found | Dashboard only: what you entered doesn't lead to a channel. | Check the channel's handle or URL. |
invalid_webhook_url | Dashboard only: the endpoint URL is malformed, isn't HTTPS or points to a private address. | Use a publicly reachable HTTPS URL. See Webhooks. |
feature_not_configured | Dashboard only: this feature isn't available right now. | Try again later. |
not_found | Dashboard only: the item doesn't exist, or it belongs to another account. | Reload the page to see what's still there. |