OpenTranscription
OpenTranscription
Back to app

API Versioning Policy

This document describes the stability guarantees and change process for the OpenTranscription v1 API (/api/v1/*). It is intended for developers building integrations against this API. Read it before you ship; the promises here are what you can rely on.


What v1 Guarantees

The following are contractual surface. They will not change within v1 without a deprecation cycle (see below).

Response field shape

Existing fields keep their name, type, and semantics. New fields may be added at any time (additive changes are non-breaking). Fields will never be renamed or removed without a deprecation window.

HTTP status codes

Documented status codes stay documented. A 200 today will be a 200 tomorrow. A 403 for an insufficient scope will keep its documented shape.

Scope names

The four scopes are stable for the lifetime of v1:

| Scope | Purpose | | ---------------------- | --------------------------------------- | | transcriptions:read | Read transcription jobs and transcripts | | transcriptions:write | Create and manage transcription jobs | | models:read | List and read model metadata | | usage:read | Read usage and billing data |

New scopes may be added. Existing scope names will not be renamed or removed.

Error response shape

The { error: string } envelope is stable. Fields such as required that appear on specific error types (e.g., scope errors) will keep their meaning. Additional fields (e.g., code, details) may be added in future.

Example 403 response:

{ "error": "Insufficient scope", "required": "transcriptions:write" }

Do not branch on the error string — it is human-readable and may be reworded. Branch on HTTP status code and structured fields like required.

Header names

These headers are stable:

| Header | Direction | Meaning | | ----------------------------- | --------- | ------------------------------------ | | Authorization: Bearer <key> | Request | Authentication | | X-RateLimit-Limit | Response | Requests allowed per window | | X-RateLimit-Remaining | Response | Requests remaining in current window | | X-RateLimit-Reset | Response | Unix timestamp when window resets |

New headers may be added. Existing headers will not be renamed.

Authentication scheme

Bearer token authentication using keys with the ot_ prefix is stable for the life of v1. The key format (ot_live_... / ot_test_...) is also stable.

URL structure

Paths under /api/v1/* keep their semantics. New paths may be added; existing paths will not be moved or removed within v1.


What is NOT Part of the Contract

Do not build implicit dependencies on these — they are not guaranteed.

Latency. Response time targets are covered as aspirational values in slo.md, not contractual guarantees.

Exact error message wording. The error field is a human-readable string. It may be reworded, improved, or localized at any time. Always branch on structured fields (status code, required, code) — never on the string value.

Undocumented fields. Any field present in a response but absent from the OpenAPI spec is internal. It may change or disappear without notice.

Job transition timing. When a job moves from uploaded to processing to completed is not contractual. Poll for status or use webhooks (when available) rather than assuming timing.

Array ordering. Unless a response is explicitly documented as ordered, do not assume a stable sort order.


Breaking Changes and the 90-Day Deprecation Process

Breaking changes — removing a field, renaming a field, changing a type, or changing the semantics of a status code — do NOT ship to /api/v1/* in place. They go to /api/v2/*. Integrators opt in to v2 by changing URLs.

When a v1 endpoint is deprecated

  1. A Sunset header appears on the deprecated endpoint with the planned removal date (ISO 8601 / RFC 8594 format).
  2. A Deprecation: true header appears alongside it.
  3. A changelog entry is published on the status page.
  4. An email is sent to all API key holders who have called the affected endpoint in the previous 90 days.

Example response headers on a deprecated endpoint:

Sunset: 2026-09-01T00:00:00Z
Deprecation: true

Minimum deprecation window

90 days from the first Sunset header appearing to the endpoint being removed.

Security-critical exceptions

A vulnerability patch may require a shorter window. In such cases we will still send email notification and publish a changelog entry — we will never silently remove or change an endpoint.


Additive Changes (Non-Breaking)

These can ship to v1 at any time without versioning or advance notice:

  • New optional fields on request bodies
  • New fields on response bodies
  • New HTTP status codes for new error scenarios (existing scenarios keep their documented codes)
  • New scopes
  • New endpoints at new paths
  • New optional query parameters (callers that ignore them continue to work)
  • Bug fixes that bring behavior in line with documentation
  • Performance improvements

How to Tell Which Version You're Using

All v1 operations are under /api/v1/*. There is no Api-Version header.

When v2 ships, it will be under /api/v2/*. You will need to consciously opt in by updating your base URL. There is no silent migration.


Changelog and Announcements

A formal changelog is planned and will be linked here when available. In the interim, breaking change notices and deprecation announcements are published to the status page.

<!-- TODO: Update with actual status page URL once status.opentranscription.io CNAME is provisioned -->

To receive notifications:

  • Email: API key holders are automatically enrolled in deprecation notices for endpoints they use.
  • RSS: Subscribe to the status page RSS feed for all announcements.

Questions

For general API questions, open a support ticket at https://opentranscription.io/support.

Enterprise customers with SLA agreements have a dedicated account manager for contract-level questions. Contact details are in your onboarding email.