Dashboard

Quickstart

Transcribe audio with one API call.

Create an API key in the dashboard, send an audio file to POST /v1/transcribe, and read the transcript from the JSON response.

1. Sign up

Create an account and verify your email.

2. Create a key

Open the dashboard and create an API key.

3. Send audio

Upload audio as multipart form data.

First request
curl -X POST https://api.transcribeapi.com/v1/transcribe \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "file=@audio.mp3" \
  -F "language=en" \
  -F "model=whisper-large-v3-turbo" \
  -F "vtt_granularity=sentence"

SDKs

Use the SDK when you want uploads, async jobs, polling, and batches handled for you.

The SDKs expose the same API surface as REST, but choose the right upload flow automatically and return plain JSON objects.

Python

pip install transcribe-api

Python SDK
from transcribe_api import TranscribeAPI

client = TranscribeAPI(api_key="YOUR_API_KEY")

result = client.transcribe(
    file="meeting.mp3",
    language="en",
    vtt_granularity="sentence",
)

print(result["text"])

npm

npm install @transcribe-api/sdk

Node.js SDK
import { TranscribeAPI } from "@transcribe-api/sdk";

const client = new TranscribeAPI({ apiKey: "YOUR_API_KEY" });

const result = await client.transcribe({
  file: "meeting.mp3",
  language: "en",
  vttGranularity: "sentence",
});

console.log(result.text);

Uploads

Local file paths and remote signed URLs are supported by the SDKs.

Batch helper

client.batch.transcribe() creates the job, uploads files, and returns a job id.

Resume and retry

The Node.js SDK can resume multipart uploads from local path uploads.

Sync transcription

POST /v1/transcribe returns the transcript in the HTTP response.

Use sync when the caller should wait for the transcript. Send one audio file as multipart form data.

Field Type Required Description
file File Yes Audio file in multipart form data.
model String No Model id. Defaults to whisper-large-v3-turbo.
language String No Language code such as en. Omit for auto-detect.
task String No transcribe or translate.
vad_filter Boolean No Set to true to filter non-speech sections.
initial_prompt String No Context for names, acronyms, product terms, or vocabulary.
vtt_granularity String No sentence or word.
exclude String No Comma-separated fields to omit from the response.

Supported language codes

Pass one of these values in language, or omit the field to auto-detect.

Afrikaans (af), Amharic (am), Arabic (ar), Assamese (as), Azerbaijani (az), Bashkir (ba), Belarusian (be), Bulgarian (bg), Bengali (bn), Tibetan (bo), Breton (br), Bosnian (bs), Catalan (ca), Czech (cs), Welsh (cy), Danish (da), German (de), Greek (el), English (en), Spanish (es), Estonian (et), Basque (eu), Persian (fa), Finnish (fi), Faroese (fo), French (fr), Galician (gl), Gujarati (gu), Hausa (ha), Hawaiian (haw), Hebrew (he), Hindi (hi), Croatian (hr), Haitian Creole (ht), Hungarian (hu), Armenian (hy), Indonesian (id), Icelandic (is), Italian (it), Japanese (ja), Javanese (jw), Georgian (ka), Kazakh (kk), Khmer (km), Kannada (kn), Korean (ko), Latin (la), Luxembourgish (lb), Lingala (ln), Lao (lo), Lithuanian (lt), Latvian (lv), Malagasy (mg), Maori (mi), Macedonian (mk), Malayalam (ml), Mongolian (mn), Marathi (mr), Malay (ms), Maltese (mt), Myanmar (my), Nepali (ne), Dutch (nl), Norwegian Nynorsk (nn), Norwegian (no), Occitan (oc), Punjabi (pa), Polish (pl), Pashto (ps), Portuguese (pt), Romanian (ro), Russian (ru), Sanskrit (sa), Sindhi (sd), Sinhala (si), Slovak (sk), Slovenian (sl), Shona (sn), Somali (so), Albanian (sq), Serbian (sr), Sundanese (su), Swedish (sv), Swahili (sw), Tamil (ta), Telugu (te), Tajik (tg), Thai (th), Turkmen (tk), Tagalog (tl), Turkish (tr), Tatar (tt), Ukrainian (uk), Urdu (ur), Uzbek (uz), Vietnamese (vi), Yiddish (yi), Yoruba (yo), Chinese (zh), Cantonese (yue)

