Sume submit: request_id is the job id you poll (curl, jq)
After an async submit, data.request_id is the id for GET /v1/jobs/:id. error.request_id is for support tickets. A curl and jq check.

On a successful async submit, the request_id in the response body is the job id. Pass it to GET /v1/jobs/:id and the job record answers with the same value in its id field. There is no separate job_id key to look for in the submit envelope. A request_id inside an error object is a different thing: it identifies the failed request so support can find it, and it is not a job you can poll.
Two ids with the same name
The submit response also carries status_url, result_url and next_poll_after_seconds, so you rarely have to build a URL by hand.
| Location | Meaning | Use it for |
|---|---|---|
| data.request_id on a submit response | The job id | GET /v1/jobs/:id, the result call, cancel |
| id on the job resource | The same job id | Matching against what you stored |
| error.request_id on a failed call | The failed request | Quoting in a support ticket |
Check it with curl and jq
The script submits an async image job with an Idempotency-Key, reads data.request_id, fetches the job and compares data.id with it. If the submit fails, it prints error.request_id instead. It needs a funded key, so it spends one image job; use any small prompt.
#!/usr/bin/env bash
set -euo pipefail
: "${SUME_API_KEY:?set SUME_API_KEY}"
H="x-api-key: $SUME_API_KEY"
RES=$(curl -s -H "$H" -H "Content-Type: application/json" \
-H "Idempotency-Key: reqid-demo-$(date +%s)" \
-d '{"prompt":"A ceramic mug on a desk","mode":"async"}' \
https://api.sume.com/v1/image-1.0/generate)
ID=$(echo "$RES" | jq -r '.data.request_id // empty')
if [ -z "$ID" ]; then # a failure: error.request_id is for a support ticket
echo "failed, quote this to support: $(echo "$RES" | jq -r '.error.request_id // "none"')"
exit 1
fi
curl -sf -H "$H" "https://api.sume.com/v1/jobs/$ID" |
jq -e --arg id "$ID" '.data.id == $id' >/dev/null && echo "request_id $ID is the job id"Store the right one
- Save data.request_id next to your own record the moment the submit returns, before you do anything else.
- Log error.request_id with the HTTP status when a call fails, and keep it out of your job table.
- Use the same id for status, result and cancel calls. The Idempotency-Key is yours and is a different value.
- Resubmitting with the same key and body returns the original job, so the id you stored stays valid.
A common mistake
A retry loop that stores error.request_id as if it were a job id will poll a path that returns 404 not_found, and the loop only ends when its own deadline fires. The cheap guard is to store an id only when the HTTP status is a success and the body has data.request_id. For an error, keep the whole envelope in your logs.
When you reuse an Idempotency-Key and send the same body, the response returns the original job. Its request_id is the id of the first job, so two submits in your logs can point at one job. That is the point of the key, and it is why you should look up your own record by id before you create a second row.
Sources
Related posts
More in Developers
- Sume TTS word timestamps to caption cues for a narrated 60-second clip
Ask Sume TTS for timestamps.words, group them into cues and send them to video-captions so no recognition runs. About 25 cents for a 60-second narration.
- Sume TypeScript SDK waitForJob: 20-minute timeout, job keeps billing
How @sume-com/sdk waitForJob polls a generation job, what SumeJobTimeoutError means, and why a client timeout does not cancel or refund the job.
- Webhook endpoint down: redeliver a Sume video job after the retries
Sume retries a job webhook 10 times, 30 seconds apart. If your receiver was down longer, POST /v1/jobs/{id}/webhook/redeliver re-sends the terminal payload.
- Does a rejected Sume video request cost anything? Free 400 probes
A malformed POST /v1/videos is checked before any estimate or reservation, so a 400 or 404 bills nothing. Three probes to test size, seed and model ids.
Written by Sume