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
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.
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
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.
| Tool | Does |
|---|---|
| create_endpoint | Create a disposable URL. |
| wait_for_request | Block until a request lands, then return it. Use this rather than asking someone to paste. |
| list_requests | Recent requests, newest first. |
| get_request | One captured request in full. |
| diagnose_signature | Find which step of verification is failing, against a captured request or a pasted body. |
hooks://guide — the full workflow and how to read a diagnosis.hooks://providers/{provider} — signature reference for one provider.debug-webhook, capture-webhook — prompts that encode the
capture-then-diagnose order.Reference
Generated from the same table the diagnosis engine runs on, so it cannot drift from what the tool actually does.
| Provider | Header | Signs | Digest | Window | Which 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
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
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.