Skip to main content
Webhooks tell your server when your funding intents, payments and refunds change. Fulfil orders on funding.credited: it arrives only after the payment is verified, settled and credited, and it reaches you even when your user has closed the page.

1. Add an endpoint

In the dashboard, open Developers → Webhooks → Add endpoint, or create one with the SDK. The signing secret is returned once, when the endpoint is created. Store it with your other secrets.
Pass ["*"] to receive every event, including types added later. Endpoint URLs must be public https:// addresses.

2. Verify and handle events

constructEvent checks the signature over the raw request body and returns the typed event. Never verify re-serialized JSON: the bytes must be exactly what was sent.
Answer 2xx quickly and do slow work afterwards. A request that takes longer than 10 seconds counts as failed.

3. Make your handler safe to repeat

The same event can arrive more than once. Every delivery of an event carries the same id and Useroutr-Event-Id, so record the ids you have handled and skip repeats. Treat a webhook as a signal: when it matters, read the current state with the SDK.

Events

data.object is the resource as it is when the event is sent, which can already be further along than the event’s type. Use type for what happened and the object for the current state.

Retries

Retries back off exponentially, from 30 seconds up to an hour between attempts, for up to 8 attempts. Every attempt is recorded. Retry a failed delivery from the dashboard, or with the SDK:
Every event is kept whether or not an endpoint received it, so you can replay what you missed with useroutr.webhooks.events.iterate().

Signatures in detail

The SDK does this for you. To verify by hand, read t and every v1 from the Useroutr-Signature header (t=<unix seconds>,v1=<hex>), then compute:
Accept if any v1 matches under a constant-time comparison and t is within five minutes.

Rotating the secret

For 24 hours both the old and the new secret sign every delivery, so you can deploy the new one without missing an event. Pass both while you switch: secret accepts an array.