Delivery behaviour
Read the response budget column first. The tightest sender you receive from is your real constraint, not the most familiar one.
| Provider | Response budget | Retry | Gives up / disables |
|---|---|---|---|
| Slacksource | 3s | 3 retries: immediately, after 1 min, after 5 min | Event subscriptions disabled if over 95% of attempts fail within 60 min |
| LINEsource | 2s Counted as request_timeout when the bot server has not answered within 2 seconds | Webhook redelivery, off by default (enable in the channel's Messaging API settings); count and interval undisclosed | May suspend webhook sending if the bot server keeps failing to receive them; threshold unpublished |
| Xerosource | 5s 200 within 5 seconds, with no body and no cookies; 401 when the signature is wrong | not verified | not verified |
| Discordsource | 3s Interaction endpoints must send an initial response within 3 seconds | not verified | not verified |
| Shopifysource | 5s 1 second to connect, 5 seconds for the whole request | 8 retries over 4 hours | Subscriptions created through the Admin API are deleted after 8 consecutive failures, with a warning email to the app's emergency developer contact |
| Paddlesource | 5s | Live: up to 60 attempts over about 2 days, about 10 in the first hour and about 45 in the first day. Sandbox: 3 attempts within about 2 min | not verified |
| HubSpotsource | 5s Applies to the whole batch, which can carry up to 100 notifications | Up to 10 attempts spread over 24 hours | not verified |
| GitHubsource | 10s | None. GitHub does not automatically redeliver failed deliveries | No disable. Deliveries stay redeliverable by hand for 3 days, then the record is gone |
| Meta (Instagram, Facebook, Threads)source | not published | Retried with decreasing frequency over 36 hours, then dropped. WhatsApp Cloud API retries for up to 7 days | not verified |
| Twiliosource | 15s Configurable. rt read timeout default 15000ms (max 15000), ct connect default 5000ms (max 10000), tt total default 15000ms | Configurable: rc 0 to 5, default 1. rp selects which failures qualify | not verified |
| Stripesource | not published Stripe publishes no figure. Its docs say only to return 2xx before any slow logic. 20s is the community working number | Exponential backoff for up to 3 days in live mode. Sandbox: 3 attempts over a few hours | Endpoint disabled after continued failure, with an email first. Events stay in the Events API for 30 days |
| Svix (Clerk, Resend)source | not published | 8 attempts: immediately, 5s, 5 min, 30 min, 2h, 5h, 10h, 10h. Then a message.attempt.exhausted operational webhook | Endpoint disabled after all attempts fail for 5 days |
| WooCommercesource | not published Delivery is queued into Action Scheduler and driven by WP-Cron, so it leaves when a page is next loaded rather than when the event happens | not verified | Webhook disabled after more than five consecutive delivery failures |
Two rows are worth reading twice. GitHub does not retry at all, so a failed delivery is lost unless somebody redelivers it inside three days. Paddle puts about 10 of its 60 attempts into the first hour and about 45 into the first day, which punishes a merely slow handler far harder than Stripe's curve.
Signature schemes
The signed payload column is the one that costs people hours. Anything other than raw body means you cannot hash the request body alone.
| Provider | Algorithm | Signed payload | Encoding | Header | Tolerance |
|---|---|---|---|---|---|
| Slack | HMAC-SHA256 | v0:{timestamp}:{body} | hex | x-slack-signature = v0=hex | 5 min |
| LINE | HMAC-SHA256 | raw body | base64 | x-line-signature = base64 | none |
| Xero | HMAC-SHA256 | raw body | base64 | x-xero-signature = base64 | none |
| Discord | Ed25519 | {timestamp}{body} | hex | x-signature-ed25519 + x-signature-timestamp | none |
| Shopify | HMAC-SHA256 | raw body | base64 | x-shopify-hmac-sha256 | none |
| Paddle | HMAC-SHA256 | {timestamp}:{body} | hex | paddle-signature = ts=X;h1=hex | 5s |
| HubSpot | HMAC-SHA256 | POST{decodedUrl}{body}{timestamp} | base64 | x-hubspot-signature-v3 | 5 min |
| GitHub | HMAC-SHA256 | raw body | hex | x-hub-signature-256 = sha256=hex | none |
| Meta (Instagram, Facebook, Threads) | HMAC-SHA256 | raw body | hex | x-hub-signature-256 = sha256=hex | none |
| Twilio | HMAC-SHA1 | full URL + form params sorted by key | base64 | x-twilio-signature | none |
| Stripe | HMAC-SHA256 | {timestamp}.{body} | hex | stripe-signature = t=X,v1=hex | 5 min |
| Svix (Clerk, Resend) | HMAC-SHA256 | {id}.{timestamp}.{body} | base64 | svix-signature = v1,base64 | 5 min |
| WooCommerce | HMAC-SHA256 | raw body | base64 | x-wc-webhook-signature | none |
| Lemon Squeezy | HMAC-SHA256 | raw body | hex | x-signature + x-event-name | none |
| PayPal | RSA-SHA256 | {txId}|{txTime}|{webhookId}|{crc32(body)} | base64 | paypal-transmission-sig + 4 more | none |
| SendGrid | ECDSA P-256 | {timestamp}{body} | base64 | x-twilio-email-event-webhook-signature | none |
| Linear | HMAC-SHA256 | raw body | hex | linear-signature | none |
| Sentry | HMAC-SHA256 | raw body, no timestamp | hex | sentry-hook-signature | none |
| Intercom | HMAC-SHA1 | raw body | hex | x-hub-signature = sha1=hex | none |
| Vercel | HMAC-SHA1 | raw body | hex | x-vercel-signature | none |
Use this data
The same table is served as JSON at /providers.json, under CC BY 4.0. Copy it, embed it, correct it. If a number here is wrong or a vendor has changed something, open an issue on the repo and it gets fixed here.
Attribution: AnyHook, Webhook Provider Behaviour Reference, https://anyhook.net/providers
Where each number came up
- GitHub does not retry, and the record expires in three days
- Slack's three seconds, and the 95% disable threshold
- Paddle's 60 attempts against Stripe's curve
- Twilio's configurable timeouts, and why the default retry never runs
- HubSpot's eventId is documented as not guaranteed unique
- Verifying signatures, provider by provider