Testing webhooks locally
Hosted test inbox, socialfetch listen forwarding, and triggering a check on demand.
You don't need a public URL to develop against webhooks. Use a hosted test inbox to inspect deliveries, or socialfetch listen to forward signed events to localhost.
Test inbox (sink endpoints)
A sink is a webhook endpoint with no URL. Monitors attach to it like a real endpoint — deliveries are signed and logged — but the signed request (headers + raw body) is captured instead of POSTed. The dashboard shows it as a live inbox: deliveries appear within seconds, each expandable to the full signed request.
The response includes a one-time secret — store it; it's shown only once. Read captured deliveries with:
Each delivery's requestHeaders and payloadText are byte-identical to what a real HTTP endpoint would receive. Verify them the same way as production (see Receiving & verifying webhooks).
Limits: 2 sinks per account, 30-day retention. In the monitor creation wizard, "test inbox" creates one for you.
socialfetch listen — forward events to localhost
Shipped in @socialfetch/sdk, modeled on stripe listen. It finds or creates a sink, polls deliveries, and forwards each one byte-exact to a local URL — original raw body, original socialfetch-* headers, real signature. Your local handler verifies it the same way as production.
Flags:
| Flag | Required | Description |
|---|---|---|
--forward-to <url> | yes | Local URL to forward events to. |
--api-key <key> | no | Defaults to SOCIALFETCH_API_KEY. |
--api-url <url> | no | Override the API origin. Defaults to production. |
--poll-interval-ms <ms> | no | Poll interval in milliseconds. Defaults to 2000. |
-h, --help | no | Show usage. |
What it does:
- Authenticates with
SOCIALFETCH_API_KEY(env or--api-key). - Finds or creates a sink described
cli-listenand reuses it on later runs. The secret is only printed on first create; rotate it if you've lost it. - Short-polls
GET /v1/webhook-endpoints/{id}/deliveries?after={cursor}every 2 seconds by default. Free management call. - Forwards each new delivery to
--forward-to, unmodified. - Prints event type, event id, and local response status/latency (or the local error).
No websockets or tunnels — a thin loop over the same APIs on this page.
Trigger a check on demand
POST /v1/monitors/{id}/trigger runs a check immediately:
Triggering is free; the poll it enqueues bills at the operation's normal per-check price. See Billing for monitors. Rate-limited to once per 60 seconds per monitor.
The full local dev loop
Terminal 1:
Terminal 2:
If the target has anything new since the last check, an event fires, lands in the CLI's sink, and is forwarded to your local server within seconds.
Send a synthetic test event instead
If you don't want to wait on real content changing, POST /v1/webhook-endpoints/{id}/test sends a sample event shaped from that source's schema (pass { "sampleType": "twitter.profile.tweets.new_items" } for a source-specific shape, or omit it for a generic one) and returns the delivery result inline. Works against a sink or a real endpoint. socialfetch listen forwards test events the same as real ones.
Where to go next
Receiving & verifying webhooks
Next.js, Hono, and Express handlers, plus the raw-body gotcha.
Delivery, retries & idempotency
Retry schedule, at-least-once delivery, and dedup guidance.
Billing for monitors
Per-check credits, dryRun previews, and plan limits.
Webhook endpoints API reference
Schemas for endpoints, deliveries, tests, and redelivery.