Webhook and event payload changes: announcing new shapes to consumers who can’t pin a version

Every discipline in API change communication quietly assumes the consumer makes the call. They pick the endpoint, pin the version in a header or an SDK, retry on their own schedule, and see errors in their own logs the moment something changes. Webhooks invert all of it. You make the call: whatever shape your producer emits tonight is what every registered endpoint receives, ready or not. The consumer can’t pin a version in a request they never make — unless you build them a way to. That single inversion changes how payload changes must be versioned, announced, and rolled out.

This guide covers the discipline for changing messages you push: why push breaks the usual migration playbook, what counts as breaking in a webhook (including changes nowhere near the JSON), the versioning strategies that give receivers back some control, an announcement playbook built on the one advantage you have — a complete census of your consumers — and a full entry template. It’s the push-side sibling of the API changelog and of data and schema changelogs, which covers event schemas at rest; this one covers the delivery.

Why push inverts the migration playbook

Three properties make webhook changes fail differently from API changes:

  • There is no pinning surface. An API consumer can send a version header, pin an SDK, or simply not upgrade. A webhook receiver has no request to put a version in. If you don’t build an explicit pinning mechanism, every consumer is permanently on latest — and every payload change is a forced, simultaneous, unconsented upgrade for all of them.
  • Failure is silent data loss, not an error message. When an API breaks, the consumer’s own code throws, in their own logs, at call time. When a webhook payload changes under a handler, the handler 500s or — worse — succeeds while reading a field that is no longer there. The delivery failures accumulate in your logs, which they never read; your retries exhaust; the events are simply gone. Many consumers discover a webhook break weeks later, as missing orders in a report, with no error anywhere on their side.
  • Handlers are write-once artifacts. The typical webhook handler was written during integration week — often by a contractor or a developer who has since left — verified once, and never monitored again. Assume nobody is watching the receiving end and you’ll calibrate your announcement effort correctly.

Against all that, one enormous advantage, unique to webhooks: you know exactly who your consumers are. Every registered endpoint URL is a row in your database, with delivery stats and response codes attached. No other kind of breaking change gives you a complete, queryable census of who will break. The playbook below leans on it hard.

What counts as breaking in a message you push

The classics apply — removing or renaming a field, changing a type, changing what a value means — but push adds categories that catch teams out because they live nowhere near the payload JSON:

  • Envelope changes. Moving the payload under a data key, renaming event_type, changing the id or timestamp format. Field changes break the consumers who use that field; envelope changes break everyone at once.
  • Signature and verification changes. A new HMAC algorithm, a renamed signature header, a rotated signing secret. The consumers you break are precisely your most diligent ones — the receivers that verify signatures fail closed and start rejecting your deliveries as forged. From their side it looks like an attack; from yours, like their endpoint went down.
  • Delivery-infrastructure changes. New source IP ranges (enterprise receivers allowlist you), a raised TLS minimum, changed timeout or retry behavior, changed ordering or duplication semantics. Consumers built against the observed behavior — Hyrum’s Law does not care that the retry schedule was never documented. Announce these like dropping platform support: a dated entry, an overlap window where old and new IPs both deliver, and a way to test early.
  • New event types sent to existing endpoints. Additive in your model; breaking for every strict handler that rejects — or alerts on — unknown types. If endpoints subscribe to specific events, new types are safely opt-in. If you broadcast everything to everyone, your “additive” launch just changed the traffic to thousands of handlers that never asked for it. Announce new event types even when they’re opt-in: they only create value if someone subscribes.
  • New fields. Genuinely safe if you’ve published the tolerant-reader rule — “handlers must ignore unknown fields; we add fields without notice” — in your docs from day one. Say it explicitly, because strict schema validators exist. Then still announce new fields as new entries: a field nobody knows about earns you nothing.

Versioning things you push

The ways to give receivers back some control, strongest first:

  • Version pinned on the endpoint, not the request. Each registered endpoint carries a payload-version setting, chosen at registration and changed by the consumer when they are ready (Stripe’s model). Upgrading is a config edit on their schedule, testable per endpoint. This is the gold standard: it restores exactly the control that push took away.
  • New event names for new shapes. Ship the new payload as a new type — a .v2 suffix or a new name — and let consumers subscribe deliberately, then sunset the old type on a dated schedule. Coarser than pinning, but it works with plain subscription mechanics.
  • The dual-send window. For a shape change without version infrastructure: deliver both — old and new event types side by side, or the old field kept alongside its replacement — for a published window, so consumers migrate while the old shape still flows. The signature-scheme variant is the dual-sign window: send old and new signature headers together so verifying receivers can switch whenever they’re ready within it. Never flip either in place.
  • A version field in the envelope. The minimum viable courtesy: stamp every delivery with its payload version so handlers can branch. It doesn’t prevent the forced upgrade; it makes it survivable.

