Webhooks
Binboi makes webhook development straightforward. Expose a local endpoint, receive webhook payloads from GitHub, Stripe, Slack, or any other service, and replay them as many times as you need without re-triggering the source.
Why Binboi for Webhooks
- Capture every payload — no more reading logs to figure out what GitHub sent
- Replay instantly — re-run any request with one command, no external trigger needed
- Inspect headers and bodies — see the exact signature headers, content types, and raw bodies
- Persistent URL — reserve a subdomain so your webhook URL stays stable across restarts
Basic Setup
Start a tunnel to your local webhook handler:
binboi http 3000 --subdomain my-webhooks
# Tunnel: https://my-webhooks.binboi.devRegister https://my-webhooks.binboi.dev/webhook as the destination in your webhook provider's dashboard. Incoming payloads will be forwarded to localhost:3000/webhook immediately.
Inspecting Webhook Payloads
Open http://localhost:4040 to see every incoming webhook in real time:
- Full request headers (including HMAC signature headers)
- Raw request body (JSON, form-encoded, or raw bytes)
- Response from your local handler
- Round-trip latency
Replaying Webhooks
Replay any captured request without re-triggering the source:
# Replay the last request
binboi replay last
# Replay a specific request
binboi replay req_abc123
# Replay with a custom header override (e.g. to test signature validation)
binboi replay req_abc123 --header "X-Hub-Signature-256: sha256=new_sig"Verifying Webhook Signatures
Most providers sign webhook payloads with an HMAC. Here is a Node.js example verifying a GitHub webhook:
import crypto from 'crypto';
import express from 'express';
const app = express();
app.use(express.raw({ type: 'application/json' }));
app.post('/webhook', (req, res) => {
const sig = req.headers['x-hub-signature-256'];
const hmac = crypto
.createHmac('sha256', process.env.GITHUB_WEBHOOK_SECRET)
.update(req.body)
.digest('hex');
if (`sha256=${hmac}` !== sig) {
return res.status(401).send('Invalid signature');
}
const event = JSON.parse(req.body);
console.log('Received event:', event.action);
res.status(200).send('OK');
});
app.listen(3000);Forwarding to Multiple Local Services
Use Binboi's routing rules to forward different webhook paths to different local ports:
binboi http --subdomain my-webhooks \
--route /github=localhost:3001 \
--route /stripe=localhost:3002 \
--route /slack=localhost:3003Common Webhook Providers
| Provider | Header | Payload Format |
|---|---|---|
| GitHub | X-Hub-Signature-256 | JSON |
| Stripe | Stripe-Signature | JSON |
| Slack | X-Slack-Signature | JSON / form |
| Twilio | X-Twilio-Signature | URL-encoded form |
| Shopify | X-Shopify-Hmac-Sha256 | JSON |
Persistent Webhook URL
Use a reserved subdomain so the URL never changes between restarts:
binboi http 3000 --subdomain my-webhooksThe subdomain is reserved to your account while your tunnel is active. To hold it across sessions, reserve it permanently from the Binboi dashboard.
Debugging Tips
- Enable debug logging for raw header output:
binboi http 3000 --log-level debug - Use the replay API in test scripts:
curl -X POST http://localhost:4040/api/requests/req_abc123/replay - Check response codes — a
200from your handler confirms the payload was processed; non-2xx responses are highlighted in the inspector
