ActessiaBook a 30-day pilot
Documentation

Escalation webhook

When a conversation goes to a person: the payload, the signature to verify, retries, the email fallback and business hours.

A conversation is escalated when the visitor asks for a person, when two tool calls fail in a row, when the same question is rephrased three times, or when the agent finds no source for a question (at the sensitivity you choose). The full transcript goes to your webhook; email is the fallback.

The request

POST https://hooks.your-company.example/actessia
Content-Type: application/json
X-Actessia-Delivery: 3f0d…      (stable across retries)
X-Actessia-Timestamp: 1758000000
X-Actessia-Signature: v1=HMAC-SHA256(secret, timestamp + "." + body)

The body is EscalationPayload: version (v1), escalation_id, tenant_id, site_id, session_id, triggered_at, trigger (user_request, tool_failures, rephrasing, turn_budget, session_cap, unanswered), trigger_detail, end_user (null for anonymous sessions), visitor_id, page_url, language, context (your setContext() data), transcript[] (redacted), tool_calls[], summary, and dashboard_url, a deep link to the transcript in your dashboard. A test-fire from the dashboard carries test: true.

Verify the signature

import { createHmac, timingSafeEqual } from "node:crypto";

export function verify(secret, headers, rawBody) {
  const ts = headers["x-actessia-timestamp"];
  const expected = "v1=" + createHmac("sha256", secret).update(`${ts}.${rawBody}`).digest("hex");
  const given = headers["x-actessia-signature"] ?? "";
  if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false; // five minutes of skew
  return given.length === expected.length && timingSafeEqual(Buffer.from(given), Buffer.from(expected));
}

Use the raw request body, not a re-serialised one. Answer 2xx within 10 seconds.

Retries and the fallback

A non-2xx answer or a timeout is retried five times with exponential backoff (30 s, 60 s, 2 min, 4 min, 8 min), the same X-Actessia-Delivery id each time. After the fifth failure the escalation goes to the fallback email you configured, with the transcript attached as JSON. With no webhook, email is the target; with neither, escalations are recorded on the dashboard and nobody is notified; the page says so.

Business hours

Set a time zone and hours. Outside them, either deliver anyway or hold until the next opening and tell the visitor a person follows up then. Frustration signals still offer a person at any hour; only the delivery waits.