The announcement playbook: use the census

You hold a complete list of consumers. The playbook writes itself from that:

  • Query the affected before you write a word. Which endpoints receive this event type? Which are pinned to the old version? Which responded 2xx this month — i.e., which are alive? The announcement can say “this affects 214 of 3,900 active endpoints” because you counted, and every affected account can be told directly.
  • Segment the delivery, never the record. Email the affected accounts with their own endpoint names in the message. But the address on file reaches the account owner — not the contractor who wrote the handler in 2023. Email is one channel, not the plan.
  • Signal in-band, where the handler’s owners look. A deprecation header on every delivery of the old shape (the push analogue of RFC 8594), a banner on the endpoint’s dashboard page, warnings in the delivery log they’ll open when debugging. The dashboard they check while integrating is the one surface you know a webhook developer has seen.
  • Give them a way to rehearse. A “send sample” button that delivers the new shape to their endpoint on demand, new-shape events in sandbox before production, and a replay tool. “Test it tonight” beats “read this migration guide” for a one-afternoon fix.
  • Publish the dated entry and announce three times. The changelog entry — announcement, reminder, change-day confirmation, per the deprecation policy you published before you needed it — is the permanent, linkable record everything else points at: the email, the deprecation header, the dashboard banner.
  • Watch response codes after the flip. An endpoint that was healthy for two years and starts erroring the day your change ships is your migration failure surfacing in your logs — the one place a webhook break is visible. Pause deliveries and contact the owner; don’t let the retries quietly exhaust and drop their events.

The entry itself

Breaking: new invoice.updated payload (version 2027-02)

What changes: amounts move from integer cents to a money object with
an explicit currency field; ids become strings. The old shape (2026-06)
is unchanged for endpoints pinned to it.

Are you affected? Only endpoints subscribed to invoice.* events —
about 6% of active endpoints. Your endpoints page shows each
endpoint’s pinned version; we’ve emailed every affected account.

Dates: 2027-02 is available now (switch per endpoint, per environment).
New endpoints default to it from May 1. The 2026-06 shape stops being
delivered Oct 1 — deliveries of the old shape carry a
Webhook-Deprecation header until then.

What to do: press “send sample” on your endpoint page to
receive the new shape now, update your handler, then flip the version.
Migration notes: <url>

Signatures, source IPs, retries, and ordering are unchanged.

That last line is a webhook-specific courtesy worth copying: because so many breaking dimensions live outside the payload, say explicitly which ones are not moving. It’s one sentence, and it spares every diligent reader an audit.

Six anti-patterns

  • The in-place flip. Same event name, new shape, one morning, everyone at once. The push equivalent of breaking an API without a version bump — except the failures land silently in other people’s dropped events instead of loudly in their consoles.
  • “It’s additive” as a free pass. Broadcasting a new event type to every existing endpoint unannounced. Additive in your schema; a traffic change and a strict-handler breaker in theirs.
  • Blaming the receiver. Your change ships, an endpoint’s error rate jumps, and the delivery log says “endpoint failing — disabled after 3 days.” If yesterday’s handler worked and today’s doesn’t, the break is yours to communicate, not theirs to discover.
  • Signature changes without a dual-sign window. Rotating secrets or switching HMAC schemes in place punishes exactly the consumers who verified — your most security-diligent receivers fail closed, and their incident channel says “possible forgery.”
  • The docs-only migration. Updating the payload reference and calling it announced. Machine consumers don’t re-read docs; the change needs a dated entry, an emailed notice, and an in-band signal — the docs describe the present; the changelog announces the change.
  • Email-only, to the account owner. The person who registered the endpoint is three jobs away; the address on file is a billing alias. Email is necessary and insufficient — without the dashboard banner, the deprecation header, and the public entry, your announcement retired with its recipient.

Running it on Wakelog

The public half of this playbook maps directly onto Wakelog: post the dated entry tagged breaking so it stands out in the feed and survives as the permanent record; schedule the reminder and change-day confirmation with publish_at so the announce-3x cadence ships itself; and the entry’s permalink is what your deprecation header, dashboard banner, and affected-account email all point at. Your changelog’s RSS and JSON feeds are the tripwire for consumers — and for teams that monitor their vendors — whose alerting reads feeds, not inboxes. We eat this cooking: Wakelog’s own publish notifications are webhooks, their payload is documented, and new fields are additive-only under a stated tolerant-reader rule. The honest boundary: Wakelog doesn’t deliver your events — pinning, dual-send, and per-endpoint dashboards live in your product. The changelog is the public, citable record they all link to.

Start your changelog — free   Next: data & schema changelogs →

Related guides

Last updated 2026-08-02 · All guides