Skip to Content
Changelog

Changelog

2026-10-03 — Recording sharing

Added

  • POST /recordings/:recording_id/shares shares a call read-only with one member of the account (email) or with every member (everyone: true). The person gets an email with the link and your optional message; notify: false sends none. Recipients always sign in; there are no public links. GET lists the shares and DELETE /recordings/:recording_id/shares/:id removes one. See Share Recording.

2026-10-03 — Audio download

Added

  • GET /recordings/:id/audio returns the audio file itself, authenticated with your API key, so you can keep your own copy of your calls. Supports Range for resuming downloads. Audio already deleted by the retention policy answers 410 with deleted_at. See Download Audio.

2026-10-02 — Internal calls returned once, scores per participant

Changed

  • Internal calls recorded on both lines are one item. GET /recordings used to return such a call twice, once per line. It now returns one of the two recordings (the one imported first, which may be the caller’s or the callee’s line); meta.total_count follows. The other recording’s id still resolves on GET /recordings/:id.
  • goal_achievement is the credited operator’s. On a call with two evaluated people it used to blend both into one number.
  • operator_id filter matches either participant of an internal call, not only the credited operator.
  • DELETE /recordings/:id on the listed recording of such a call deletes both recordings. Deleting the other, unlisted recording by its own id removes only that one.

Added

  • participants on list and detail items: [{ operator_id, name, side, goal_achievement }], credited operator first.
  • GET /recordings/:id/results returns the goal results of every participant, each marked with subject_operator_id and subject_name.

2026-04-15 — Public API surface trim

Removed

  • GET /api/v1/public/outbound_calls and POST /api/v1/public/outbound_calls — outbound call origination is no longer exposed via the public API. The web UI still supports originating outbound calls.
  • GET /api/v1/public/regulatory_requirements, POST /api/v1/public/regulatory_requirements, GET /api/v1/public/regulatory_requirements/check, GET /api/v1/public/regulatory_requirements/:id, POST /api/v1/public/regulatory_requirements/:id/refresh — regulatory-requirement management moves to the web UI only.

These endpoints had limited external-integration value and carried maintenance surface we don’t want to support publicly. Internal functionality is unchanged: the web application still handles outbound calls and regulatory compliance workflows through TelnyxRequirementsService and the account documents UI.

2026-04-15 — Public API expansion

Contains breaking changes. See Breaking changes below before upgrading integrations.

Added

  • Projects API at /api/v1/public/projects with GET / GET :id / POST / PATCH / DELETE. Account-wide API keys can now manage projects programmatically; project-scoped keys see and can mutate only their own project.
  • project_id parameter on POST /recordings. Required for account-wide keys (422 if omitted), optional for project-scoped keys (must match or be omitted).
  • external_id idempotent upsert on POST /recordings. Re-POSTing a recording with the same (project_id, external_id) returns the existing record with 200 OK. Retry-safe for integrations like 3CX, Tele2, Tenesys.
  • project_id on PATCH /recordings/:id. Account-wide keys can move recordings between projects; project-scoped keys cannot.
  • /recordings/filters and /recordings/:id/audio_url now documented in OpenAPI.
  • New response fields on Recording: public_id (UUIDv7), project_id, external_id, called_at, recording_source.

Breaking changes

  • Numeric id removed from Recording response bodies. Use public_id (UUIDv7 string) instead. URL path parameters still accept both numeric id and public_id for back-compat.
  • Account-wide keys must pass project_id on POST /recordings. Previously, missing project_id silently created an orphan recording with recording_project_id = NULL. Now returns 422.
  • Project-scoped keys receive 403 when project_id disagrees with the key’s project on POST /recordings and PATCH /recordings/:id. Previously the mismatched parameter was silently ignored.
  • Cross-project resource access via project-scoped keys is now blocked. Operators, virtual numbers, and outbound call origination were previously scoped to the account rather than the project; a project-scoped key could read/mutate resources belonging to sibling projects in the same account. This cross-tenant leak is fixed. If you were relying on it, switch to an account-wide key.

Removed / corrected in docs

  • Rate-limit claims removed. The OpenAPI spec and marketing copy previously advertised X-RateLimit-* headers; no limiter was implemented. These claims have been stripped. A rate-limit implementation is tracked separately.
  • Voice biometrics references removed from the public-API docs. Voice biometric endpoints are session-authenticated under /api/v1/voice_profiles/*, not public-API.

Infrastructure

  • scoped_for(relation) helper on PublicApiController — standardizes how every public endpoint narrows to the API key’s scope.
  • OpenAPI contract test at test/integration/openapi_contract_test.rb asserts every documented path resolves to a real route and every public route is documented in the spec.