Webhooks
Subscribe to BoxOwl PDaaS events and receive real-time HTTP notifications to your endpoint.
Subscribe
POST
/api/v1/orgs/{slug}/webhooks
webhooks:write
curl -X POST https://api.boxowl.me/api/v1/orgs/acme/webhooks \
-H "X-API-Key: boxlive_01h455..." \
-H "Content-Type: application/json" \
-d '{
"url": "https://api.acme.com/webhooks/boxowl",
"events": ["consent.granted", "consent.revoked", "vault.updated"],
"description": "Production vault event handler"
}'
Response 201 Created:
{
"webhookId": "wh_01h455vb4pex5vsknk084sn02q",
"url": "https://api.acme.com/webhooks/boxowl",
"events": ["consent.granted", "consent.revoked", "vault.updated"],
"description": "Production vault event handler",
"status": "active",
"createdAt": "2026-04-27T12:00:00Z"
}
List Subscriptions
GET
/api/v1/orgs/{slug}/webhooks
webhooks:write
curl https://api.boxowl.me/api/v1/orgs/acme/webhooks \
-H "X-API-Key: boxlive_01h455..."
Unsubscribe
DELETE
/api/v1/orgs/{slug}/webhooks/{webhookId}
webhooks:write
Event Payload
BoxOwl sends an HTTP POST to your endpoint with a JSON body:
{
"id": "evt_01h455vb4pex5vsknk084sn02q",
"type": "consent.revoked",
"timestamp": "2026-04-27T14:30:00Z",
"organizationId": "org_01h455...",
"data": {
"connectionId": "con_01h455...",
"userId": "usr_01h455...",
"handle": "alice",
"scope": "vault:read"
}
}
Signature Verification
Each webhook request includes X-BoxOwl-Signature — an HMAC-SHA256 hex digest of the raw request body, signed with your API key secret.
Always verify signatures before processing payloads:
const crypto = require('crypto');
const sig = req.headers['x-boxowl-signature'];
const expected = crypto
.createHmac('sha256', apiKeySecret)
.update(rawBody)
.digest('hex');
if (sig !== expected) {
return res.status(401).send('Invalid signature');
}
Retry Policy
If your endpoint returns a non-2xx response or times out (10s), BoxOwl retries with exponential backoff:
- Attempt 1: immediate
- Attempt 2: 1 minute later
- Attempt 3: 5 minutes later
- Attempt 4: 30 minutes later
- Attempt 5: 2 hours later
After 5 failed attempts, the webhook is marked failed and no further retries occur. Inspect and replay from your dashboard.