Response
{
  "job_id": "job_...",
  "billed_seconds": 600,
  "price_per_hour": 0.15,
  "cost": 0.025,
  "remaining_balance": 152.4758,
  "text": "The full transcript...",
  "vtt": "WEBVTT\\n\\n00:00.000 --> 00:04.120\\n...",
  "segments": [
    {
      "id": 0,
      "start_seconds": 0,
      "end_seconds": 4.12,
      "text": "The first sentence."
    }
  ],
  "detected_language": "en"
}
Error shape
{
  "error": "Attach an audio file in the `file` field.",
  "code": "missing_file"
}

Async jobs

Use jobs when transcription should run in the background.

Async jobs support direct uploads and remote signed URLs. Create the job, upload or import audio, then poll the job or receive a webhook.

Create job POST /v1/jobs Upload audio or import URL Poll or webhook Get result URL
Uploaded file job
{
  "type": "big_file",
  "size_bytes": 157286400,
  "content_type": "audio/mpeg",
  "model": "whisper-large-v3-turbo",
  "webhook_url": "https://example.com/transcribe-webhook"
}
Remote URL job
{
  "type": "big_file",
  "source": {
    "type": "url",
    "url": "https://storage.example.com/audio.mp3?signature=..."
  },
  "model": "whisper-large-v3-turbo",
  "webhook_url": "https://example.com/transcribe-webhook"
}
Step Endpoint Use
Create POST /v1/jobs Create a big_file job.
Resume POST /v1/jobs/{job_id}/resume-upload Refresh upload instructions for an active upload.
Status GET /v1/transcribe/{job_id} Poll job metadata and status.
Upload complete POST /v1/transcribe/{job_id}/upload-completed Start processing after all uploads for the job have finished.
Create job response
{
  "job_id": "job_123",
  "status": "uploading",
  "total_files": 1,
  "uploads": [
    {
      "reference_id": "file_000001",
      "upload": {
        "type": "put",
        "url": "https://...",
        "headers": {}
      }
    }
  ]
}
Job status response
{
  "job_id": "job_123",
  "job_status": "queued",
  "billed_seconds": 0,
  "cost": 0,
  "total_files": 1
}
Result response
{
  "job_id": "job_123",
  "status": "completed",
  "billed_seconds": 709,
  "price_per_hour": 0.15,
  "cost": 0.029542,
  "remaining_balance": 4.970458,
  "result_url": "https://...",
  "expires_at": "2026-06-04T12:00:00.000Z"
}
Resume upload response
{
  "job_id": "job_123",
  "upload": {
    "type": "multipart",
    "key": "usr_123/job_123/audio.mp3",
    "upload_id": "4~VJ...",
    "part_size": 5242880,
    "parts": [
      {
        "part_number": 1,
        "url": "https://..."
      }
    ],
    "complete_url": "https://...",
    "abort_url": "https://..."
  }
}

Job status values

Jobs move through a finite set of status values. The API returns these raw values from GET /v1/transcribe/{job_id}.

Status Meaning Terminal
uploading Client upload is still in progress. No
verifying Uploaded or imported audio is being validated and prepared for transcription. No
queued Job is ready and waiting for transcription execution. No
completed Job finished and webhook delivery succeeded or no webhook was configured. Yes
completed_with_errors Batch job finished with per-file failures, and the result is available. Yes
result_available Job finished, but webhook delivery did not succeed. Fetch the result manually. Yes
result_available_with_errors Batch job finished with per-file failures and webhook delivery did not succeed. Yes
failed_* Terminal failure during upload validation, import, probing, verification, billing reconciliation, or result finalization. Yes

Poll GET /v1/transcribe/{job_id}. When status becomes completed, the response includes result_url.

Public terminal failure values use the failed_* pattern. Examples include failed_batch_file_count_mismatch, failed_batch_size_mismatch, failed_batch_too_large, failed_batch_total_size_mismatch, failed_insufficient_credits, failed_manifest_mismatch, failed_missing_batch_file, failed_result_missing, failed_source_missing, failed_unsupported_batch_format, failed_upload_missing, and failed_upload_size_mismatch.

Batch jobs

Use batch jobs to transcribe many audio files together.

Batch is async only. The SDK is the simplest path because it creates the manifest, uploads files, and returns the job id.

Node.js batch
const batch = await client.batch.transcribe({
  files: [
    { reference_id: "episode_1", file: "episode-1.mp3" },
    { reference_id: "episode_2", file: "episode-2.wav" },
  ],
  webhookUrl: "https://example.com/transcribe-webhook",
});

const job = await client.jobs.get(batch.job_id);
const resultUrl = job.result_url ?? null;
Remote batch
{
  "type": "batch",
  "files": [
    {
      "reference_id": "file_000001",
      "url": "https://storage.example.com/one.mp3?signature=..."
    }
  ],
  "webhook_url": "https://example.com/transcribe-webhook"
}

Manual uploads

After creating a batch job, call POST /v1/jobs/{job_id}/upload-urls for upload URLs.

Remote files

Use signed HTTPS URLs when files already live in S3, R2, GCS, or another storage provider.

Results

Use the webhook payload or poll GET /v1/transcribe/{job_id} until result_url is returned.

Upload URLs response
{
  "job_id": "job_123",
  "uploads": [
    {
      "file_id": "file_000001",
      "filename": "episode-1.mp3",
      "key": "usr_123/job_123/file_000001.mp3",
      "upload": {
        "type": "put",
        "key": "usr_123/job_123/file_000001.mp3",
        "url": "https://...",
        "headers": {
          "Content-Type": "audio/mpeg"
        }
      }
    }
  ]
}

The upload object returned by POST /v1/jobs, POST /v1/jobs/{job_id}/upload-urls, and POST /v1/jobs/{job_id}/resume-upload is either a simple signed put upload or a multipart upload with upload_id, part URLs, complete_url, and abort_url.

Webhooks

Receive async and batch results in your app.

Pass webhook_url when creating a job or webhookUrl in the SDK. Your endpoint should accept JSON and return a 2xx response. Webhook requests are signed with Ed25519.

Webhook payload
{
  "type": "transcription.completed",
  "job_id": "job_...",
  "status": "completed",
  "result_url": "https://...",
  "expires_at": "2026-06-04T18:00:00.000Z"
}

Completed states

Successful jobs use completed. Batch jobs can also return completed_with_errors.

Fallback

If your endpoint misses an event, poll GET /v1/transcribe/{job_id}.

Result file

The signed result URL contains the transcript data for the finished job.

Webhook verification

Each webhook includes X-TranscribeAPI-Timestamp, X-TranscribeAPI-Signature, and X-TranscribeAPI-Key-Id. Verify the signature against the raw request body using the public key published at GET /.well-known/transcribeapi-webhook-keys.json.

Verification input
${timestamp}.${raw_request_body}

Reject old timestamps, for example anything older than 5 minutes, and make webhook processing idempotent. The current key id is v1.

Billing

Billing is returned in API responses and visible in the dashboard.

Sync transcription charges after processing. Async and batch jobs reserve credit when the job starts and finalize the charge when the result is ready.

Response fields

  • billed_seconds is the rounded billable duration.
  • cost is the final request cost.
  • remaining_balance is the account balance after the charge.

Dashboard

  • Use Billing to view balance, ledger entries, and payment methods.
  • Use Usage to inspect requests, billed seconds, costs, and date ranges.
  • Create and revoke API keys from the dashboard, not from the public API reference.

Pricing

$0.15 per hour of transcription.

Pricing is linear and based on billable audio seconds. Each transcription is rounded up to the next second.

Transcription $0.15/hr

Responses include price_per_hour so charges can be reconciled.

10 minutes $0.025

Example cost for 10 minutes of billable audio.

1 hour $0.15

Example cost for one hour of billable audio.

10 hours $1.50

Async and batch use the same transcription rate.

Limits

File, rate, upload, and format limits.

These limits apply to public API usage. Use async jobs or batch jobs when a request does not fit sync.

