Send signed webhooks
Let your users register an endpoint, and deliver each event to it from a job, signed as Standard Webhooks and retried on a growing delay.
Last updated
After reading this guide, you will know
- What guides build outgoing webhooks, and in what order to follow them
- Where an endpoint's URL is checked and its signing secret is kept
- How your users verify a delivery with any Standard Webhooks library
By the end of this recipe your users register a URL and receive a signed POST there whenever
an event happens in your app. Each delivery runs in its own job, so a slow endpoint holds up
nobody else, and a failed one is retried on a growing delay. Deliveries follow Standard Webhooks,
so your users verify them with any library that implements it.
Register an endpoint
The URL is one a user typed, so refuse private and reserved hosts when it is saved, as
Refuse the URL at the endpoint
does. Mint the endpoint's whsec_ secret as the end of
Send webhooks of your own
describes, show it once, and store it with sealSecret from
Seal secrets at rest.
Run deliveries as jobs
Declare webhooks.deliver as
Declare the job a delivery becomes
does, and build the queue, the dispatcher and ctx.jobs with
Background jobs and cron.
Sign and deliver each event
Write the delivery job from
Send webhooks of your own,
opening the stored secret with openSecret before Webhooks.sign. Where the event happens,
store it and call ctx.jobs.enqueueMany(jobs.webhooks.deliver, …) with one input per endpoint.
For an endpoint that answers 429 with Retry-After, wait as long as it asks:
Honor Retry-After.
Tell your users how to verify
Each delivery carries the webhook-id, webhook-timestamp and webhook-signature headers
Standard Webhooks defines, so your documentation names the standard and the endpoint's secret.
A user on Remix verifies with @sdxc/webhooks as
Verify, then enqueue shows.
Test it
Test each stage as its guide does: Test the exact delays checks the waits between attempts, and Test the receiver signs a delivery the way your job does.
Where to go next
Fetch URLs a stranger chose — check where an endpoint's name resolves, beyond its spelling.
Sign and verify HTTP requests — sign with a key pair, so users verify without a shared secret.
Retry on a growing delay — test the exact delays your deliveries wait.