Gemini thin webhook payload vs Sume: artifact URLs in the body
Gemini webhooks send a snapshot with pointers to results. A Sume job.completed webhook already carries the media.sume.com artifact URL, so no second fetch.

Gemini webhooks are thin: the delivery is a snapshot with status details and pointers to results, not the output file itself. A Sume job.completed webhook is different in one respect that matters here: its payload.artifacts array already holds the media.sume.com URL, so a receiver can use it without a follow-up call.
Sources: the Gemini Webhooks page and Sume's Webhooks docs, read 2026-10-01.
What does a Sume webhook body contain?
The documented job.completed body has event, request_id, job_id, status: "OK" and a payload.artifacts list. Each artifact has an id, a url of the form https://media.sume.com/artifacts/..., a type and a content_type. Failed and canceled deliveries use status: "ERROR" and include an error object.
| Aspect | Gemini webhook | Sume webhook |
|---|---|---|
| Result in body | Pointer, not the output file | Artifact url in payload.artifacts |
| Events | Several event types, including interaction events | Terminal only: job.completed, job.failed, job.canceled |
| Duplicate handling | At-least-once; a header is provided for duplicates | At-least-once retries; dedupe on job_id |
Does Sume send progress events?
No. Sume sends terminal job events only, with no progress or partial deliveries. For progress, a polling client reads the job's events or status.
When do I still need to fetch the result?
Polling clients use GET /v1/jobs/:id/result, which is only for completed jobs. A receiver on the webhook path normally does not. If you want the full record anyway, fetch it by job_id after you have stored the event; see this note on large payloads.
How do I avoid processing a delivery twice?
Non-2xx responses are retried until attempts are exhausted, so the same event can arrive more than once. Return a 2xx after durably storing the event and use job_id as your idempotency key.
Sources
Related posts
More in Developers
- GPT Image 2 input_fidelity: omit it; Sume returns 400
OpenAI says to omit input_fidelity for gpt-image-2 because inputs run at high fidelity. Sume lists no such field and rejects unlisted parameters with 400.
- GPT Image moderation_blocked vs Sume content_policy_rejected
OpenAI returns moderation_blocked with moderation_details. On Sume, policy refusals are grouped under content_policy_rejected. What to read and when to retry.
- GPT Image revised_prompt: what a Sume images response returns
OpenAI returns revised_prompt on the image generation call. A Sume POST /v1/images response has data[].url and usage, with no revised prompt field.
- GPT Image user error: don't retry unchanged; Sume failures unbilled
OpenAI says not to auto-retry image_generation_user_error without changing the prompt or inputs. On Sume, retry 429 with backoff; failed images are not billed.
Written by Sume