Updated 2026-10-19
Turn public media links into transcripts from your own tools and AI agents.
Create an API key on your account page, then submit a public link. Every request carries the key as a Bearer token, and the task spends the same Credits and runs on the same pipeline as the website.
curl -X POST https://videoscript.uk/v1/transcriptions \
-H "Authorization: Bearer vs_live_..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 6f1c2b8e-..." \
-d '{"source_url": "https://www.youtube.com/watch?v=..."}'The answer is 202 Accepted with the task id, a Location header and a Retry-After hint. Poll that task, then read the finished transcript or export it:
curl https://videoscript.uk/v1/transcriptions/<id> \
-H "Authorization: Bearer vs_live_..."
curl "https://videoscript.uk/v1/transcriptions/<id>/export?format=markdown" \
-H "Authorization: Bearer vs_live_..."Reuse one Idempotency-Key per submission: retrying the same request with the same key and the same body returns the same task instead of creating a second one (a different body is refused). Without the header, each request creates a new task.
The command-line client wraps the same endpoints:
npm install -g videoscript
videoscript auth login --token vs_live_...
videoscript transcribe create https://www.youtube.com/watch?v=... --wait
videoscript transcript get <id> --format srt --output talk.srtEvery request carries Authorization: Bearer vs_live_…. The full key value is shown once, when you create it; only its prefix stays visible afterwards. A key that is missing, unknown, revoked or expired always answers 401 api_key_invalid — a request is never silently treated as anonymous.
Each key carries three scopes, checked on every request:
transcriptions:write — submit a new transcription.transcriptions:read — read a task, its transcript and its exports.credits:read — read the account's Credits balance.A key can also carry its own Credits budget. Once the key has spent it — counting the Credits reserved by tasks that are still running — further submissions are refused with 403 api_key_budget_exceeded and nothing is charged. The account balance still applies on top, so a key can never spend more than the account has.
Failures answer the stable machine code, a safe message and whether a retry can help: {"errorCode": "...", "errorMessage": "...", "retryable": false}.
| Code | What it means | Retry |
|---|---|---|
invalid_request (400) | The request body or a query parameter is not valid. When the answer names a field, that field is the problem. | No |
api_key_invalid (401) | The key is missing, unknown, revoked or expired. | No |
api_key_scope_denied (403) | The key does not carry the scope this endpoint needs. | No |
api_key_budget_exceeded (403) | The key has reached its own Credits budget. | No |
insufficient_credits (402) | The account does not have enough Credits for the media. | No |
unsupported_platform, private, paid, drm, region (422) | The link is not public content we may process: unsupported source, login-only, paid, DRM-protected or region-blocked. There is no workaround to configure. | No |
not_found (404) | No such task for this account — a task that belongs to another account answers the same code. | No |
not_completed (409) | The task has not finished yet; the transcript is not ready. | Yes — keep polling |
rate_limited, too_many_active (429) | More requests than the per-key limits allow, or this key already has a task running. | Yes — wait for Retry-After |
provider_unavailable (502), queue_full (503) | A temporary failure on our side or upstream. | Yes — wait for Retry-After |
Limits are per key in a fixed 60-second window: 5 submissions and 20 reads per minute, and one task running at a time. A request over a limit answers 429 — or 503 when the queue is full — with Retry-After in seconds; sending the same request again earlier is refused. Credits are only charged for finished work, and a task refused by any of these gates charges nothing.
Questions about the API: [email protected].