Stripe thin events: fetch the object, vs a Sume webhook receipt

Stripe thin events are GA for v1 resources in Endive: you fetch the object. A Sume webhook carries the receipt; an oversized one points to result_url.

5 min readSume
All posts

Stripe's changelog lists thin events for API v1 resources as generally available in the Endive API version dated 2026-09-30. A thin event tells you which object changed and you fetch the current object yourself. A Sume webhook works the other way round: it carries the finished receipt, and you only fetch when the body is too large to ship.

So if you are porting a Stripe handler, the shape of the work changes. Stripe asks for a follow-up call to get the data. Sume asks for one only in the oversize case.

What Stripe says a thin event is

Stripe's events page describes a thin event as a lightweight notification with limited information about the event and the affected object. You then make a call to fetch the complete event or the related resource. A snapshot event carries the complete object as it was when the event was raised, which Stripe warns can be stale by the time you process it.

One caveat from the same day: the changelog says thin events for v1 resources are GA in Endive, while the event destinations page I read still states that thin events come from API v2 resource state changes. Check which of the two your account and API version actually produce before you rely on it.

Stripe event formats (Stripe docs, read 2026-10-02)
FormatPayloadTo get current data
Thin eventSmall: IDs and type of the related objectFetch the related object or the full event
Snapshot eventLarge: a snapshot of the objectFetch the latest object, because the snapshot may be outdated

What a Sume webhook carries

A Sume job webhook is sent when the job reaches a terminal state: job.completed, job.failed or job.canceled. The body has event, request_id, job_id, a status of OK or ERROR, and payload.artifacts. A Format run webhook (format.run.terminal) carries the run receipt in its payload, with a status of OK or ERROR and an outcome of ok, degraded or error.

The one place Sume behaves like a thin event is the size cap. The run webhooks page says a receipt over 1 MiB arrives as payload null with error.code payload_too_large and a result_url. A handler that reads payload and finds null should fetch result_url, not treat the run as failed. The status is still the run's real outcome.

What to change in a ported handler

Sume does not offer a thin-event mode that you can switch on. The webhook format is fixed, and the docs I read describe no option to choose between small and large payloads.

  • Do not add a fetch call to the happy path. Read the receipt from the body.
  • Branch on payload being null. If it is, fetch result_url once and continue with the same code.
  • Keep the dedupe key from the envelope: job_id for job webhooks, request_id (which equals the run id) for run webhooks.
  • Keep a poll on status_url as a backstop for deliveries that never arrive.

Checklist for the port

Stripe's own page pairs thin events with typed SDK helpers that fetch the related object for you. A Sume receiver has nothing equivalent to call, because the receipt is already in the body, so the port mostly deletes code. What remains is verification, dedupe and the null-payload branch.

Test the oversize branch on purpose. Send your handler a body with payload set to null and error.code payload_too_large and confirm it fetches result_url once, records the result, and returns 200. Most handlers are only ever tested with the happy path and fail the first time a large receipt arrives. Also keep the stale-data warning in mind: a Sume receipt is the final state of that run, so unlike a Stripe snapshot it does not need a refresh before you act on it.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume