hooks.bot Docs

Catch a webhook, then find out why it fails.

hooks.bot gives you a disposable URL that records every request sent to it, and a debugger that rebuilds a failing signature every way it could plausibly have been made until it finds the one that matches — then tells you which step differs. No account, no API key.

Quick start

Get a URL and send it something

Open https://hooks.bot and an endpoint is already waiting. Or take one from the API:

curl -X POST https://hooks.bot/api/endpoints
# {"id":"abc…","url":"https://hooks.bot/h/abc…", …}

curl -X POST https://hooks.bot/h/abc…/anything -d '{"hello":"world"}'

Every method works, and any path below the endpoint is recorded as-is. Requests appear in the browser the moment they land — nothing needs refreshing.

Then diagnose it

Open a captured request and press Diagnose this signature. The payload and headers are handed to the debugger; add your signing secret and it reports the construction that reproduces what the provider sent.

The debugger runs entirely in your browser. The HMAC work happens via Web Crypto in the page, so a signing secret pasted there has nowhere to go. Check the network tab.

For agents

Drive all of it over MCP

Claude Code, Cursor and Codex can create an endpoint, wait for the webhook to land, and diagnose it — without you copying anything into a browser.

claude mcp add --transport http hooks-bot https://hooks.bot/mcp

Streamable HTTP, no authentication. The server also ships connect-time instructions, reference resources and prompts, so an agent arrives knowing how to use it.

Tools

ToolDoes
create_endpointCreate a disposable URL.
wait_for_requestBlock until a request lands, then return it. Use this rather than asking someone to paste.
list_requestsRecent requests, newest first.
get_requestOne captured request in full.
diagnose_signatureFind which step of verification is failing, against a captured request or a pasted body.

Resources and prompts

Reference

How each provider signs

Generated from the same table the diagnosis engine runs on, so it cannot drift from what the tool actually does.

ProviderHeaderSignsDigestWindowWhich secret
Stripe Stripe-Signature {timestamp}.{body} HMAC-SHA-256
hex
300s Endpoint signing secret from the Stripe dashboard, used whole: whsec_…
GitHub X-Hub-Signature-256 raw body HMAC-SHA-256
hex
— The webhook secret you typed when creating the webhook. No prefix, used as-is.
Svix / Standard Webhooks webhook-signature {id}.{timestamp}.{body} HMAC-SHA-256
base64
300s whsec_… — the prefix is stripped and the remainder base64-decoded to key bytes.
Shopify X-Shopify-Hmac-Sha256 raw body HMAC-SHA-256
base64
— Your app's client secret (API secret key) — not the API key, not an access token.
Slack X-Slack-Signature v0:{timestamp}:{body} HMAC-SHA-256
hex
300s Signing Secret from your app's Basic Information page — not a bot token.
Paddle Billing Paddle-Signature {timestamp}:{body} HMAC-SHA-256
hex
5s Notification destination secret key, pdl_ntfset_… — used as-is.
Twilio X-Twilio-Signature URL + sorted POST params HMAC-SHA-1
base64
— Your account Auth Token — not an API key secret.

Every provider has its own page with the exact scheme, the mistakes that actually happen, and a worked example: Stripe · GitHub · Svix / Standard Webhooks · Shopify · Slack · Paddle Billing · Twilio.

Stripe and Svix both hand you a secret starting whsec_ and treat it completely differently. Stripe uses the whole string as the key. Svix strips the prefix and base64-decodes the rest. Mixing the two up is the single commonest failure in this category.

HTTP API

Everything the page does, you can do

POST /api/endpoints                  Create an endpoint
GET  /api/endpoints/{id}             createdAt, expiresAt, count
GET  /api/endpoints/{id}/requests    ?limit=N, newest first
GET  /api/endpoints/{id}/ws          WebSocket live tail
ALL  /h/{id}/*                       Capture anything sent here

Machine-readable: /openapi.json, /llms.txt, MCP server card.

Limits

What you get, and for how long

Captured responses carry a restrictive Content-Security-Policy: an endpoint cannot serve active content and is not useful for hosting anything. There is no authentication anywhere — see /auth.md.