<!-- source: https://platform.scriptivox.com/docs/versioning -->
<!-- title: Versioning and Deprecation Policy | Scriptivox API -->

# Versioning and deprecation

This page is the promise you can build against: what we are allowed to change without telling you, what we are not, and how you find out before it happens.

---

## How the API is versioned

The version is in the URL path. Every endpoint lives under `/v1`:

```
https://api.scriptivox.com/v1/transcribe
```

There is no version header and no `Accept` negotiation on version. If a request works today at a given `/v1` URL, that URL is the contract.

`info.version` in [openapi.json](/openapi.json) is the version of the *document*, not of the API. It moves whenever the description is corrected. Do not pin behaviour to it — pin to `/v1`.

## What counts as a breaking change

Breaking changes only ever ship behind a new major version — a `/v2` prefix, never a silent change to `/v1`.

**Breaking**, and therefore never done to `/v1`:

- Removing an endpoint, a request parameter, or a response field.
- Renaming any of the above.
- Changing the type of a response field, or making an optional request parameter required.
- Removing a value from an enum you receive (a `status`, an `error.code`).
- Tightening a validation rule so a request that used to succeed now fails.

**Not breaking**, and shipped to `/v1` without notice — write your client so these cannot hurt it:

- Adding a new endpoint.
- Adding a new **optional** request parameter.
- Adding a new field to a response body.
- Adding a new value to an enum you *send* us.
- Adding a new `error.code`, or a new HTTP header.
- Fixing a bug where the documented behaviour and the actual behaviour disagreed.

> **Two client habits that turn a safe change into an outage:** 
> **Do not reject unknown fields.** We add response fields without notice. A client that treats an unrecognised key as a parse error will break on a change nobody was required to announce.
> 
> **Do not exhaustively switch on `error.code` without a default branch.** New codes are additive. Treat an unrecognised code as "an error I do not specifically handle", never as an unreachable case.
> 
> (Note the asymmetry: *we* reject unknown fields on request bodies — `additionalProperties: false` — because a silently ignored typo in your request is worse than a loud rejection.)

## Notice before anything is removed

If an endpoint, parameter or field is ever deprecated:

- **Six months minimum** between the deprecation announcement and the removal. No exception for anything except a security defect that cannot be fixed any other way, which will say so explicitly.
- **Twelve months minimum** of `/v1` running alongside `/v2` after a `/v2` exists, so migration is never a same-week emergency.
- The announcement is machine-readable. It is not only a blog post you have to be subscribed to.

## How deprecation is signalled on the wire

A deprecated endpoint answers normally and adds three response headers:

| Header | Meaning |
| --- | --- |
| `Deprecation` | [RFC 9745](https://www.rfc-editor.org/rfc/rfc9745.html). An HTTP date: when the resource became deprecated. |
| `Sunset` | [RFC 8594](https://www.rfc-editor.org/rfc/rfc8594.html). An HTTP date: the earliest date the resource may stop responding. |
| `Link` | `rel="sunset"`, pointing at this page. |

```http
Deprecation: @1794787200
Sunset: Sat, 15 Aug 2026 00:00:00 GMT
Link: <https://platform.scriptivox.com/docs/versioning>; rel="sunset"
```

The response body is unchanged — a deprecation never breaks a working integration on the day it is announced. That is the whole point of the headers: an automated client can notice and open a ticket six months before anything stops working.

> **Nothing is deprecated today:** 
> No endpoint, parameter or field in `/v1` currently carries a `Deprecation` or `Sunset` header, because nothing is scheduled for removal. The mechanism is in place and documented so it is already there on the day it is first needed — not invented in a hurry alongside the first removal.

## What to do if you see one

1. Read the `Link` target for the migration path.
2. Note the `Sunset` date. It is the earliest date the endpoint may stop working, not a date it will be checked again.
3. Migrate. If the `Sunset` date is inconvenient, say so at [support@scriptivox.com](mailto:support@scriptivox.com) *before* it passes — dates are set to be generous, and we would rather move one than break you.

## Watching for changes without polling

- **[openapi.json](/openapi.json)** is regenerated on every deploy and is the most precise description of the current surface. Diffing it in CI is the cheapest change detector there is; a removed `operationId` or a changed `required` list shows up as a diff before it shows up as an incident.
- **Every response** carries `Link: <https://platform.scriptivox.com/openapi.json>; rel="service-desc"` ([RFC 8631](https://www.rfc-editor.org/rfc/rfc8631.html)), so a client can find that document without hard-coding this page.
- **[status.scriptivox.com](https://status.scriptivox.com)** carries incidents and maintenance, which is a different thing from deprecation — availability, not contract.

## Other surfaces

The [CLI](/docs/cli) and the [MCP server](/docs/mcp) follow semver independently of the API version. Their major versions may move while the API stays at `/v1`: a tool renamed in the MCP server is a breaking change to that npm package, not to `/v1`. Deprecated MCP tool names are kept as working aliases and are listed in the [manifest](/.well-known/mcp) with the release that removes them.
