Dashboard
Binboi Docs/Monitoring/Webhooks

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.dev

Register 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:3003

Common 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-webhooks

The 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 200 from your handler confirms the payload was processed; non-2xx responses are highlighted in the inspector