When something happens in Telyzer (a call ends, a caller is owed a call back, an alert fires), it is published once as an event, in the same database transaction as the change itself. The same event then reaches your webhooks, the live views in the portal, and, as new Telyzer modules arrive, their screens too. An event is never sent for a change that did not happen.
The event catalogue
Every event type is listed, with its module and description, at GET /api/v1/events/types (public, no key needed). Webhooks can subscribe to any type in the catalogue.
curl https://app.telyzer.com/api/v1/events/types| Event | Sent when |
|---|---|
call.completed | A call ended: inbound or outbound, answered or not. Internal calls are not events. |
call.missed | An inbound call from outside was not answered, or went to voicemail. |
callback.opened | A missed caller is now owed a call back (they were not already waiting). See Callbacks. |
callback.closed | A waiting caller was called back, got through themselves, or was closed by hand. |
alert.triggered | An alert rule fired. |
report.delivered | A scheduled report was emailed. |
source.silent | A phone system stopped sending call records during working hours. |
- Call and callback events are sent once per call, when its last segment arrives. A file of old calls imported later is history, not news: calls that ended more than 7 days ago produce no events.
- Events carry a summary only, never recordings or audio. Phone numbers are masked unless the receiver may see them in full (see Masked numbers).
- Each type has a
version. A change that would break a receiver comes as a new type or version, never silently.
Webhook payloads: classic or CloudEvents
Each webhook has a Payload format. Classic is the default and the format Telyzer webhooks have always used, so existing receivers keep working unchanged:
{
"event": "call.missed",
"occurredAt": "2026-10-25T07:14:03.512Z",
"data": { "callId": "0192…", "direction": "inbound", "outcome": "unanswered", "number": "+966•••••••77", … }
}CloudEvents 1.0 wraps the same data in the standard CloudEvents envelope (JSON format, structured mode), which many tools and cloud services read natively:
{
"specversion": "1.0",
"id": "0192f3a1-7c4e-7b55-9a10-3c2d9e8b4f61",
"source": "/telyzer/cdr",
"type": "call.missed",
"subject": "calls/0192f3a1-7c4e-7b55-9a10-3c2d9e8b4f60",
"time": "2026-10-25T07:14:03.512Z",
"datacontenttype": "application/json",
"data": { "callId": "0192…", "direction": "inbound", "outcome": "unanswered", "number": "+966•••••••77", … }
}| Attribute | Meaning |
|---|---|
id | The event's unique id. Retries of a delivery carry the same id, so you can ignore duplicates. |
source | The Telyzer module that published it, e.g. /telyzer/cdr for Call analytics. |
type | The event type from the catalogue. |
subject | What it is about, e.g. calls/<call id> or callbacks/<missed call id>. |
time | When it happened (UTC). |
Both formats are signed the same way (X-Telyzer-Signature, see Verifying the signature) and carry the X-Telyzer-Event and X-Telyzer-Delivery headers. You can switch a webhook's format under Change events; the change applies to events queued from then on.
Live updates in the portal
The wallboard and the Callbacks page update as soon as a call ends, through a live stream of events (Server-Sent Events). If the stream is interrupted they keep refreshing on their own every few seconds, so a screen on the wall never stops.
- The stream is
GET /api/v1/events/stream, for signed-in members. Each message is a CloudEvents envelope;?types=narrows it to some types. - Members see the events their role allows (call events need permission to read calls), with numbers masked unless they may see them in full, and only for their own sites and departments if their access is limited.
- After a short interruption the browser reconnects and receives what it missed, up to an hour back. An organization can have up to 50 live connections open at once.
// In the portal (signed in): refresh a view when a call ends
const es = new EventSource("/api/v1/events/stream?types=call.completed,callback.opened");
es.onmessage = (m) => {
const event = JSON.parse(m.data); // a CloudEvents envelope
console.log(event.type, event.subject, event.data);
};
es.addEventListener("resync", () => location.reload()); // too much was missed to replayHow long events are kept
Events are kept for 30 days, and longer only while a webhook delivery of them is still being retried. Your call history itself follows your plan (see How long history is kept).