Docs menu

Outbound webhooks

Get finished reports and call summaries pushed to your systems as they happen, so you don't have to poll.

Setting up #

In Dashboard → Integrations → Add a destination, choose Webhook and enter your HTTPS endpoint. Pick the events you want. After you connect, a signing secret (whsec_…) is shown once. Store it with your endpoint's config. Slack, Microsoft Teams and Discord are also available as ready-made destinations.

Events #

EventSent when
report.completedAn AI report finishes, whether started from the dashboard, a schedule or the API
call.completedA call recording has been transcribed and summarised

Request format #

Each delivery is a POST with a JSON body and these headers:

HeaderValue
X-Summarix-Eventreport.completed or call.completed
X-Summarix-DeliveryDelivery ID, the same on every retry. Use it to ignore duplicates
X-Summarix-TimestampUnix seconds when the request was signed
X-Summarix-Signaturesha256= + hex HMAC-SHA256 of {timestamp}.{raw body} with your signing secret
report.completed
{
  "event": "report.completed",
  "workspace": "Acme (Pty) Ltd",
  "report": {
    "id": "cm…",
    "title": "Q3 sales performance",
    "url": "https://app.summarix.co.za/dashboard/reports/cm…",
    "summary": "Revenue grew 18% quarter-on-quarter…",
    "kpis": [{ "label": "Revenue", "value": "R 1 234 567" }],
    "insights": ["…"],
    "recommendations": ["…"]
  }
}
call.completed
{
  "event": "call.completed",
  "workspace": "Acme (Pty) Ltd",
  "call": {
    "id": "cm…",
    "url": "https://app.summarix.co.za/dashboard/calls/cm…",
    "title": "Billing query resolved",
    "summary": "Customer queried a duplicate debit order…",
    "sentiment": "positive",
    "outcome": "resolved",
    "agentName": "Thandi",
    "durationSec": 312,
    "startedAt": "2026-09-24T08:15:00.000Z",
    "followUpRequired": true,
    "actionItems": [{ "owner": "agent", "task": "Email corrected invoice", "due": "today" }]
  }
}

Verifying signatures #

Always verify the signature before trusting a webhook, and reject timestamps more than 5 minutes old to block replays. Use the raw request body, before any JSON parsing.

node (express)
import crypto from "node:crypto";

app.post("/summarix", express.raw({ type: "application/json" }), (req, res) => {
  const ts = req.header("X-Summarix-Timestamp");
  const sig = req.header("X-Summarix-Signature") ?? "";
  if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return res.sendStatus(400);
  const expected = "sha256=" + crypto.createHmac("sha256", process.env.SUMMARIX_WEBHOOK_SECRET)
    .update(`${ts}.${req.body}`).digest("hex");
  if (sig.length !== expected.length || !crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected))) return res.sendStatus(401);
  const event = JSON.parse(req.body);
  // … handle event.event
  res.sendStatus(204);
});
python (flask)
import hmac, hashlib, time, os
from flask import request, abort

@app.post("/summarix")
def summarix():
    ts = request.headers.get("X-Summarix-Timestamp", "0")
    sig = request.headers.get("X-Summarix-Signature", "")
    if abs(time.time() - int(ts)) > 300: abort(400)
    body = request.get_data()
    expected = "sha256=" + hmac.new(os.environ["SUMMARIX_WEBHOOK_SECRET"].encode(), f"{ts}.".encode() + body, hashlib.sha256).hexdigest()
    if not hmac.compare_digest(sig, expected): abort(401)
    event = request.get_json()
    return "", 204
php
$ts = $_SERVER['HTTP_X_SUMMARIX_TIMESTAMP'] ?? '0';
$sig = $_SERVER['HTTP_X_SUMMARIX_SIGNATURE'] ?? '';
$body = file_get_contents('php://input');
$expected = 'sha256=' . hash_hmac('sha256', $ts . '.' . $body, getenv('SUMMARIX_WEBHOOK_SECRET'));
if (abs(time() - (int)$ts) > 300 || !hash_equals($expected, $sig)) { http_response_code(401); exit; }
$event = json_decode($body, true);

Delivery & retries #

Respond with any 2xx within 15 seconds. Non-2xx responses and timeouts are retried with exponential backoff (after about 30 s, then 1 min), for up to 3 attempts in total. After that, the delivery is marked failed and the error is shown on the destination card. Deliveries can arrive more than once or out of order. X-Summarix-Delivery stays the same across retries, so use it to de-duplicate.

Webhook endpoints must be public HTTPS URLs. Private, loopback and cloud-metadata addresses are refused.