Webhooks
Get every matching event POSTed to your endpoint, signed and retried. A Pro feature.
- Create a webhook
On Webhooks, click New webhook, give it a name and an HTTPS URL. The signing secret is shown once — store it.
- Pick filters
Filters are AND-ed; leave one empty to match everything. Filter by platform (e.g. only Sherlock), program type (bug bounty vs competition), event type (e.g. only
commit.new), or tag. To cut commit noise, enable code changes only: commits that touched solely docs, tests, or CI are suppressed, so you only get commits that changed in-scope source. This only gates commits — releases and tags always deliver. - Send a test event
Use Send test on the webhook to fire a
test.syntheticdelivery and verify your endpoint before real traffic arrives.
Delivery format
Each event is an HTTP POST with a JSON body:
{
"id": "dlv_...",
"type": "commit.new",
"program_id": "prg_...",
"asset_id": "ast_...",
"data": { "repo": "...", "branch": "...", "sha": "...", "message": "...", "url": "..." }
} data varies by event type. Event types: commit.new, pr.new, release.new,
tag.new, asset.added, program.created, program.updated,
audit.published, competition.opened, competition.judging,
competition.completed, and test.synthetic.
On commit.new, data also carries:
code_changed—truewhen the commit touched in-scope source,falsewhen it changed only docs, tests, or CI. Omitted when we couldn’t determine the changed files (e.g. a merge commit).summary— a one-line description of what changed (e.g."adds nonReentrant guard to withdraw()"). Omitted when unavailable.
Headers on every delivery:
X-BountyHunt-Signature: v1=<hex>— HMAC signature (below)X-BountyHunt-Timestamp— unix seconds when the delivery was signedX-BountyHunt-Event— the event typeX-BountyHunt-Delivery— the delivery id
Verifying signatures
The signature is HMAC-SHA256 over timestamp.delivery_id.event_type.body,
keyed with your webhook secret:
const expected = crypto
.createHmac('sha256', SECRET)
.update(`${ts}.${deliveryId}.${eventType}.${rawBody}`)
.digest('hex')
// compare against the hex after "v1=" using a constant-time comparison ts, deliveryId, and eventType come from the headers above; rawBody is the
exact request body. Reject if the signature mismatches or the timestamp is older
than a few minutes.
Retries and failures
Respond with a 2xx within 10 seconds. Anything else is retried up to 5
times with backoff (30s, 2m, 10m, 30m, 1h). After 10 consecutive exhausted
deliveries the webhook is auto-disabled — re-enable it from the dashboard once
your endpoint is healthy. Every attempt is visible in the webhook’s delivery
log.
Limits
Up to 10 webhooks per account; test events are limited to 30 per hour. Deliveries pause while your plan is Free and resume when you’re back on Pro.