Poll Sume audio jobs at the recommended interval, not a fixed sleep
The Sume job status response tells you when to poll next and whether the job is terminal. Read those fields instead of hardcoding sleep(2).

Read the poll hints Sume returns instead of guessing a sleep. The job status response includes next_poll_after_seconds, recommended_poll_interval_seconds, retry_after_seconds, a terminal flag and a result_ready flag. A loop that sleeps for the recommended interval and stops on terminal polls no more often than it needs to, and does not hammer the API for a long TTS or STT job.
It also means you can change the pacing from the server side without editing every client.
Which fields matter?
The status route is /v1/jobs/{id}/status. The Sume OpenAPI spec lists these fields as required on the response.
| Field | Use |
|---|---|
| terminal | Stop polling when true |
| result_ready | Fetch /result when true |
| recommended_poll_interval_seconds | Default sleep between polls |
| next_poll_after_seconds | Server hint for the next call |
| retry_after_seconds | Back off at least this long |
| cancelable | True only before generation has started |
| sume_status | queued, processing, completed, failed or canceled |
Why not a fixed sleep?
A fixed two second sleep is fine for a demo and wasteful at scale. With a hundred jobs in flight it is a hundred requests every two seconds, much of which tells you nothing new. A server hint lets the API slow you down when work is slow, and a 429 from the API is a reason to honour retry_after_seconds rather than retry immediately.
- Stop on
terminal, not on a status string you invented. - Fetch the result only when
result_readyis true. - Add a ceiling so a stuck job does not poll forever.
What does the loop look like?
A loop with a ceiling and the server's interval:
import os, time, requests
H = {"Authorization": "Bearer " + os.environ["SUME_API_KEY"]}
url = f"https://api.sume.com/v1/jobs/{os.environ['JOB_ID']}/status"
deadline = time.time() + 900
while time.time() < deadline:
d = requests.get(url, headers=H, timeout=30).json()["data"]
if d["terminal"]:
print(d["sume_status"], "result_ready:", d["result_ready"])
break
time.sleep(d.get("next_poll_after_seconds")
or d.get("recommended_poll_interval_seconds") or 3)
else:
print("gave up waiting; the job may still finish")
Should you poll at all?
If you can expose a public HTTPS endpoint, a webhook removes polling for the common case. Keep polling as the fallback; see async TTS polling on Sume and what to do after a sync timeout.
Sources
Related posts
More in Developers
- Ported Sora wrapper blocked until done? Sume sync stops at 30 s
A wrapper that blocks until the video is done will time out on Sume sync mode, which waits at most 30 seconds. Return the job id and poll, never resubmit.
- Pre-flight tool access: tools_list on Sume's MCP
Notion added a tool that reveals connection-scoped capabilities before requests. Sume's MCP does the same job with tools_list, tools_schema and mcp_health.
- Prism mock server from Sume's openapi.json: test without spending
Download api.sume.com/reference/json, run prism mock -d on port 4010 and point your client at it. What a mock proves and what it cannot.
- Prometheus counters for Sume API errors, split by code and status
Wrap every Sume call in a counter and histogram labeled by route template, status and error.code, never by job id or request id, then alert on retryable rates.
Written by Sume