Scriptivox logoScriptivox

    Get started

    OverviewQuickstartAuthenticationPricing

    API Reference

    TranscribeFile UploadGet ResultBalanceError CodesRate LimitsFormatsLanguages

    Guides

    WebhooksCLIMCP ServerVersioning

    Use Cases

    Folder Watcher
    Scriptivox logoScriptivoxAPI Documentation

    Quickstart

    Get your first transcription running in under 5 minutes.


    1

    Create an API key

    Go to the API Keys page in your dashboard and create a new key. Copy it — you'll only see it once.

    Your key looks like: sk_live_12ab34cd...

    2

    Add balance

    Transcription costs $0.20/hour of audio, billed per second. Add funds on the Billing page. Minimum deposit is $5.00 (~25 hours of audio).

    3

    Transcribe

    Send a URL and we'll download, validate, and transcribe it. Supports direct file links, Google Drive, Dropbox, and OneDrive sharing links.

    resp = requests.post(f"{BASE}/transcribe",
    headers={"Authorization": API_KEY},
    json={
    "url": "https://example.com/podcast.mp3",
    "diarize": True
    })
    job = resp.json()
    print(f"Transcription ID: {job['id']}")

    You'll get back a transcription ID immediately. The file downloads and processes in the background.

    Optionally enable speaker diarization with diarize: true, and wire up automatic webhooks via webhook_url. If you know how many speakers are on the recording, pass speaker_count along with diarize — providing it noticeably improves accuracy versus letting the model auto-detect. Word-level timestamps (align) are on by default; pass align: false to opt out. When diarize: true, alignment is always enabled (it's required for speaker assignment) regardless of what you pass.

    Pass language when you know it. If you omit it, the model auto-detects, which usually works but can misclassify short clips, code-switched audio, or files that start with music. Passing the ISO code (e.g. "language": "en") is both faster and more accurate. See the language parameter notes for details.

    4

    Get the result

    Poll until the status is completed or failed. Typical transcriptions complete in under a minute.

    import time
    while True:
    resp = requests.get(f"{BASE}/transcribe/{job['id']}",
    headers={"Authorization": API_KEY})
    result = resp.json()
    if result["status"] == "completed":
    print(result["result"]["full_transcript"])
    break
    elif result["status"] == "failed":
    print("Error:", result["error"])
    break
    time.sleep(5)

    The response includes the full transcript, timestamped utterances, word-level timestamps (alignment is on by default), and speaker labels when diarization is enabled:

    json
    {
    "id": "txn-456",
    "status": "completed",
    "audio_duration_seconds": 120,
    "cost_cents": 0.6667,
    "result": {
    "full_transcript": "Hello, thanks for joining the call today...",
    "language": "en",
    "duration_seconds": 120,
    "speakers": ["SPEAKER 1", "SPEAKER 2"],
    "utterances": [
    {
    "start": 0.5,
    "end": 3.2,
    "text": "Hello, thanks for joining the call today.",
    "speaker": "SPEAKER 1",
    "confidence": 0.95,
    "words": [
    { "word": "Hello,", "start": 0.5, "end": 0.9, "confidence": 0.98, "speaker": "SPEAKER 1" },
    { "word": "thanks", "start": 1.0, "end": 1.3, "confidence": 0.97, "speaker": "SPEAKER 1" }
    ]
    }
    ]
    }
    }

    Need to upload your own files?

    If you don't have a public URL, you can upload files directly using the file upload flow in the API Reference.

    When something goes wrong

    Failures arrive on two different paths, and a client that only handles one of them will silently lose jobs.

    Synchronous errors come back on the call you just made, as JSON with a stable code:

    json
    {
    "error": {
    "code": "INSUFFICIENT_BALANCE",
    "message": "Add funds to continue transcribing.",
    "docs_url": "https://platform.scriptivox.com/docs/api-reference#error-codes"
    }
    }

    The ones worth handling by name on submit are INVALID_API_KEY (401 — the key is missing, malformed or revoked), INSUFFICIENT_BALANCE and ZERO_BALANCE (402 — top up on the Billing page), VALIDATION_ERROR (400 — the body is wrong; the message says how), and RATE_LIMIT_EXCEEDED (429 — wait for the seconds in Retry-After, then retry).

    Asynchronous errors do not appear on submit at all. POST /v1/transcribe returns status: "created" before the file has been fetched, so anything about the file itself — an unreachable URL, a permission-gated Drive link, a corrupt container, a codec we cannot decode, a file over 5 GB or longer than 10 hours, or a recording with no audible speech — surfaces later on the poll:

    json
    {
    "id": "txn-456",
    "status": "failed",
    "error": {
    "code": "DOWNLOAD_FAILED",
    "message": "The URL could not be fetched (HTTP 403)."
    }
    }

    Treat status: "failed" as a first-class outcome next to "completed". Both are terminal; neither will change if you keep polling. Failed and cancelled jobs cost nothing — the reserved balance is released — so a retry after fixing the input is free.

    Retrying safely

    Pass Idempotency-Key on POST /v1/transcribe and POST /v1/upload. If the same key arrives again within 24 hours you get the original job back instead of a second one, which makes a network timeout safe to retry. Without it, a retried submit is a second billable job.

    Polling without hammering

    Poll no faster than once every few seconds — the rate limit is 100 requests per minute per endpoint, and every response tells you where you stand:

    http
    RateLimit-Policy: "endpoint";q=100;w=60, "ip";q=300;w=60
    RateLimit: "endpoint";r=94;t=41

    If you would rather not poll at all, register a webhook_url on the submit call and we will POST the finished transcription to you, HMAC-signed. See Webhooks.

    Supported input

    25 container formats are accepted — MP3, WAV, FLAC, M4A, AAC, OGG, Opus, MP4, MOV, MKV, WebM among them — from 1 second to 10 hours long and at most 5 GB. Public URLs work, including Google Drive, Dropbox and OneDrive share links, as long as the link does not require a sign-in. 119 languages are supported; pass language whenever you know it.

    Next steps

    API Reference

    Full endpoint documentation

    Authentication

    Keys, headers, rotation and what each 401 means

    Webhooks

    Real-time completion notifications

    CLI

    npx @scriptivox-api/cli for shells and scripts