Skip to content

What's New

The latest Teler SDK releases and features, newest first.

September 18, 2026
Stable SDK releases: Node 2.0.0 and Python 1.0.0 #
Added

Node SDK 2.0.0 and Python SDK 1.0.0 are now stable with production-ready call mutations, media streaming, SIP management, recordings, and events APIs. Python includes async client with full parity to Node.

Node SDK 2.0.0 and Python SDK 1.0.0 — Stable releases with full API support for all Teler services:

Core capabilities (Node and Python):

  • Voice calls — Initiate, control, and manage calls with mutations (mute, DTMF, play, hangup, transfer)
  • SIP trunks — Full SIP trunk management with IP ACL support and UDP transport
  • Virtual numbers — Provision and manage Teler numbers
  • Recordings — Capture call audio in multiple modes: mono, stereo, or per_leg
  • Events — Subscribe to call and stream lifecycle events via webhooks
  • Secrets — Securely store and retrieve API credentials for integrations

Python-specific:

  • Sync Client for traditional blocking code
  • Async AsyncClient for high-concurrency applications (new in 1.0.0)
  • Full feature parity with Node SDK

Node-specific:

  • Auto-pagination built-in for all list operations
  • Promise-based async API
Terminal window
pip install teler
Terminal window
npm install @frejun/teler

Both SDKs include:

  • Automatic idempotency key generation for safe retries
  • Typed exceptions: BadParametersException, ForbiddenException, RateLimitException, TelerException
  • Cursor-based pagination for large result sets
  • Webhook signing verification with HMAC-SHA256
  • Streaming support via StreamConnector to bridge AI provider integrations
  • Production-ready error handling and retry logic
Release Notes → SDKs → Node repository → Python repository →
July 11, 2026
Human handoff: call transfer and the dial action #
Added

Two ways to move a caller from an AI agent to a live person: a REST transfer operation for live calls, and the dial flow verb for flow-time handoff.

Transfer an in-progress call to a new PSTN or SIP destination, enabling agent-to-human handoff flows. Three features ship together to support flexible transfer patterns:

Your backend can initiate a transfer on a live call via POST /api/v1/voice/calls/{call_id}/transfer. This is async and idempotent — use the same Idempotency-Key to safely retry.

Request:

POST /api/v1/voice/calls/{call_id}/transfer
Content-Type: application/json
Idempotency-Key: <unique-per-attempt>
{
"target": { "kind": "pstn", "number": "+14155550123" },
"mode": "cold",
"timeout": 30,
"record": false,
"ringback": "suppress",
"on_failure": { "action": "play", "media_url": "https://.../could-not-connect.mp3" }
}

Supported parameters:

  • target.kind — "pstn" (PSTN number) or "sip" (SIP URI)
  • timeout — 1–600 seconds, default 30
  • record — Recording mode: false, true, "mono", "stereo", "per_leg"
  • ringback — "suppress" (default) or "passthrough"
  • on_failure — Nested action (play, hangup) if transfer fails

Constraints:

  • Only mode: "cold" is supported today
  • One transfer per call at a time (409 transfer_in_progress)
  • Voice App only
  • Requires webhook version 2026-06-01

Track the transfer as it progresses through your webhook:

  • call.transfer.initiated — Transfer request accepted, target leg originates
  • call.transfer.bridged — Target answered and is now bridged to caller
  • call.transfer.failed — Transfer failed (includes reason for debugging)

Each event carries the transfer ID (op_<ULID>) for correlation.

3. dial (flow verb) — Flow-based handoff

Section titled “3. dial (flow verb) — Flow-based handoff”

Return {"action": "dial", "to": "+14155550123"} from your flow endpoint to dial and bridge a target, letting your flow logic drive the handoff decision.

Request:

{
"action": "dial",
"to": "+14155550123",
"timeout": 25,
"record": "stereo",
"ringback": "passthrough",
"dial_music": { "action": "play", "media_url": "https://cdn.example.com/hold.mp3", "loop": true },
"on_no_answer": { "action": "hangup" },
"on_busy": { "action": "play", "media_url": "https://cdn.example.com/try-later.mp3" }
}

Supported parameters:

  • to — Target E.164 number or SIP URI (single target)
  • timeout — 1–600 seconds, default 30
  • record — Recording mode: false, true, "mono", "stereo", "per_leg", default false
  • ringback — "passthrough" (default) or "suppress"
  • dial_music — Audio to play to caller while target rings
  • confirm_sound — Audio to play to target immediately after pickup
  • on_no_answer, on_busy, on_failure — Fallback actions (play or hangup only)
  • custom_headers — SIP headers starting with X- (max 16, 256 bytes each)

Constraints:

  • Not available on webhook version 2025-08-01; requires 2026-06-01
  • Nested actions support only play and hangup
  • Multiple targets, machine_detection, and mixed SIP+PSTN targets not yet shipped

Leg lifecycle events

