Documentation

Webhooks

Stop polling. Register a webhook and BIE will POST completed intelligence to your endpoint the moment analysis finishes, signed with HMAC-SHA256 so you can trust the sender.

Registering a webhook

Add an endpoint under Settings → Webhooks in the app. Paste your HTTPS URL, choose which events to subscribe to, and BIE generates a signing secret shown exactly once, copy it immediately. The secret is stored encrypted and used to sign every delivery.

Caution
The signing secret is never retrievable after creation. If you lose it, delete the webhook and add a new one.

Event types

Subscribe to any combination of four events per endpoint:

layer_z_threshold_crossed, a scored human turn pushed a Layer Z dimension (trust calibration, frustration buildup, or dependency drift) into the broken band (above 0.55) on a deployment.
anomaly_detected, a rated behavioral anomaly fired on a deployment.
uhr_generated, a weekly User Health Report finished generating.
outcome_shift_detected, a deploy event meaningfully moved the conversation resolved-rate before vs after (at least 3 points, at least 30 conversations each side, statistically significant), measured once the post-deploy window settles.

Payload shape

BIE sends a POST request with a stable envelope (id, event_type, version, created_at, org_id, deployment_id, and an event-specific data object) plus three headers: X-BIE-Event identifies the event type, X-BIE-Signature carries an HMAC-SHA256 of the raw request body using your webhook secret, and X-BIE-Delivery is a stable id you can use to deduplicate retries.

http
POST /webhooks/bie HTTP/1.1
Content-Type: application/json
X-BIE-Event: layer_z_threshold_crossed
X-BIE-Signature: sha256=a1b2c3...
X-BIE-Delivery: wh-7f3c...-lzx:9a2e...:frustration_buildup

{
  "id": "lzx:9a2e...:frustration_buildup",
  "event_type": "layer_z_threshold_crossed",
  "version": "webhooks-v1.0",
  "created_at": "2026-05-28T17:04:11.000Z",
  "org_id": "8b1d...",
  "deployment_id": "b25f7018-...",
  "data": {
    "dimension": "frustration_buildup",
    "score": 0.72,
    "threshold": 0.55,
    "band": "broken",
    "conversation_id": "c3f0...",
    "conversation_external_id": "conv_0000080",
    "signal_id": "a17c...",
    "occurred_at": "2026-05-28T17:04:10.000Z"
  }
}

Verifying the signature

Always verify the signature before trusting a payload. Compute HMAC-SHA256 of the raw request body using your webhook secret and compare against X-BIE-Signature using a constant-time comparison.

typescript
import { createHmac, timingSafeEqual } from 'node:crypto'

function verifySignature(rawBody: string, header: string, secret: string): boolean {
  const expected = 'sha256=' + createHmac('sha256', secret).update(rawBody).digest('hex')
  const a = Buffer.from(expected)
  const b = Buffer.from(header)
  return a.length === b.length && timingSafeEqual(a, b)
}

Retries and delivery status

A delivery succeeds when your endpoint returns a 2xx status within 10 seconds. Failed deliveries (non-2xx, timeout, or connection error) retry with exponential backoff up to 5 attempts; after the fifth failure the delivery is marked failed and stops. Every attempt is recorded under Settings → Webhooks, where you can see the status, response code, attempt count, and error for recent deliveries, and fire a test event at any endpoint.

Idempotency

Each event carries a stable id and X-BIE-Delivery header. The same event is never re-queued for the same endpoint, but retries reuse the same delivery id, key on it if you need exactly-once processing.