Text to Speech

Turn text into speech with any voice, one at a time or in batches.

Create a task

POST /api/v1/tts
Content-Type: application/json
curl https://voiceailabs.com/api/v1/tts \
  -H "Authorization: Bearer $VAL_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: article-88-paragraph-1" \
  -d '{
    "voice_id": "VOICE_ID",
    "text": "The weather is lovely today - perfect for a walk.",
    "language": "en",
    "speed": 1.1,
    "mode": "balance",
    "title": "Article 88, paragraph 1"
  }'
ParameterTypeRequiredDescription
voice_idstringYesVoice ID (your voice or a public voice)
textstringYesText to synthesize, within your plan's per-request limit (limits.max_text_length from GET /account)
languagestringNoauto (default), zh, en, yue, ja, ko, fr, es, pt, de
speednumberNoSpeaking rate 0.5–2.0, default 1.0
modestringNobalance (default), stable (consistent, good for long narration), creative (more expressive)
seedintegerNoRandom seed 0–2147483647; the same parameters and seed give more similar results
titlestringNoTask name, up to 255 characters, shown in the web app's library

Returns 202 with a task object:

{
  "code": 0,
  "message": "ok",
  "data": {
    "id": "9a3e6b1c-…",
    "object": "synthesis",
    "type": "tts",
    "status": "pending",
    "voice_id": "VOICE_ID",
    "text": "The weather is lovely today - perfect for a walk.",
    "language": "en",
    "speed": 1.1,
    "mode": "balance",
    "audio_url": null,
    "credits_used": 17,
    "batch_id": null,
    "created_at": "2026-10-09T02:00:00.000Z"
  }
}

Then check the result with GET /syntheses/{id}, or receive a synthesis.completed webhook.

Tips

  • Split long articles into paragraphs or sentences within the per-request limit, then submit them with the batch endpoint.
  • Your pronunciation dictionary from the web app is applied to API requests automatically.
  • If numbers, abbreviations or names are read incorrectly, write them the way they should be spoken or add them to your pronunciation dictionary.

Create a batch

Submit up to 100 texts at once. Each item becomes its own task and audio file, billed separately.

POST /api/v1/tts/batches
curl https://voiceailabs.com/api/v1/tts/batches \
  -H "Authorization: Bearer $VAL_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: game-lines-v3" \
  -d '{
    "items": [
      { "voice_id": "VOICE_A", "text": "Welcome to the village.", "title": "npc_001" },
      { "voice_id": "VOICE_B", "text": "Watch out, monsters ahead!", "title": "npc_002", "speed": 1.2 }
    ]
  }'

Each item in items takes the same parameters as a single task.

  • All or nothing: if any item is invalid, exceeds the character limit, or you don't have enough credits, nothing is created and nothing is charged. For invalid parameters, data.index tells you which item (starting at 0).
  • Tasks are queued according to your plan's concurrency limit, so they may finish in a different order than submitted.

Returns 202 with a batch object:

{
  "code": 0,
  "message": "ok",
  "data": {
    "id": "c41f…",
    "object": "batch",
    "status": "processing",
    "total": 2,
    "counts": { "pending": 2, "processing": 0, "completed": 0, "failed": 0 },
    "credits_used": 17,
    "created_at": "2026-10-09T02:00:00.000Z",
    "items": [ /* task objects, in submission order */ ]
  }
}

Get a batch

GET /api/v1/tts/batches/{id}

Returns the same batch object. Like querying a single task, this also advances unfinished tasks. status becomes completed once every task has completed or failed. With a webhook configured, a single batch.completed event is sent when the batch finishes.

Failed items are not retried automatically - create them again with the same parameters (and a new Idempotency-Key).