hook.testtau.com — Webhook capture
POST, PUT, GET, anything — to https://hook.testtau.com/<hookId> and inspect every request live at https://hook.testtau.com/_/<hookId>.
Quick start
curl -X POST https://hook.testtau.com/my-hook-id \
-H 'content-type: application/json' \
-d '{"event":"hello"}'
What's captured
- Method, full path including subpaths and query string.
- Every header (except CF-internal ones).
- Client IP and country (from Cloudflare).
- Full request body, up to 1 MiB.
Configurable response
By default the hook responds with 200 {"ok":true}. Open the inspector and click ⚙ to change status code, body, or content-type — useful when testing how your sender handles a 4xx or 5xx.
Replay
Any captured request can be re-sent against another URL — handy for forwarding a recorded production event to your local dev environment.
Schema assertions NEW
Attach a JSON Schema to a hook and every captured request body is validated against it. Pass/fail shows up next to each request in the inspector, and a dedicated /assert endpoint returns 200 or 422 so CI can gate a build on it.
Setting a schema
Open the inspector at https://hook.testtau.com/_/<hookId> and click the Schema button. Paste a JSON Schema (draft 2020-12 or draft-07) and pick a fail mode:
- Record (default) — failing requests are marked red in the inspector, but the hook still responds with its configured 2xx. Use this when you want to observe without disrupting the sender.
- Reject — failing requests get an immediate
422with the validation errors in the body. Use this when your sender has a retry policy and you want to force a fix.
Example schema
{
"type": "object",
"required": ["event", "user_id"],
"properties": {
"event": { "type": "string", "enum": ["signup", "login", "logout"] },
"user_id": { "type": "string", "pattern": "^u_[a-z0-9]+$" }
},
"additionalProperties": false
}
CI gating
The /assert endpoint summarises the last N captures:
curl -fsS "https://hook.testtau.com/_/<hookId>/api/assert?since=$(date +%s%3N)&min_count=1"
Returns 200 with a JSON summary when all captures since the given timestamp passed (and there were at least min_count of them); returns 422 with the same summary otherwise. curl -f turns that into a non-zero exit code that fails the build.
GitHub Actions example
jobs:
contract:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Trigger webhook sender
run: ./scripts/fire-webhook.sh
- name: Wait for capture + assert schema
run: |
START=$(date +%s%3N)
sleep 10
curl -fsS \
"https://hook.testtau.com/_/<hookId>/api/assert?since=$START&min_count=1" \
| tee assert.json
Limits
| Body size | 1 MiB |
| Retention | 48 h |
| Capture rate limit | 120 requests/minute per IP |
| Hook id rate limit | 300 requests/minute per hook id |
| Schema size | ~50 KiB (lives in the DO's config row) |
| Errors returned per request | first 20 |
Reserved paths
Hook ids matching _, health, favicon.ico, robots.txt, admin, or api are reserved.