Sume run webhook: two request_ids, which one to dedupe on
Dedupe a Sume run webhook on the envelope request_id, which equals run_id and is stable across retries. Ignore payload.request_id, a correlation id.

Use the top-level request_id of the webhook envelope. It equals run_id and stays the same across retries. The receipt inside payload has its own request_id, which is a correlation id for the call that produced the receipt, and you should ignore it for deduping.
Why there are two
The payload is the same receipt that GET /v1/{family}-runs/{run_id} returns in data. When you poll, its request_id is an HTTP req_... id. Inside a webhook, Sume sets it to the run id. If you wrote one parser for both transports, a second dedupe key hidden in the receipt is a trap: it differs by transport.
| Field | Poll response | Webhook |
|---|---|---|
| Envelope request_id | Not present | Run id, stable across retries |
| run_id | In data.id | Same run id |
| payload.request_id | HTTP req_ id | Run id (correlation) |
| Use for dedupe | No | Envelope request_id |
Ordering and outcome
Retries repeat the same request_id, so it cannot order deliveries. created_at is the time Sume built each delivery body, so use it for order. Branch on outcome, not just status: ok, degraded or error.
A canceled run sends no webhook, so your dedupe table will never see one.
A minimal rule
Insert the envelope request_id into a unique column before doing work. If the insert conflicts, return success and stop. Then process payload with the same code you use for polled receipts.
Sources
Related posts
More in Developers
- Voice note to SRT in Python with Sume STT sentence segments
Submit a voice note to Sume STT with sentence segmentation, poll the job, and write an SRT file from segments[]. Runnable Python with asyncio.run.
- Sume timeouts in one table: 30 s, 55 s, 10 s, 90 minutes
Every wait in the Sume API has its own number: sync 30 s, jobs_wait 55 s, webhook attempts 10 s, SDK helpers 10 and 20 minutes, Format runs 90 minutes.
- Sume TTS without a language field: English default, Hangul fallback
What Sume TTS 1.0 does when you leave out language, why a Hangul-only script is the one fallback, and why you should set language yourself on every job.
- Sume TTS sentence slices need wav or raw output, not mp3
Sume TTS returns per-sentence audio_url slices only for wav or raw output. With mp3 you get timings but no slices. The request that gets clips.
Written by Sume