Poll a transcription job safely

Follow the Location header with bounded backoff and stop cleanly at terminal states.

Reliable polling without duplicate transcription jobs

Create once, persist the job ID, and retrieve that job until it completes or fails. Transient network failures should repeat the GET—not the original POST.

Persist first

Associate the API job ID with your application record.

Back off

Space status checks rather than polling in a tight loop.

Stop once

completed and failed are terminal states.

Separate failures

HTTP errors and a later failed job need different handling.

From request to transcript

A predictable sequence you can reuse in server applications, automations, and internal tools.

  1. 01

    Read Location

    Capture the relative URL from the create response.

  2. 02

    GET the job

    Use the same bearer key and a bounded delay between checks.

  3. 03

    Resolve your record

    Save the result on completed or the error on failed.

Make the request

Examples use the production API origin and an environment variable for the secret key.

Implementation
async function waitForTranscription(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 (data.status === "completed" || data.status === "failed") return data;
    await new Promise((resolve) => setTimeout(resolve, delay));
    delay = Math.min(Math.round(delay * 1.5), 10_000);
  }

  throw new Error("Timed out waiting for transcription");
}
Keep credentials server-side
Never expose a Fast Transcriber API key in public browser JavaScript, a mobile bundle, source control, or a prompt.

Requirements and boundaries

  • Do not repeat POST /transcriptions to check progress.
  • Use a maximum wait time appropriate for your application.
  • Stop polling terminal jobs.
  • Treat network errors as retriable separately from data.status = failed.

Frequently asked questions

Does Fast Transcriber send webhooks?+

Not in the current v1 API. Use polling for job completion.

Should a timeout create a new job?+

No. Preserve the job ID and continue retrieving it later.

Does the list endpoint include transcript text?+

No. Fetch the individual job for completed text and segments.

© 2026 FastTranscriberBuilt for developers who work with speech.