Sume webhook_url without a mode field: it runs in webhook mode
Send webhook_url and omit mode, and Sume treats the submit as mode webhook: 202, job id in the first response, signed terminal callback, poll as backup.

If you send webhook_url (or its alias callback_url) and leave out mode, Sume runs the job in webhook mode. If you omit both, you get async. In webhook mode the submit returns 202 with the job envelope and poll URLs, and Sume stores the callback and posts a signed terminal event to it.
The four modes
The Jobs and results page compares the modes. The mode decides how you learn the outcome. It never changes whether a job is created, its cost, or its run time.
| Mode | HTTP returns | Job id in the first response | Server blocks | Next step |
|---|---|---|---|---|
| async (default) | 202 with envelope and poll URLs | Yes | No | Poll status_url |
| sync | Same envelope after at most 30 s | Yes | Up to 30 s | Terminal? read it. Not terminal? poll, do not resubmit |
| subscribe | Same as sync | Yes | Same as sync | Same as sync |
| webhook | 202 with envelope and poll URLs | Yes | No | Wait for the callback; keep polling as a backup |
A submit with no mode
This request names no mode. The presence of webhook_url selects webhook mode. The URL must be public HTTPS. The API rejects localhost, private-network, and non-HTTPS URLs, so test with polling or a tunnel.
curl -X POST https://api.sume.com/v1/image-1.0/generate \
-H "Authorization: Bearer $SUME_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: hero-2026-10-09-001" \
-d '{
"prompt": "Product hero shot of a matte black bottle on marble",
"webhook_url": "https://hooks.example.com/sume"
}'
# No "mode" field: because webhook_url is present, the job runs in webhook mode.What arrives, and what does not
Job webhooks are terminal-only. Exactly three events exist: job.completed, job.failed, and job.canceled. There are no progress or partial callbacks. If you want progress, submit async and read GET /v1/jobs/:id/events, which is a pull snapshot, not a stream.
The delivery is signed with HMAC-SHA256 over {timestamp}.{raw_body}, with x-sume-webhook-timestamp and x-sume-webhook-signature: sume-v1=.... Verify it, store it, answer 2xx, and keep the status_url polls available for deliveries that never arrive. A webhook is a delivery optimization, not your only recovery path.
Practical checks
Log the job id from the 202 response before you do anything else. If your endpoint returns an error, the job is not lost: Sume retries, and you can still poll or redeliver. Use a tunnel with a public HTTPS name during development, since localhost URLs are rejected.
Store the signing secret from GET /v1/webhooks/signing-secret on the server, which needs the account:read scope, and verify every delivery before trusting it.
Sources
Related posts
More in Developers
- Text to speech API voice id: list avatars where voice.status is ready
Sume TTS rejects voice names from other services before any credit is held. Use avatar_id or avatar_handle, or a UUID or voi_ id copied verbatim.
- Three blind retries of a 30 s Seedance 720p submit can reserve $52.00
Without an Idempotency-Key, a timeout and two retries on one 30 s Seedance 2.5 clip can book $52.002. The same loop with one key, in curl, plus Wan 3.0 totals.
- Total usage.cost for Sume video job ids with curl, jq and awk
One shell pipeline: read job ids from a file, GET /v1/videos/{id} for each, keep completed jobs, and sum usage.cost with awk. No Python or Node needed.
- Transcribe a 15-second voice note in one request: STT sync mode
Sume STT can answer in the same HTTP call: mode sync with wait_timeout_seconds up to 30 returns 200, otherwise 202 and a poll. A $0.01 minimum, with curl.
Written by Sume