Handle webhooks
Runledger tells you when something happens that you didn’t directly request: a confirmation window closed, a rule reversed a charge, a dispute deadline is near, an invoice finalized. Register an endpoint with POST /v1/webhook_endpoints and choose the event types you handle.
The payload
Events are thin. They say what happened and to which object, and you fetch the object for its current state:
Events about a window, a threshold or a purchase also carry a context that names the customer, member_id, team_id, pool, allowance, spend limit and threshold they are about, so you can write a message without another call. Events that report a share of a window or limit point related_object at the customer’s usage summary.
Fetching the object means an out-of-date event can never overwrite newer state. When the cause was an API request, reason carries its request_id and idempotency_key, so you can match the event to your own call.
Verify deliveries
Deliveries follow the Standard Webhooks specification, so its open-source libraries verify them. Each delivery has three headers:
webhook-id: unique per event and the same on every retry. Use it to drop duplicates.webhook-timestamp: when this attempt was signed. Reject attempts more than five minutes old.webhook-signature:v1,followed by a base64 HMAC-SHA256 ofid.timestamp.body, keyed with the endpoint’swhsec_secret.
Verify against the raw body, before any JSON parsing changes it. While a secret is rotating, deliveries carry two signatures and either one passes.
Delivery
- At least once, so deduplicate on
webhook-id. - In no guaranteed order. Fetch the object instead of relying on order.
- Any
2xxwithin 15 seconds counts as delivered. Anything else is retried with exponential backoff for three days. - An endpoint that fails every delivery for five days is disabled automatically, and
statusbecomesdisabled. Each endpoint reportslast_success_at,last_failure_at,failing_sinceanddisables_at, so you can see a failing endpoint before it is disabled. Setstatusback toenabledwithPATCH /v1/webhook_endpoints/{id}once the endpoint works again. - Missed events are not replayed automatically. An event that failed all its retries stays
failed, and events that happened while an endpoint was disabled are not sent to it when you enable it again. Redeliver is manual and per event: find them withGET /v1/webhook_events?delivery_status=failed(or byendpoint), and send each one withPOST /v1/webhook_events/{id}/redeliver. The list keeps the last 30 days, so redeliver within that window. POST /v1/test_helpers/webhook_endpoints/{id}/send_eventsends a signed sample event to one endpoint in the sandbox, so you can test a handler and its signature check.GET /v1/webhook_eventslists the last 30 days, so you can catch up after an outage, andPOST /v1/webhook_events/{id}/redeliversends one event again, to one endpoint or to every enabled endpoint subscribed to its type. Nothing redelivers for you. Each event has adelivery_statusofpending,succeededorfailed, and the list filters bydelivery_statusand byendpoint.
Event types
New types may be added; subscribe only to the ones you handle.
See also
- Going live shows how to wire up webhooks and disputes.
- Outcome settlement explains the lifecycle the events report.