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.
Events
| Event | When |
|---|---|
session.started | A session or call has started. |
session.completed | A session or call finished. Carries the end-of-call report: transcript, variables, cost, recording, latency. |
transcript.updated | A new turn was added to a live session. |
voicemail.detected | An inbound call was answered by a machine. |
call.recording.ready | A recording finished processing and is available. |
workflow.published | An agent version was published. |
workflow.promoted | An agent was promoted to another environment. |
member.invited | A 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.
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);from glytos import verify_webhook
ok = verify_webhook(raw_body, request.headers["X-Glytos-Signature"], secret)parse_str(str_replace(',', '&', $header), $parts); // t=...,v1=...
$expected = hash_hmac('sha256', $parts['t'] . '.' . $rawBody, $secret);
$ok = hash_equals($expected, $parts['v1']);mac := hmac.New(sha256.New, []byte(secret))
mac.Write([]byte(timestamp + "." + string(rawBody)))
ok := hmac.Equal([]byte(signature), []byte(hex.EncodeToString(mac.Sum(nil))))expected = OpenSSL::HMAC.hexdigest('SHA256', secret, "#{timestamp}.#{raw_body}")
ok = Rack::Utils.secure_compare(expected, signature)The Node and Python SDKs ship this as verify() so you do not have to implement it -
see the SDKs. In any other language it is the six 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. Without that check 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. Deliveries can arrive more than once, so make handling an event idempotent - key on the session id rather than assuming exactly-once.