The dialed leg emits events as it progresses:

  • leg.created — Outbound leg originated to target
  • leg.answered — Target answered and bridge established
  • leg.completed — Leg disconnected with reason (normal, no_answer, busy, rejected, unreachable, etc.)

Each event includes the leg ID for tracking across your call lifecycle.

Call transfer (REST)dial (flow verb)
Decision pointBackend, mid-callFlow endpoint, before response
Use caseReal-time server logic (queue depth, agent availability)Flow-driven logic (intent, escalation policy)
TargetPSTN or SIPPSTN or SIP
Timeout1–600 s (default 30)1–600 s (default 30)
Fallback controlon_failure onlyon_no_answer, on_busy, on_failure
RecordingConfigurable per transferConfigurable per dial
Eventscall.transfer.*leg.*
RequiresVoice App 2026-06-01; Voice App onlyVoice App 2026-06-01
Live call control → dial → Call flows →
July 3, 2026
Webhook version 2026-06-01: event envelope, call control, and call resources #
Added Changed

New dated webhook version with event envelope wrapper, live call control operations, call resources API, new event types, and stable event IDs for idempotent deduplication.

A new dated webhook API version, 2026-06-01, available opt-in per Voice App or SIP Trunk. The previous 2025-08-01 version continues to work for existing deployments. This version introduces a complete redesign of webhooks, new call management APIs, and infrastructure for reliable event delivery.

Every webhook body is now wrapped in a standard envelope:

{
"id": "evt_...",
"type": "call.initiated",
"api_version": "2026-06-01",
"occurred_at": "2026-07-03T12:34:56Z",
"account_id": "acc_...",
"voice_app_id": "va_...",
"call_id": "cs_...",
"leg_id": "cl_...",
"data": {
"from_number": "+14155550100",
"to_number": "+14155550123",
"direction": "inbound",
"answered_at": "2026-07-03T12:34:57Z",
"duration_seconds": 45,
"ended_by": "caller",
"reason": "normal"
}
}

Envelope fields:

  • id — Stable, unique event ID (for idempotent deduplication across retries)
  • type — Event type (e.g., call.initiated, call.answered, leg.created)
  • api_version — Pinned webhook version (2026-06-01)
  • occurred_at — ISO 8601 timestamp when the event occurred
  • account_id, voice_app_id / sip_trunk_id, call_id, leg_id — Resource IDs for correlation
  • data — Event-specific payload

New headers on every webhook request:

  • X-Teler-Event-Id — Echoes the event id for deduplication
  • X-Teler-Api-Version — Echoes 2026-06-01
  • X-Teler-Source — Identifies the webhook source (e.g., voice_app, sip_trunk)

All resource IDs now have consistent prefixes for type safety:

  • acc_ — Account
  • va_ — Voice App
  • st_ — SIP Trunk
  • cs_ — Call
  • cl_ — Call leg
  • ms_ — Media stream
  • evt_ — Event
  • rec_ — Recording
  • pb_ — Playback

Eight new events ship with this version:

  • leg.created — Outbound leg originated
  • leg.answered — Leg answered and bridged
  • leg.completed — Leg disconnected with reason
  • stream.initiated — Media stream started
  • stream.completed — Media stream ended
  • recording.completed — Recording file ready
  • recording.failed — Recording failed
  • Plus existing call events with new envelope format

See Call events for full schemas.

Retrieve call and leg details via REST:

GET /api/v1/voice/calls
GET /api/v1/voice/calls/{call_id}
GET /api/v1/voice/calls/{call_id}/legs
GET /api/v1/voice/calls/{call_id}/legs/{leg_id}

For SIP Trunks:

GET /api/v1/sip/calls
GET /api/v1/sip/calls/{call_id}
GET /api/v1/sip/calls/{call_id}/legs

Returns call state, participant info, timing, recording status, and more. See Call resources.

Perform mutations on active calls via async, idempotent operations:

POST /api/v1/voice/calls/{call_id}/hangup
POST /api/v1/voice/calls/{call_id}/mute
POST /api/v1/voice/calls/{call_id}/dtmf
POST /api/v1/voice/calls/{call_id}/play

All require Idempotency-Key header for safety. See Live call control.

The id field is stable across webhook retries, replays, and recovery re-deliveries. Use it to deduplicate events on your side for exactly-once processing. See Retries and idempotency.

Inside the data payload, fields are renamed for clarity:

  • hangup_time → ended_at
  • hangup_source → ended_by
  • duration (seconds) → duration_seconds
  • answer_time → answered_at
  • New normalized reason field for all completion events
  • direction unchanged (inbound / outbound)

Full migration guide: API versioning.

Pin this version on a per-Voice-App or per-SIP-Trunk basis. The previous 2025-08-01 version continues to work unchanged for existing resources that don’t pin the new version.

Event envelope → Call resources → Live call control → Call events → API versioning →

See all Release Notes →