Webhooks — bRRAIn Docs
Receiving events from bRRAIn — webhook subscription, signature verification, retries, and delivery semantics.
Webhooks
Webhooks let your systems react to events in your bRRAIn — a record being added, an orchestration completing, a member joining, an alert firing — without polling.
Subscribing
Create a subscription via the Console (Settings → Integrations → Webhooks → + Add subscription) or programmatically via the API:
POST /api/orgs/{org_id}/webhooks
Authorization: Bearer {token}
Content-Type: application/json
{
"url": "https://your-system.example.com/bRRAIn-hook",
"events": ["record.created", "record.updated", "orchestration.completed"],
"secret": "<32 bytes you generate>",
"active": true
}
The secret is used to sign every delivery. Store it in your secret manager.
Event types
A non-exhaustive list (more in the API explorer):
| Event | Fires when |
|---|---|
| record.created | A new record is added to a Vault zone. |
| record.updated | A record is modified. |
| record.deleted | A record is soft-deleted (hard-delete fires record.purged). |
| record.purged | Past-retention purge runs on a record. |
| member.joined | A new member accepts an invitation. |
| member.left | A member is removed or leaves. |
| member.role_changed | A member's role is changed. |
| extension.installed | A marketplace extension is installed. |
| extension.updated | An installed extension version changes. |
| extension.uninstalled | An extension is uninstalled. |
| orchestration.started | An orchestration run begins. |
| orchestration.completed | An orchestration run finishes successfully. |
| orchestration.failed | An orchestration run fails. |
| pod.healthy | The brain pod transitions to healthy. |
| pod.degraded | The brain pod transitions to degraded. |
| billing.charge_succeeded | A billing charge succeeds. |
| billing.charge_failed | A billing charge fails. |
| audit.high_severity | An audit-log entry tagged high severity is recorded. |
Delivery format
Every delivery is a POST of:
{
"id": "evt_8a2b3c...",
"type": "record.created",
"occurred_at": "2026-05-13T18:42:01.123Z",
"org_id": "org_AB123",
"data": {
"record_id": "rec_45678",
"zone": "engineering",
"actor_id": "usr_9876",
"title": "Design decision: pick database X for Y",
...
},
"delivery_attempt": 1
}
Signature verification
Each delivery carries an X-Bbi-Signature header:
X-Bbi-Signature: t=1715637721,v1=63d6...8e
t is the Unix timestamp at sending. v1 is the HMAC-SHA256 hex of {t}.{body} using your subscription secret.
To verify:
import hmac, hashlib, time
def verify(body: bytes, header: str, secret: str, max_age=300) -> bool:
parts = dict(p.split("=", 1) for p in header.split(","))
t = int(parts["t"])
if time.time() - t > max_age:
return False # stale
expected = hmac.new(
secret.encode(),
f"{t}.".encode() + body,
hashlib.sha256,
).hexdigest()
return hmac.compare_digest(expected, parts["v1"])
Always verify before processing. The t check rejects replays.
Retries
If your endpoint returns 2xx, the delivery is acknowledged and we move on.
If your endpoint returns 4xx, we retry with exponential backoff for 24 hours. After 24 hours of 4xx responses we mark the subscription as failing and notify your organization.
If your endpoint returns 5xx or times out (timeout is 10 seconds), we retry with exponential backoff for 72 hours.
Retry schedule: 30s, 1m, 5m, 15m, 1h, 6h, 24h, then daily until the cutoff.
Idempotency
Every delivery carries an X-Bbi-Idempotency-Key header equal to the event's id. Use it to deduplicate; we may deliver the same event more than once if our acknowledgment was lost in transit.
Ordering
Webhooks are delivered in approximately occurrence order. Strict ordering is not guaranteed across event types. If your processing depends on order, key off occurred_at and process in that order on your side.
Filtering
A subscription can include filters:
event_types— list of types to subscribe to.zones— only events from specified Vault zones.extensions— only events from specified extensions.actor_roles— only events with actors of specified roles.
Filters are anded together.
Test deliveries
From the Console, click Test on any subscription to fire a synthetic event of your choice. The test event is clearly tagged so you can ignore it in production processing.
Inspecting delivery history
Per-subscription history under Settings → Integrations → Webhooks → [Subscription] → Deliveries:
- Each delivery's payload, response, and result.
- Filter by event type, status code, time range.
- Re-send any delivery on demand.
Inbound webhooks (vendor → bRRAIn)
The opposite direction (vendors calling bRRAIn) is handled by integrations and the MCP Gateway. See Console: Integrations.
Where to next
- API: Authentication — for the bearer tokens used in subscription management.
- API: Errors — error format used in webhook health responses.
- Console: Notifications — the user-facing channels that webhooks complement.