Concept
Asynchronous transcription jobs
Understand 202 responses, polling, and terminal transcription states.
Lifecycle
- 01
Create once
POST one source. Save the job ID and Location header from the 202 response.
- 02
Retrieve repeatedly
GET the job-specific resource with a bounded delay between requests.
- 03
Resolve locally
On completed, store the result. On failed, store the error and stop.
States
| Field | Type | Description |
|---|---|---|
processing | non-terminal | Media resolution or transcription is still running. |
completed | terminal | Text and available segments can be read. |
failed | terminal | Processing stopped and data.error contains a message. |
Polling
async function waitForJob(location, token) {
const deadline = Date.now() + 15 * 60_000;
let delay = 2_000;
while (Date.now() < deadline) {
let response;
try {
response = await fetch(`https://fast-transcriber.com${location}`, {
headers: { Authorization: `Bearer ${token}` }
});
} catch {
await new Promise((resolve) => setTimeout(resolve, delay));
delay = Math.min(Math.round(delay * 1.5), 10_000);
continue;
}
const payload = await response.json();
if (!response.ok) {
if (response.status >= 500) {
await new Promise((resolve) => setTimeout(resolve, delay));
delay = Math.min(Math.round(delay * 1.5), 10_000);
continue;
}
throw new Error(`${payload.error?.code ?? response.status}: ${payload.error?.message ?? "Request failed"}`);
}
const { data } = payload;
if (["completed", "failed"].includes(data.status)) return data;
await new Promise((resolve) => setTimeout(resolve, delay));
delay = Math.min(Math.round(delay * 1.5), 10_000);
}
throw new Error("Polling timed out");
}Webhooks are not part of v1
Design integrations around polling. A local timeout does not mean the server-side job stopped.
Recovery
- Persist the job ID before starting a background polling loop.
- Retry a failed GET after transient transport errors; do not repeat the creation POST.
- Use list-transcriptions to recover recent IDs, then fetch an individual job for its result.