Skip to navigation

Asynchronous Text-to-Speech

Use POST /v2/tts/jobs to submit speech synthesis and retrieve the result later. Submission returns 202 with a job and a Location header. This is useful when your application needs to keep a job ID across a disconnect or restart.

API-key access requires your organization to be enabled for the asynchronous TTS rollout. A request from an organization without access returns 503. The existing POST /v2/tts remains available with its synchronous 200 response containing id, url, and duration.

Submit a job

The body is the same as synchronous TTS: script contains 1–5,000 characters, voiceId identifies an available voice, and provider is required. Use elevenlabs for ElevenLabs voices. Optional stability and similarityBoost range from 0 to 1.

curl -i https://api.sync.so/v2/tts/jobs \
-H "x-api-key: $SYNC_API_KEY" \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: narration-take-001' \
-d '{
"script": "Welcome to our product tour.",
"voiceId": "EXAVITQu4vr4xnSDxMaL",
"provider": "elevenlabs"
}'

Save the returned id before polling. A new job can look like this:

{
"id": "6533643b-aceb-4c40-967e-d9ba9baac39e",
"status": "PENDING",
"url": null,
"duration": null,
"error": null,
"createdAt": "2026-10-02T09:30:00Z",
"startedAt": null,
"finishedAt": null
}

The response also sets Location: /v2/tts/jobs/6533643b-aceb-4c40-967e-d9ba9baac39e. An idempotent replay returns the original job in its current state, which may already be terminal.

Poll and use the audio

curl -i https://api.sync.so/v2/tts/jobs/6533643b-aceb-4c40-967e-d9ba9baac39e \
-H "x-api-key: $SYNC_API_KEY"
StatusAction
PENDINGKeep the ID and wait before polling again.
PROCESSINGSynthesis is running; keep polling.
SUCCESSUse url for hosted audio and duration for its length in seconds.
FAILEDInspect error.code and error.message before deciding whether to submit another job.

A pending or processing response includes Retry-After: 3. Wait at least three seconds before the next poll. Stop polling at SUCCESS or FAILED; terminal responses omit that header. Jobs are scoped to your organization, and a missing or inaccessible job returns 404.

On success, pass the returned url as an audio input to POST /v2/generate, alongside your video. This reuses the synthesized take; it does not synthesize the script again.

Retries and errors

Use one Idempotency-Key for each intended take. Keys contain 1–128 characters after trimming and are scoped to your organization. If submission times out or the response is lost, resend the same body and key. It returns the original job. Reusing the key with a different body returns 409.

An idempotent replay does not restart a failed job. After inspecting and correcting a failure, use a new key only when you intend a new synthesis attempt. In particular, PROVIDER_RESULT_UNKNOWN means the provider outcome was uncertain; do not assume a new submission is a free replay.

HTTP status at submissionHandling
400Correct the script, voice/provider fields, options, or idempotency key.
402Resolve the applicable billing or free-tier usage limit.
409Reuse the original body with the original key, or choose a new key for a different take.
422Check voice availability and restrictions.
503Check rollout access or temporary admission availability. Honor Retry-After when present and use backoff for temporary failures.

Accepted jobs report failures in error, separately from submission HTTP errors. Codes are CREATE_FAILED, PROVIDER_FAILED, PROVIDER_TIMEOUT, PROVIDER_RESULT_UNKNOWN, UPLOAD_FAILED, TIMEOUT, and UNKNOWN. Keep the job ID and error message for support. See Error Handling for shared billing and provider errors.