Skip to main content

Versioning

Teler pins the webhook payload shape and event catalog to a dated version per Voice App and per SIP Trunk. Existing pins never change on their own; you decide when to migrate.

Two versions are available today.

VersionStatusWire formatAdditional events
2025-08-01Frozen. Continues to work for existing pins.Flat body, direct HTTP delivery.none
2026-06-01Available for new pins.Envelope with id, type, api_version, unified field vocabulary.call.ringing

Only the webhook wire format and event catalog are versioned. Call Flow JSON, SDK method signatures, and the media-streaming WebSocket protocol are unaffected by this pin.

Pinning a version

The pin lives on the owning resource as webhook_api_version. Set it when you create the Voice App or SIP Trunk in the dashboard; change it later by editing the same resource.

Valid values: "2025-08-01" or "2026-06-01". Any other value is rejected.

caution

Changing the pin takes effect on the next event for that resource. Deploy your 2026-06-01-capable handler before flipping the pin.

Identifying the version at runtime

Two ways. Use whichever fits your handler.

HTTP header (present on every 2026-06-01 request, absent on 2025-08-01):

X-Teler-Api-Version: 2026-06-01

Body field at the envelope root (2026-06-01 only):

{ "api_version": "2026-06-01", "type": "call.initiated", "...": "..." }

If neither is present, the event is 2025-08-01.

Body shape

2025-08-01 sends a flat body with the event name inside:

{
"event": "call.initiated",
"account_id": "<uuid>",
"call_app_id": "<uuid>",
"data": { "call_id": "<uuid>", "from": "...", "to": "...", "...": "..." }
}

2026-06-01 wraps the payload in an envelope:

{
"id": "evt_01H8ZXK9M2P7Q3R4S5T6V7W8XY",
"type": "call.initiated",
"api_version": "2026-06-01",
"occurred_at": "2026-06-01T11:30:45.100Z",
"account_id": "acc_01H8ZXK9M2P7Q3R4S5T6V7W8XY",
"voice_app_id": "va_01H8ZXK9M2P7Q3R4S5T6V7W8XY",
"sip_trunk_id": null,
"call_id": "cs_01H8ZXK9M2P7Q3R4S5T6V7W8XY",
"leg_id": null,
"data": { "call_id": "cs_...", "...": "..." },
"previous_attributes": null
}

Exactly one of voice_app_id or sip_trunk_id is set on every event, never both.

Envelope fields

FieldTypeNullableDescription
idstring (evt_<ULID>)noUnique event ID, stable across retries and replays. Use as your idempotency key.
typestringnoEvent name. See per-event pages under Webhooks.
api_versionstringnoAlways "2026-06-01".
occurred_atISO-8601 UTCnoWhen the underlying event happened. Stable across retries.
account_idstring (acc_<ULID>)noYour Teler account.
voice_app_idstring (va_<ULID>)yesSet on Voice App events; null on SIP Trunk events.
sip_trunk_idintegeryesSet on SIP Trunk events; null on Voice App events.
call_idstring (cs_<ULID>)yesIdentifies the call. Same format for Voice App and SIP Trunk calls.
leg_idstring (cl_<ULID>)yesReserved for future per-leg events. null on today's event catalog.
dataobjectnoEvent-specific payload.
previous_attributesnullyesReserved for future *.updated events.

Field renames inside data

2025-08-012026-06-01Notes
hangup_timeended_atUnified across call, leg, and SIP Trunk events.
hangup_sourceended_byValues also normalized (see below).
duration (int, seconds)duration_seconds (int, seconds)Same units, explicit name.
answer_timeanswered_atAligned with ended_at.
(not present)reasonNew field. Normalized terminate reason such as "no_answer", "user_busy", "canceled".

ended_by value mapping

2025-08-01 (hangup_source)2026-06-01 (ended_by)
callercaller
calleecallee
platform / systemsystem

Identifiers

2025-08-01 uses raw UUIDs. 2026-06-01 uses prefixed, resource-typed IDs everywhere.

PrefixRefers to
acc_Account
va_Voice App
st_SIP Trunk
cs_Call Session (Voice App or SIP Trunk call)
cl_Call Leg
evt_Webhook Event
rec_Recording
pb_Playback

data.call_id and envelope-root call_id always agree on 2026-06-01.

Headers

Header2025-08-012026-06-01
X-Teler-Timestampyesyes
X-Teler-Signatureyesyes
X-Teler-Event-Idnoyes (echoes envelope id)
X-Teler-Api-Versionnoyes
X-Teler-Sourcenoyes (live | replay | recovery)

Signature scheme is identical on both versions: HMAC-SHA256(secret, "{timestamp}.{raw_body}").

Event catalog

Events emitted on 2025-08-01:

call.initiated, call.answered, call.completed, call.failed, stream.initiated, stream.completed, recording.completed, recording.failed.

Events emitted on 2026-06-01. Everything above, plus:

EventWhat it means
call.ringingCallee's phone is ringing (outbound) or Teler is routing the call (inbound).

Idempotency

2025-08-01 has no idempotency key. Duplicates are distinguishable only by comparing body content.

2026-06-01 guarantees a stable envelope id across every retry, replay, and recovery re-delivery. Store id on receipt and reject duplicates.

What is not different

AspectBehavior on both versions
Signing algorithmHMAC-SHA256 over "{timestamp}.{raw_body}"
Retry policyUp to 8 attempts, exponential backoff
Timeout5 seconds for your response
OrderingBest-effort per call_id. Reorder by timestamp if order matters.
Which secret is usedThe one on the owning Voice App or SIP Trunk

Migration checklist

Order matters. The goal is that your handler serves 2026-06-01 traffic correctly before you flip the pin.

  1. Deploy a handler that branches on X-Teler-Api-Version (or on presence of the api_version body field). Keep the 2025-08-01 parser online.
  2. Point a low-traffic Voice App or SIP Trunk in staging at 2026-06-01. Confirm one call end-to-end.
  3. Flip production resources one at a time. Watch for the terminal event (call.completed or call.failed) at the expected rate on the new pin.
  4. Once nothing is emitting 2025-08-01, remove the 2025-08-01 parser.
tip

The pin is per-resource. You can migrate one Voice App at a time and leave the rest on 2025-08-01.

Deprecation policy

  • 2025-08-01 is frozen but continues to work indefinitely for existing pins. No end-of-life date is set.
  • New dated versions ship when a wire-format change is not backward-compatible.