Webhooks
Allerto posts JSON events to the URL in the agent's delivery (or to a call's callback_url).
| Event | When |
|---|---|
call.completed | Once per call, when it has ended for good: with outcome, result, summary, sentiment |
call.attempt_failed | An outbound attempt was not answered and another is scheduled (next_attempt_at) |
{
"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 affects new events; events already queued keep the previous secret. 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
- At least once: store the event id and ignore repeats. The id and payload never change between retries; timestamp and signature do.
- Any
2xxacknowledges. Redirects are not followed. Timeout: 10 seconds. - Up to 5 attempts with growing delays (15 s, 30 s, 60 s, …, max 1 h).
- Destinations must be HTTPS on port 443 and resolve to public addresses.
GET /v1/events(orallerto events list) shows recent events and their delivery status.
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.