Webhooks

Webhooks push events to your backend as they happen, so you do not have to poll.

Subscribing

Register an endpoint and pick the events you want. Subscriptions are validated against the catalog below, so a typo cannot silently swallow deliveries. GET /webhooks/events returns the same catalog.

An endpoint can also carry:

  • timeout_seconds - how long to wait for your response, from 1 to 300. The default is 10 seconds.
  • headers - extra headers sent with every delivery.
  • auth_header - sent as the Authorization header, for a receiver that expects one. It is write-only: reads report only whether one is set.

Custom headers cannot replace the signature, event or delivery headers below.

Events

EventWhen
session.startedA session or call has started.
session.completedA session or call finished. Carries the end-of-call report: transcript, variables, cost, latency.
transcript.updatedA new turn was added to a live session.
function.calledThe model invoked a tool during a live call.
voicemail.detectedAn outbound call Glytos placed was answered by a machine, as reported by the carrier's answering-machine detection.
call.recording.readyA recording finished processing. Carries the session uuid; fetch the audio from the session with your API key.
sip.trunk.registeredA SIP trunk registered with its carrier and can take calls.
sip.trunk.downA SIP trunk lost its registration. Calls to its numbers will not arrive.
workflow.publishedAn agent version was published.
workflow.promotedAn agent was promoted to another environment.
member.invitedA member was invited to the organization.

session.completed is the one most integrations need: it is the whole conversation and its outcome in one delivery. It carries no recording address; see Sessions.

What a delivery looks like

Every delivery is a JSON POST. The body names the event and carries its payload under data:

{
  "event": "call.recording.ready",
  "data": { "session_uuid": "..." }
}

It comes with these headers:

HeaderWhat it is
X-Glytos-SignatureThe signature, described below.
X-Glytos-EventThe event type, the same as event in the body.
X-Glytos-DeliveryThe delivery id. A redelivery sends the same id again.

Verifying a delivery

Every delivery is signed. The signature is an HMAC-SHA256 over the timestamp and the raw body, sent as:

X-Glytos-Signature: t=<timestamp>,v1=<signature>

Verify it before trusting a payload:

import { verifyWebhook } from '@glytos/node';

// `rawBody` must be the untouched request body.
const ok = verifyWebhook(rawBody, req.headers['x-glytos-signature'], secret);

Every server SDK ships this check - Node, Python, PHP, Go and .NET - so you do not have to implement it; see the SDKs. Each also rejects a delivery whose timestamp is more than five minutes old, which you can change through its tolerance argument. In any other language it is the few lines above.

Verify against the raw request body, before any JSON parsing. Parsing and re-serialising changes the bytes and the signature will never match.

Reject deliveries whose timestamp is old; the SDK helpers do this by default. If you verify by hand, add the check yourself. Without it a captured, valid delivery can be replayed at you later.

Expectations

Return a 2xx quickly and do the work afterwards. A handler that blocks on slow work is a handler that times out.

A delivery is attempted once. A non-2xx response, a timeout or an unreachable endpoint marks it failed, and it is not retried automatically. List deliveries with GET /webhooks/deliveries (filter by status and event_type) and resend one with POST /webhooks/deliveries/{delivery_id}/redeliver. If missing an event matters, check for failed deliveries rather than assuming every event arrived.

A redelivery can reach you after the original did, so make handling an event idempotent - key on the session uuid or on X-Glytos-Delivery rather than assuming exactly-once.