Stripe webhooks
Payment, subscription and payout events, with the timestamp tolerance Stripe specifies.
In short
- Verification: the provider’s own HMAC signature over the raw body.
- Deduplication: The event
idin the body. - Once verified, the event joins your catalogue with the same retries, log and replay as anything you publish yourself.
The contract
| Field | Value |
|---|---|
| Provider key | stripe |
| Header checked | Stripe-Signature: t=<unix>,v1=<hex> |
| Scheme | HMAC-SHA256 over <timestamp>.<raw body>. The timestamp must be inside a five-minute window, which is what makes a captured request useless later. |
| Deduplicated on | The event id in the body |
| Event type | The type field becomes stripe.payment_intent.succeeded and similar. |
Setting it up
# 1. create a verified source; the secret is shown once
curl -X POST https://api.hookget.com/v1/sources \
-H "authorization: Bearer $HOOKGET_KEY" \
-H "content-type: application/json" \
-d '{"provider":"stripe","name":"Production"}'
# {"id":"src_…","secret":"whsec_…","ingest_path":"/ingest/src_…"}
- In the Stripe dashboard, open Developers → Webhooks → Add endpoint.
- Paste the ingest URL. Stripe issues its own signing secret — put that value into the HookGet source as the secret.
- Select the event types you need.
Worth knowing. The signature covers the timestamp as well as the body, so a replayed request outside the window is refused even though the HMAC is arithmetically correct. That is the point of it.
What you get after verification
- The event appears in your log with a namespaced type, so Stripe traffic never collides with your own.
- It fans out to your destinations with the same retry schedule and dead-letter behaviour as any other event.
- The source secret rotates with an overlap window, so you can update Stripe at your own pace.
- Each inbound source is rate limited on its own, so a busy provider cannot exhaust your publish budget.
Questions
How do I verify a Stripe webhook?
HMAC-SHA256 over <timestamp>.<raw body>. The timestamp must be inside a five-minute window, which is what makes a captured request useless later. With HookGet you do not implement it: the source is created with a secret,
and every request is checked against Stripe-Signature: t=<unix>,v1=<hex> before the event exists.
What happens if Stripe sends the same event twice?
Redeliveries are deduplicated on The event id in the body, namespaced per source, so a repeat becomes
the same event rather than a second one.
What if verification fails?
The request is refused with 401 and nothing enters the pipeline. The rejection is logged on our side as a signal worth watching; the caller learns nothing beyond the status.