Webhooks
Teler delivers asynchronous events to your HTTPS endpoint as signed POST
requests. Use webhooks for state changes you can’t afford to poll for: call
lifecycle, stream lifecycle, and recording availability.
Delivery contract
Section titled “Delivery contract”| Property | Value |
|---|---|
| Transport | HTTPS POST, JSON body |
| Timeout | 5 seconds for your response |
| Success | Any 2xx response |
| Retry policy | Up to 5 attempts, exponential backoff (immediate to ~30 min) |
| Ordering | Best-effort per call_id. Use timestamps to reorder. |
| Idempotency | Each event has a unique ID. Dedupe on receive. |
| Signing | HMAC-SHA256, see Signing & verification |
Configure your endpoint
Section titled “Configure your endpoint”Webhooks are sent to:
- The Call Status URL on a Voice App, for inbound calls.
- The
status_callback_urlpassed tocalls.create(), for outbound calls. - The Call Status URL on a SIP Trunk, for trunk-routed calls.
Your endpoint must be HTTPS and reachable from the public internet.
Respond fast, process async
Section titled “Respond fast, process async”Your endpoint must return 2xx within 5 seconds. If you do real work
inline, such as database writes, downstream API calls, and slow integrations,
you risk timeouts and unnecessary retries.
Every production webhook handler should follow the same shape:
1. Verify the signature2. Acknowledge with 200 OK3. Enqueue for async processingRetries
Section titled “Retries”Non-2xx responses, timeouts, and connection errors are retried with exponential backoff:
| Attempt | Delay (approx) |
|---|---|
| 1 | immediate |
| 2 | +5 s |
| 3 | +30 s |
| 4 | +5 min |
| 5 | +30 min |
After 5 failed attempts the event is marked failed (not dropped). Failed events remain visible in the dashboard’s webhook log and can be redelivered for up to 30 days.
Ordering
Section titled “Ordering”Events for the same call_id are dispatched in chronological order, but
network re-ordering can deliver them out of sequence to your endpoint.
Don’t trust arrival order. Use the timestamps inside the event payload
(occurred_at on the envelope, answered_at, ended_at, etc.) to
reconstruct the lifecycle.