Webhooks
Get the signing secret for a webhook URL, send a test delivery, read the delivery history, and rotate secrets without dropping events.
Jobs (crawls, batches, videos, routine runs) post their events to the URL you pass in webhook. Each delivery is signed with a secret that belongs to that URL. Jobs, streams and webhooks shows the payload and how to verify it; this page covers the secret and the history.
Get the secret
bashcurl -s https://beta-api.b3os.org/v1/webhooks/secret \ -H "Authorization: Bearer $B3OS_API_KEY" \ -H "Content-Type: application/json" \ -d '{"url": "https://example.com/hooks/b3os"}'
tsconst { secret } = await b3os.webhooks.getSecret({ url: "https://example.com/hooks/b3os" });
pythonsecret = b3os.webhooks.get_secret({"url": "https://example.com/hooks/b3os"})["secret"]
Webhook secrets belong in your receiver's configuration, not in an agent's context. Fetch them from code.
The first call for a URL creates its secret (whsec_...); later calls return the same one until you rotate it. URLs are compared after lowercasing the scheme and host and dropping a default port, so HTTPS://Example.com:443/hooks/b3os and https://example.com/hooks/b3os share a secret. The call needs platform:write.
Test the receiver
bashcurl -s https://beta-api.b3os.org/v1/webhooks/test \ -H "Authorization: Bearer $B3OS_API_KEY" \ -H "Content-Type: application/json" \ -d '{"url": "https://example.com/hooks/b3os"}'
B3OS sends one signed webhook.test event now and returns the delivery with the outcome of that single attempt: status, last_status_code and last_error. Test deliveries are not retried.
Delivery history
GET /v1/webhooks/deliveries lists the last 7 days of deliveries, newest first, with their attempts, last status code, last error and next attempt. Filter with url, job_id or status (pending, retrying, succeeded, failed). Each delivery's id is the event ID in its body.
Failed deliveries are retried with backoff for 24 hours. Answer with a 2xx status quickly and do the work afterwards; deliveries come from the node through the egress guard, so receivers on private or loopback addresses never get them.
Rotate the secret
bashcurl -s https://beta-api.b3os.org/v1/webhooks/secret/rotate \ -H "Authorization: Bearer $B3OS_API_KEY" \ -H "Content-Type: application/json" \ -d '{"url": "https://example.com/hooks/b3os", "grace_s": 86400}'
For grace_s seconds (a day by default, up to 7 days) every delivery carries two v1 signatures, one per secret, and previous_valid_until says when the old one stops. Deploy the new secret to your receiver within that window; a receiver that accepts any matching v1 keeps working throughout.
Other webhooks
- Firecrawl-compatible jobs post Firecrawl's payloads with
X-Firecrawl-Signature: sha256=<hex>, signed with this same per-URL secret. See Firecrawl compatibility. - Webhooks into B3OS, which start routine runs, are a different thing: see triggers.