Skip to Content
Changelog

Changelog

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.