What this is
Webhooks are a Premium-tier-only push channel. Instead of polling/v1/arb/live or holding a WebSocket connection open, you give us an
HTTPS URL and we POST the same opportunity payload to you the moment
the engine detects it — typically within ~100 ms of the underlying
snapshot arriving.
Use this if you’d rather not run a persistent process to receive
signals. A serverless function (Cloudflare Worker, Vercel function,
Lambda) wakes up only when a real signal fires.
Registering a webhook
- Open
/dashboard/webhooks. - Click Create webhook.
- Fill in:
- URL —
https://your-domain.com/webhook(must be HTTPS) - Label — anything memorable, e.g.
prod-bot - Tier filter —
logical,endgame, or both - Ticker filter — subset of
BTC,ETH,SOL(omit for all)
- URL —
- The success callout shows the signing secret ONCE
(starts with
whsec_…). Save it. You can’t retrieve it later — if you lose it, delete the webhook and recreate.
What each POST looks like
Header reference
Body fields
Verifying the signature
Always verify. Without the check, anyone with your URL could POST fake opportunities. The signature is a hex-encoded HMAC-SHA256 over the raw request body bytes (not the parsed JSON) using your secret as the key.Delivery semantics
- Timeout: 5 seconds. Reply 2xx within that or we treat the delivery as failed.
- Auto-pause: 10 consecutive failures → the webhook is paused. You’ll see it in
/dashboard/webhookswith a “Failing” badge; click Resume once your endpoint is back. - Idempotency: Each opportunity carries a unique
(market_id, detected_at)pair. We may re-fire the same opportunity if our worker restarts; deduplicate on that pair if your downstream isn’t idempotent. - At-least-once: Treat the delivery as at-least-once, not exactly-once. The Redis pub/sub channel + the retry loop means a single fire event can land twice in rare cases.
- No backfill on register: If signals fired before you created the webhook, you won’t get them later. Use
GET /v1/arb/liveto catch up on currently-actionable signals.
Quick local testing
The simplest test setup needs no servers:- Open webhook.site — you get a unique URL like
https://webhook.site/abc-…. - Paste that URL into the create-webhook form.
- Leave both tabs open. When an opportunity fires, you’ll see the POST appear in real time on webhook.site.
localhost:
Common mistakes
- Parsing the body before verifying the signature — most web frameworks parse JSON middleware-style. The signature is over the raw bytes, so middleware that re-serializes the body breaks verification. Capture raw bytes first, verify, then parse.
- HTTP, not HTTPS — we reject
http://URLs at registration time. Signatures don’t replace TLS; both matter. - Replying slowly — if your handler does heavy work synchronously, we may timeout before you ack. Acknowledge immediately, do the work in the background.
- No tier check downstream — we deliver to webhooks registered when the user was on Premium even if they later downgrade (we re-check tier at register time only). If you build a multi-tenant system on top, gate at your own layer too.
Pricing
Webhook alerts are included with the Premium plan. Free / Pro / Plus users can register webhooks via the dashboard but registration returns403. See pricing.