Sume sync mode waits at most 30 seconds: short TTS vs long scripts

mode sync is a bounded wait, clamped to 0-30 seconds, not a promise the audio is ready. When to use it, and when to go async or webhook.

5 min readSume
All posts

Sume's sync mode is a bounded wait, not a guarantee. mode: sync (and its alias subscribe) blocks the HTTP request for at most wait_timeout_seconds, which is clamped to 0 to 30 seconds, and only when waiter capacity is available. If the job is not terminal by then you get the job id and polling URLs back, exactly as in async mode. Use sync for short lines; use async or a webhook for anything you would not stake a 30 second timeout on.

The mistake to avoid is treating a timed-out sync call as a failure and sending the request again.

What are the three modes?

The Sume OpenAPI spec says every mode returns the job id in the first response. Async, the default, returns immediately with polling URLs.

Communication modes, Sume spec read 2026-10-04
ModeBehaviourBest for
async (default)Returns at once with polling URLsAnything long
sync or subscribeBlocks up to wait_timeout_seconds, max 30Short single lines
webhookTerminal callback to webhook_urlBatches and queues

What does a timeout mean?

It bounds how long the request blocks, not how long the job may take. The job keeps running. Read the id from the response, poll /v1/jobs/{id}/status, and fetch /result once terminal is true. If you do resend, include an Idempotency-Key so the retry is recognised; the longer version is in do not resubmit after a sync wait times out.

  • Set wait_timeout_seconds below your own HTTP client timeout.
  • Handle both outcomes: result inline, or job id only.
  • Do not use sync inside a request a user is staring at for longer than you can afford.

What does the code look like?

A sync call that falls back to polling:

import os, time, requests

H = {"Authorization": "Bearer " + os.environ["SUME_API_KEY"]}
B = "https://api.sume.com"

r = requests.post(B + "/v1/tts-1.0/generate", headers=H, timeout=45, json={
    "transcript": "Your order has shipped.",
    "voice": {"id": os.environ["VOICE_ID"]},
    "language": "en",
    "mode": "sync",
    "wait_timeout_seconds": 20,
})
r.raise_for_status()
job_id = r.json()["data"]["job"]["id"]
while not requests.get(B + f"/v1/jobs/{job_id}/status", headers=H,
                       timeout=30).json()["data"]["terminal"]:
    time.sleep(2)
print("done", job_id)

Which mode for which work?

A one-sentence confirmation line: sync is fine. A 20,000 character script: async. A nightly batch: webhook. For a complete polling loop see async TTS polling on Sume.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume