Webhooks
This guide covers the delivery contract for events the Platform sends to your integration: registering an endpoint, verifying every delivery, acknowledging correctly, and handling retries and duplicates. The payload definitions are in Webhook Event Schemas; your obligations as a receiver are also stated in the Webhook Obligations policy. Build your receiver to this contract before you register it: a receiver written after events start arriving is written too late.
Why webhooks
Webhooks replace polling. Instead of asking "has anything changed" on a timer, your system is told when an order is placed, a shipment is reported, a refund is issued, or standing changes: within moments, at a fraction of the rate budget (Rate Limit Headers). Core Concepts covers the trade-off; this guide covers the mechanics.
Step 1: Register an endpoint
- Provide one HTTPS endpoint URL per event group you subscribe to. HTTPS is required; plain HTTP endpoints are not accepted.
- Choose events deliberately. Subscribe to the events your integration acts on: every extra event is traffic you must verify, store, and discard correctly.
- Registration gives you a signing secret for the endpoint. Store it in your secrets manager like an API key (Authentication and Authorization); it is how you will know a delivery really came from the Platform.
Step 2: Know the delivery shape
Deliveries are HTTPS POST requests with a JSON body. Event payloads follow Webhook Event Schemas; in outline
- Each event has a unique event
id, a type in the domain vocabulary: for example, an order placed, a fulfillment shipped, a refund issued, a standing change: a timestamp, and the affected object's current state with the change that produced the event. - The payload carries enough to act in the common case without a follow-up read. Where exact current state matters, fetch the resource by its
idrather than reasoning from a possibly stale sequence of payloads. - Events are facts about the past, not instructions. An order-paid event states that payment succeeded; what your integration does about it is your design.
- Events are ordered per object, not globally across objects. Never build logic that assumes an event about one order precedes an event about another.
Step 3: Verify every delivery
An unverified webhook endpoint is an open control channel into your systems for anyone who discovers the URL. Verify from the first version
- Every delivery carries a signature of the raw request body, computed with your endpoint's signing secret and delivered in the headers, together with a timestamp.
- Recompute the signature over the exact bytes received: before any JSON parsing or re-serialization: and compare in constant time, not with ordinary string equality. Reject mismatches with
401and process nothing. - Check the timestamp as well: reject deliveries older than a few minutes, to close the replay window.
- If verification suddenly fails on every delivery, suspect secret rotation: on your side or the endpoint's: before suspecting an attack. Rotation is the common cause; check your stored secret first.
Step 4: Acknowledge fast, process idempotently
- Return
200within seconds. Do the heavy work: fulfillment calls, emails, accounting writes: asynchronously, after acknowledgement. A slow endpoint backs up its own deliveries. - Delivery is at least once. The Platform retries until your endpoint acknowledges, so duplicates are a certainty, not an edge case. The event
idis your idempotency key (Idempotency Keys): record processed ids, and make a second delivery of the same event a no-op. Never let a retried delivery create a second shipment, a second refund, or a second email. - The retry schedule backs off: minutes, then hours, spanning roughly a day: after which undeliverable events are parked where they can be inspected and replayed. A persistently failing endpoint is disabled rather than left dropping events silently; a dead endpoint silently losing refund events is worse than no endpoint at all.
- Alert on your own delivery failures the way you alert on downtime. A week of failed deliveries discovered by a customer is a quarter's trust spent in a day.
Failure handling
- Your endpoint returns
5xxor times out: the Platform retries with backoff; fix the receiver, and the backlog drains. Keep processing idempotent so the drain is safe. - You receive an event type you do not recognize: acknowledge it, log it, and ignore the payload. New event types are additive; failing them turns an announcement into an outage.
- You suspect a missed event: reconcile by reading current state through the API (Orders Endpoints and its siblings) on a slow schedule. Webhooks carry the present; periodic reconciliation proves the past arrived. Design for both from the start.
- You need to move or rebuild the endpoint: register the new endpoint and confirm deliveries before retiring the old one, and replay parked events after the move rather than assuming none matter.
What to build
- The receiver: HTTPS, signature verification over raw bytes, constant-time comparison, timestamp check, fast
200, asynchronous processing, idempotent by eventid. - The operations around it: delivery logging keyed by event
id, alerting on sustained failure, and a reconciliation read on a schedule: the three things that separate a webhook integration from a webhook hope.
Questions about webhooks: support@aapawz.com.