Webhooks

A webhook is a delivery action defined within a configuration. When an operator produces a result that meets the action's condition, the platform POSTs a JSON envelope to the action's webhook_url. Unlike the session event stream — which delivers everything — webhooks deliver only the results your actions select.

You define a webhook action with a webhook_url, an optional set of webhook_headers, and an optional condition. See Actions for conditions and once_per_session.

The envelope

Every delivery has the same shape:

{
  "session_id": "abc-123",
  "configuration_id": "5f1c…",
  "customer_metadata": { "your_ref": "xyz" },
  "fired_at": "2026-06-17T10:30:00.000Z",
  "type": "operator_result",
  "action": { "index": 2, "once_per_session": true },
  "data": { },
  "evaluated": {
    "fraud-confidence": { "result": { "value": 84 }, "confidence": 0.91, "call_elapsed_seconds": 42.0 }
  }
}
  • type — the kind of operator event that triggered delivery: operator_result or operator_error.
  • data — the full operator event that triggered the action. This is the same payload the session stream carries: see the operator_result and operator_error shapes.
  • evaluated — a per-operator summary (result, confidence, call_elapsed_seconds) of every operator the condition tested, so you can see exactly what satisfied it. null for an unconditional action.
  • customer_metadata — echoed verbatim from the value you supplied when the session was created; null if none was set.
  • action.index — the action's position in the configuration. When several actions post to the same URL, use it together with session_id to tell deliveries apart.
  • fired_at — the timestamp_utc of the triggering operator event.

Unconditional actions also fire on operator_error, where data has no result. Conditions that test result never match an error, so a conditional action only delivers operator_result. Read type before reading data.

Delivery

Each delivery is a single HTTP POST with a JSON body (Content-Type: application/json) and any webhook_headers you configured on the action. Your endpoint should return a 2xx status promptly — do slow work asynchronously after acknowledging. The platform waits up to 10 seconds for a response.

Retries

Outcome Behaviour
2xx / 3xx Treated as delivered.
4xx Permanent failure — not retried (a client error won't be fixed by retrying). Check your endpoint and headers.
5xx, timeout, or network error Retried with backoff.

Retried deliveries are attempted up to 3 times: the initial attempt, then again after roughly 5 seconds, then after roughly 30 seconds. If all three fail, the delivery is abandoned and logged.

Delivery is at-least-once. A retry can deliver the same event more than once, and an endpoint that is slow to acknowledge (but eventually succeeds) may still be retried. Make your handler idempotent — deduplicate on the triggering event id (data.event_id) together with action.index. For at-most-once-per-call business logic, set once_per_session on the action.

Securing your endpoint

Deliveries are not signed. To verify a request genuinely came from the platform:

  • Set a secret on the action's webhook_headers — for example { "Authorization": "Bearer <your-shared-secret>" } — and check it on every request.
  • Serve your endpoint over HTTPS.
  • Don't trust the payload's identifiers for authorisation on their own; gate on the shared secret first.
ActionsDefine webhook actions, conditions, and once_per_session within a configuration.Session eventsThe realtime stream that carries the same operator results, unconditionally.