TTS call returned processing in sync mode: poll, do not resubmit

Sume TTS in sync mode waits at most 30 seconds. If the job is not terminal, poll status_url, and retry a submit only with the same Idempotency-Key.

4 min readSume
All posts

If a Sume TTS request sent with mode: "sync" comes back still queued or processing, nothing is wrong. The wait is capped at 30 seconds and the job keeps running. Take status_url from the response and poll it until the job is terminal; do not submit a new paid job for the same line. If you must retry the submit itself, send the same Idempotency-Key so you get the original job back.

What does sync actually do?

The OpenAPI text for wait_timeout_seconds says it is an integer from 0 to 30 and bounds how long the HTTP request blocks, not how long the job may take. If no terminal update arrives before the timeout, or the API process has no waiter capacity, the response is still 2xx and carries the current job state with polling URLs. Jobs and results adds that the envelope's sync.timed_out is true after a timeout and sync.capacity_exhausted is true when the wait was skipped.

subscribe is the same bounded wait under another name. For new work the docs recommend async or webhook.

Communication modes on Sume submit endpoints, from Jobs and results and the OpenAPI, read 2026-10-02.
ModeWhat the HTTP call doesWhat you do next
async (default)Returns 202 with polling URLsPoll status_url, then fetch result_url
syncWaits up to wait_timeout_seconds (max 30)If not terminal, poll; do not resubmit
subscribeSame as syncSame as sync
webhookReturns 202 and stores the callbackWait for the terminal callback; keep polling as backup

How do I poll safely?

Read next_poll_after_seconds when it is present and back off otherwise. Stop on completed, failed or canceled, then fetch result_url. The script below submits in sync mode, then polls if the first answer was not final.

import json, os, time, urllib.request

BASE = "https://api.sume.com"
HEAD = {"Authorization": "Bearer " + os.environ["SUME_API_KEY"], "Content-Type": "application/json", "Idempotency-Key": "narration-001"}

def call(url, body=None):
    req = urllib.request.Request(url, data=body and json.dumps(body).encode(), headers=HEAD)
    return json.load(urllib.request.urlopen(req))["data"]

env = call(BASE + "/v1/tts-1.0/generate", {"transcript": "A short line.", "avatar_handle": "@your_avatar", "language": "en", "mode": "sync", "wait_timeout_seconds": 30})
while not env["terminal"]:
    time.sleep(env.get("next_poll_after_seconds") or 2)
    env = call(env["status_url"])
print(env["result_url"])

Why must I reuse the idempotency key?

A 2xx from submit means the job exists and paid work is in flight. A second submit with a new key is a second job. With the same key, the retry returns the original job. Choose a key that names the intent, for example a script id and sentence number, so a restart of your own process reuses it.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume