Skip to content

API versioning

Teler versions the webhook wire format and event catalog with dated versions. Each Voice App and each SIP Trunk is pinned to exactly one version. Existing pins never change on their own. You decide when to migrate.

Two versions exist today:

VersionStatusWire formatNew events
2025-08-01Original: frozen, still supported for existing pinsFlat body, direct HTTP deliverynone
2026-06-01Current: recommended for new integrationsEnvelope with id, type, api_version, unified vocabularyleg.*

Only the webhook side is versioned. Call Flow JSON, SDK method signatures, and the media-streaming WebSocket protocol are not affected by this pin.

Both versions run in parallel. Traffic on one has no effect on the other.

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

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

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 (2026-06-01 only, at the envelope root):

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

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

Concrete differences: 2025-08-012026-06-01

Section titled “Concrete differences: 2025-08-01 → 2026-06-01”

The wire format is a hard break: parse the two shapes with separate code paths, don’t try to unify. This section is exhaustive for that reason.

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_01H...",
"type": "call.initiated",
"api_version": "2026-06-01",
"occurred_at": "2026-06-01T11:30:45.123Z",
"account_id": "<uuid>",
"call_id": "cs_01H...",
"leg_id": null,
"sip_trunk_id": null,
"data": { "call_id": "cs_01H...", "from": "...", "to": "...", ... }
}

See Event envelope for the full field reference.

Legacy 2025-08-01Current 2026-06-01Notes
hangup_timeended_atUnified across call, leg, and sip-trunk events.
hangup_sourceended_byValues also normalized, see below.
duration (integer, seconds)duration_seconds (integer, seconds)Same units, explicit name.
answer_timeanswered_atNaming aligned with ended_at.
direction: "incoming"direction: "inbound"Enum values renamed.
direction: "outgoing"direction: "outbound"Enum values renamed.
nonereasonNew field: normalized terminate reason (e.g. "no_answer", "busy").
Legacy valueCurrent value
"caller""caller"
"callee""callee"
"platform" / "system""system"

2025-08-01 used raw FreeSWITCH UUIDs. 2026-06-01 returns prefixed, resource-typed IDs everywhere:

PrefixRefers toWhere you see it
acc_AccountEnvelope account_id
va_Voice AppEnvelope voice_app_id
st_SIP TrunkEnvelope sip_trunk_id
cs_Call session (a whole call, root of the leg tree)Envelope call_id for Voice App calls
cl_Call leg (one participant leg on a call)Envelope leg_id, and call_id inside per-leg events
ms_Media stream (a bridged audio stream on a call)data.stream_id in media-streaming events
evt_Webhook eventEnvelope id; also X-Teler-Event-Id header
rec_Recordingdata.recording_id in recording events
pb_Playback (from the play verb / control API)data.playback_id in play events

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

The wire field on the envelope is voice_app_id (not call_app_id).

Header2025-08-012026-06-01
X-Teler-Timestamp
X-Teler-Signature
X-Teler-Event-Idnone✓ (echoes envelope id)
X-Teler-Api-Versionnone
X-Teler-Sourcenone✓ (live | replay | recovery)

Signature scheme is identical: HMAC-SHA256(secret, "{timestamp}.{raw_body}"). See Signing & verification.

Events emitted on 2025-08-01:

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

Events emitted on 2026-06-01, everything above plus:

EventWhat it means
leg.createdA new participant leg was originated (multi-party calls, dials).
leg.answeredThat leg was answered.
leg.completedThat leg ended.

2025-08-01 has no idempotency key. Duplicate deliveries are distinguishable only by content comparison.

2026-06-01 guarantees stable envelope id values across retries and replays. Dedupe on id. See Retries & idempotency.

AspectBehavior on both versions
Signing algorithmHMAC-SHA256 over "{timestamp}.{raw_body}"
Retry policyUp to 5 attempts, exponential backoff
Timeout5 seconds for your response
Delivery orderingBest-effort per call_id, use timestamps to reorder
Which secret is usedThe one on the owning Voice App / SIP Trunk

Do these in order: the goal is that your handler can serve 2026-06-01 traffic successfully before you flip the pin.

  1. Deploy a handler that switches on the X-Teler-Api-Version header (or on the presence of the api_version body field). Keep the legacy parser online.
  2. Point one low-traffic Voice App / SIP Trunk at 2026-06-01 in staging. Confirm your handler processes at least one call end-to-end.
  3. Flip production resources one at a time. Watch for call.completed at the same rate on the new pin.
  4. Once nothing is emitting 2025-08-01, delete the legacy parser.
  • 2025-08-01 is frozen but continues to work indefinitely for existing pins. No end-of-life date is set.
  • New dated versions ship every 6-12 months when there is a wire-format change that isn’t backward-compatible.
  • Announcements land in the Release notes and, for pinned customers, in an email to the account owner.