Skip to main content

Overview

The speech-to-text endpoints run for as long as the media is long. A synchronous request holds the HTTP connection open for the whole download and transcription — reliable for short clips, not for long ones: clients, reverse proxies and marketplace gateways all time out. That is why every speech-to-text endpoint has an async twin. You submit the job, get a task_id back immediately, and collect the result by polling or through a webhook.
Synchronous calls are limited to 10 minutes of media. Longer media is rejected with 400 video_too_long. Use the async endpoints for anything that may run past 10 minutes — they have no duration cap, and they work just as well for short videos.

Which endpoint to use

Each async endpoint accepts exactly the same body as its synchronous counterpart, plus an optional webhook_url. The result you get back is identical to the synchronous response’s data block, so the same parsing code works for both.
If you don’t know the video’s duration in advance, just use the async endpoint every time. There is no extra cost.
TikTok profile scrape and TikTok keyword search are async by design and follow the same polling and webhook model.

How it works

1

Submit the job

POST to the async endpoint. The API validates the request and returns 202 Accepted with a task_id and a check_status_url.
2

Wait for the result

Either poll check_status_url every few seconds while task_status is processing, or pass a webhook_url (or configure a default one in Studio → API) and get called back when the job finishes.
3

Read the result

When task_status is completed, data.result holds the result. When it is failed, data.error carries the error code and HTTP status the synchronous endpoint would have returned.

1. Submit the job

Accepted response (202)

2. Poll for the result

Polling is free — the GET endpoints consume no credits. A few seconds between polls is plenty.

Job states

Completed response

Failed response

The poll request itself returns 200 even when the job failed — check task_status. data.error uses the same codes as the synchronous endpoint, so existing error handling can be reused unchanged. See Errors.

Retention

  • Results are kept for 1 hour after the job finishes (not from submission), so even a long transcription leaves a full hour to collect it.
  • Reading a task does not consume or delete it — re-read the same task_id as often as you like until it expires.
  • After expiry, the poll endpoint returns 404 task_not_found.

Webhooks instead of polling

Pass webhook_url on the submit request, or configure an account-level default endpoint in Studio → API. The per-request value wins; pass "webhook_url": "" to opt a single job out of the default. See the full contract — payload, signature verification, retries — in the Webhooks guide.
Webhooks are best effort. Treat polling as the source of truth: if a callback never arrives, the result is still available on check_status_url.

Billing

Billing is identical to the synchronous endpoint — the async mode costs nothing extra — and happens in the background worker.
  • include_usage is not accepted on the submit endpoint (the 202 fires before any charge is made). Pass include_usage=true on the poll endpoint instead: it replays the final charges once task_status=completed.
  • A failed job has all of its charges reverted.
  • Polling is free.
See Usage & Costs for unit prices.

Submit-time errors

These are returned by the POST itself; no task is created.

Migrating from synchronous calls

  1. Switch the URL: /transcribe/transcribe/async, /extract/video/extract/video/async, /tweet/statement/tweet/statement/async. Keep the same body.
  2. Remove include_usage from the submit body and pass it as a query parameter on the poll endpoint if you need it.
  3. Poll check_status_url (or receive the webhook) and read data.result — it has the same shape as the synchronous data block.
  4. Map data.error.error to your existing error handling.