API changelog

Integration-relevant changes to the Voice Platform API

View as Markdown

Use this page to track changes that can affect an application built on the Voice Platform API. Entries describe the public behavior of the API and any action an existing integration should take.

How changes are published

Changes are grouped by release date and labeled as follows:

  • Added — a new, backward-compatible capability.
  • Changed — an existing contract or behavior changed. The entry includes migration guidance when an application may need to change.
  • Fixed — the implementation or documentation was corrected to match the intended contract.
  • Deprecated — a capability remains available but should no longer be used. The entry identifies its replacement and the planned removal timeline.

The endpoint reference remains the source for the current contract. This page records the history needed to understand differences between an existing integration and the current contract.

August 7, 2026

Added

  • Applications can read and update their own webhook delivery URL with GET /api/v1/app/webhook and PUT /api/v1/app/webhook. Sending null or an empty string disables delivery; a successful update applies to webhook deliveries created afterward.
  • Unauthenticated GET /health and GET /livez endpoints are now part of the public contract. Use /health for dependency readiness and /livez only for process liveness.

Changed

  • The canonical API base URL is https://api.telekesher.dev. Session endpoints moved from /api/v1/sessions... to /v1/sessions.... Update constructed request URLs to remove the /api segment from Session routes.

August 6, 2026

Changed

  • Session webhook names now use the session resource namespace: call.created, call.answered, call.ringing_started, call.early_media_started, and call.ended became their corresponding session.* events, and command.call.dial.accepted became command.session.dial.accepted. Update event filters and webhook dispatch logic to use the new names.
  • Terminal room playback events are now room.playback.ended for natural completion or an API stop, and room.playback.failed for errors and timeouts. The former room.playback.finished name is no longer used. Inspect the event’s reason to distinguish the terminal outcome.
  • Session lifecycle fields are endpoint-specific. Items returned by GET /sessions use state, while GET /sessions/{session_uuid} uses status. Both fields have the same lifecycle values. Applications that deserialize both responses into one model should accept the field associated with each endpoint.
  • playback/seek, recording/mask, and recording/unmask draw from one shared seek rate-limit bucket. A burst of one of these commands can reduce the capacity available to the other two. See Rate limits.
  • Recording command acknowledgement events now document expires_at alongside pull_url. For mask and unmask acknowledgements, the two fields are either both present or both omitted. See Command acknowledgements.
  • A 503 response after an idempotent command may mean the command completed but its saved response could not be returned. Retry once with the same Idempotency-Key; if the response is still unavailable, reconcile using the resulting resource or webhook events before issuing a new key.
  • WebSocket pause and resume affect audio in both directions. Pausing preserves buffered backend audio, and resuming does not change mute state.

Fixed

  • Playback seek requests now reject seek_ms: 0. Use a positive value to seek forward or a negative value to rewind.
  • Authentication and client-error responses now distinguish malformed credentials (400), missing or invalid credentials (401), forbidden operations (403), and resources hidden by application ownership (404). Error responses expose a stable code for programmatic handling.