Limit Free Pay as you go
Transcription requests 10 requests/min 300 requests/min
Sync file size 30 MB 30 MB
Sync duration 10 minutes 10 minutes
Batch files 10,000 files 10,000 files
Batch total size 10 GB 10 GB
API keys 5 keys 5 keys

429 response

When rate limited, the API returns rate_limit_exceeded with the active plan limit.

Signed URLs

Upload URLs are valid for 1 hour. Result URLs are valid for 7 days.

Audio formats

Use audio files: mp3, mpeg, mpga, m4a, wav, or webm. MP4 video uploads are not supported.

Errors

HTTP status codes and error codes returned by the public API.

Error responses use the shape { "error": "...", "code": "..." }. Some codes also include extra fields such as limits, required credit, or the current job status.

Status Meaning
400 Invalid request body, invalid form fields, upload metadata, or sync limit violation.
401 Missing or invalid API key.
402 Account balance is too low for the requested transcription.
403 API key belongs to an account with an unverified email.
404 Route or job was not found.
409 Job exists, but the requested action is not valid in its current state.
429 Per-minute transcription rate limit was exceeded.
500 Unexpected server-side failure.
502 Temporary server-side transcription failure.
Status Code Meaning
400 audio_too_long Sync transcription exceeded the 10 minute limit. Use async jobs.
400 batch_too_large Batch total size exceeded 10 GB.
400 file_too_large Sync upload exceeded the 30 MB file size limit.
400 invalid_file_metadata Batch upload file metadata or file format is invalid.
400 invalid_form_data Request was not valid multipart/form-data.
400 invalid_job_request Async job request body failed validation.
400 invalid_json Request body was not valid JSON.
400 invalid_request_options One or more sync transcription fields had invalid values.
400 invalid_upload Resume-upload payload is missing required upload fields or has invalid values.
400 invalid_upload_page Batch upload URL request included too few or too many files.
400 invalid_upload_type upload.type must be multipart or put.
400 missing_file No audio file was attached in the file field.
400 too_many_files Batch job exceeded the maximum file count.
401 invalid_api_key API key is invalid.
401 missing_api_key Authorization: Bearer YOUR_API_KEY header was missing.
402 insufficient_credit Account does not have enough credit for sync or async transcription.
403 email_not_verified The API key owner must verify their email before using the API.
404 job_not_found The requested async or batch job does not exist for this account.
404 not_found The requested route does not exist.
409 invalid_job_status The requested upload action is not allowed for the job’s current status.
409 result_not_available Job result URL is not available yet for the current status.
429 rate_limit_exceeded Account exceeded the per-minute transcription request limit.
500 internal_error The API hit an unexpected server error.
502 transcription_failed Temporary server-side transcription failure.

Models

Use whisper-large-v3-turbo.

This is the public model id for sync, async, SDK, and batch transcription.

whisper-large-v3-turbo

Default model for all public transcription requests.

Language detection

Pass language when you know it, or omit it to detect automatically.

Latency

Choose sync for immediate responses and async for background processing.

These are typical completion targets for healthy traffic. Actual completion depends on file duration, upload speed, and queue depth.

Short sync 3-10 sec

For short clips sent to /v1/transcribe.

Longest sync 30-60 sec

For sync requests near the sync boundary.

Async start Seconds

Jobs are queued as soon as upload or import completes.

Long audio Minutes

Async jobs complete in the background and report by webhook or polling.

Batch Queue based

Batch timing depends on total audio, file count, and active queue depth.

Endpoint reference

Public developer endpoints.

Except for /health, use API key auth with Authorization: Bearer YOUR_API_KEY.

Method Path Description
GET /health Health check for the API service.
GET /.well-known/transcribeapi-webhook-keys.json Public webhook signing keys for signature verification.
POST /v1/transcribe Sync transcription. Multipart audio in, transcript JSON out.
POST /v1/jobs Create a big_file or batch async job.
POST /v1/jobs/{job_id}/upload-urls Get signed upload URLs for batch upload pages.
POST /v1/jobs/{job_id}/resume-upload Refresh upload instructions for an active big-file upload.
GET /v1/transcribe/{job_id} Poll async job status and metadata.
POST /v1/transcribe/{job_id}/upload-completed Mark uploads complete and queue the async job for processing.