Allerto API

Webhooks

Allerto posts JSON events to the URL in the agent's delivery (or to a call's callback_url).

EventWhen
call.completedOnce per call, when it has ended for good: with outcome, result, summary, sentiment
{
  "id": "evt-uuid",
  "type": "call.completed",
  "version": "2",
  "created_at": "2026-09-21T14:29:14Z",
  "livemode": true,
  "partner_id": "…",
  "call": { "…": "the call object, see Calls and campaigns" }
}

livemode: false marks events produced by test keys. For inbound agents with review: on_issues, the event is sent after an operator approves the data when something was missing.

Signing secret

One secret per account signs every event:

POST /v1/webhook-secret        →  {"secret": "whsec_…"}
allerto webhook-secret rotate

It is shown once. Rotating takes effect immediately: every delivery from then on, including retries of events that failed before the rotation, is signed with the new secret. Update your receiver right after rotating, then retry failed events. An agent whose delivery uses a webhook cannot be published until a secret exists.

Verify every request

Headers:

Content-Type: application/json
Idempotency-Key: <event id>
X-Allerto-Event-Id: <event id>
X-Allerto-Timestamp: <unix seconds>
X-Allerto-Signature: sha256=<hex HMAC-SHA256 of "<timestamp>.<raw body>">

Node.js:

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

export function verify(rawBody, headers, secret) {
  const ts = headers["x-allerto-timestamp"];
  const got = Buffer.from(
    String(headers["x-allerto-signature"]).replace(/^sha256=/, ""),
    "hex",
  );
  const want = createHmac("sha256", secret).update(`${ts}.${rawBody}`).digest();
  const fresh = Math.abs(Date.now() / 1000 - Number(ts)) < 300;
  return fresh && got.length === want.length && timingSafeEqual(got, want);
}

Python:

import hmac, hashlib, time

def verify(raw_body: bytes, headers, secret: str) -> bool:
    ts = headers["X-Allerto-Timestamp"]
    got = headers["X-Allerto-Signature"].removeprefix("sha256=")
    want = hmac.new(secret.encode(), f"{ts}.".encode() + raw_body, hashlib.sha256).hexdigest()
    return abs(time.time() - int(ts)) < 300 and hmac.compare_digest(got, want)

Always verify against the raw body, before parsing JSON.

Delivery guarantees

Email delivery

Inbound agents can also send each result by email (delivery.mode: "email" or "both"), with the subject and introduction you configure and, optionally, a short AI summary. Test keys never send emails.