# Versioning and deprecation

> Dated API versions, what we count as a breaking change, and how long you get before anything goes away.

Source: https://tickwire.io/docs/versioning/

Code you write against Tickwire today keeps working. Breaking changes to the native API ship only
under a new dated version that you opt into, and nothing is removed without at least **six months**
of notice, in headers and in the [API changelog](https://tickwire.io/docs/changelog-api/).

## Which surfaces are versioned

| Surface | Paths | Versioning |
|---|---|---|
| Native API | `/v1/…` on `api.` | Dated versions, `Tickwire-Version` header |
| `/users/current` REST API | `/users/current/…`, the regional API hostnames | **Frozen** to its existing shapes |
| Terminal routes | `/mt4/{id}/…`, `/mt5/{id}/…` | **Frozen** to their existing shapes |

The compatible surfaces exist so that code written for these API styles runs unchanged. Their
request and response shapes are fixed and are never changed by a Tickwire version. We may add
fields there when the API style does; we never rename, remove or retype one. `Tickwire-Version` is
ignored on those routes and not echoed.

## Dated versions

Versions are dates: `YYYY-MM-DD`. The current and only version is **`2026-09-25`**.

- Send `Tickwire-Version: 2026-09-25` on a `/v1` request to choose a version for that call.
- Without the header, the call uses your organisation's **pinned** version (see below).
- Every `/v1` response echoes the version that served it in `Tickwire-Version`, errors included.
- A malformed or unknown version is refused with `400`
  [`invalid_api_version`](https://tickwire.io/docs/errors/invalid_api_version/), listing the supported versions in
  `metadata.supportedVersions`. Nothing is forwarded.

Sending the header explicitly is the safest choice: your code then never changes behaviour when the
pin does.

## Your organisation's pin

Every organisation is pinned to one version. A `/v1` call without `Tickwire-Version` is served in
that version, so a new version never changes how your existing code behaves until you move the pin.

- A new organisation is pinned to the latest version on the day it is created.
- Organisations created before pins existed are pinned to `2026-09-25`.
- The header always wins: a call that sends `Tickwire-Version` gets that version, whatever the pin.

Read the pin with any API key or API token:

```bash
curl https://api.tickwire.io/v1/api-version -H "X-API-Key: $TICKWIRE_KEY"
```

```json
{"apiVersion": "2026-09-25", "latestVersion": "2026-09-25", "supportedVersions": ["2026-09-25"]}
```

### Upgrading the pin

Test your code against the new version first by sending `Tickwire-Version: <new date>` on its
calls. When it passes, move the pin, either in the dashboard (**Settings → API version**, owners
and admins) or with the API:

```bash
curl -X POST https://api.tickwire.io/v1/api-version \
  -H "X-API-Key: $TICKWIRE_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "X-Actor: deploy-bot" \
  -H "X-Reason: upgrade after the integration tests passed" \
  -H "Content-Type: application/json" \
  -d '{"apiVersion": "2026-09-25"}'
```

```json
{"apiVersion": "2026-09-25", "previousApiVersion": "2026-09-25", "changed": false,
 "latestVersion": "2026-09-25", "supportedVersions": ["2026-09-25"]}
```

- It needs a **full** API key, or a full-access API token with the writer role. Keys are issued by
  owners and admins; in the dashboard only owners and admins see the upgrade button.
- `Idempotency-Key`, `X-Actor` and `X-Reason` are required (`400`
  [`missing_header`](https://tickwire.io/docs/errors/missing_header/) otherwise; percent-encode a non-ASCII value).
  Repeating the key returns the first answer; the same key with a different body is `409`
  [`idempotency_conflict`](https://tickwire.io/docs/errors/idempotency_conflict/).
- Every change is written to your organisation's audit log as `api_version.pinned`, with the old
  and new version, the actor and the reason.
- An unknown or malformed version is `400` [`invalid_api_version`](https://tickwire.io/docs/errors/invalid_api_version/).
  A version older than the oldest supported one is `400`
  [`api_version_unsupported`](https://tickwire.io/docs/errors/api_version_unsupported/). The pin is unchanged in both
  cases.
- You can move the pin back to an older version while it is still supported.
- The new pin applies to calls without the header **within 30 seconds**.

## What counts as breaking

Breaking (only in a new dated version):

- removing or renaming an endpoint, a field, a query parameter or an enum value;
- changing a field's type, format, units or meaning (for example broker time to UTC);
- making an optional request field required, or adding a new required field;
- changing a success status code, an error code, or when an error is returned;
- changing default values, sort order or pagination behaviour;
- tightening validation so that a request accepted before is now refused.

Not breaking (can ship at any time, in every version):

- new endpoints, new optional request fields and parameters;
- new response fields (ignore fields you don't know);
- new enum values in fields documented as open-ended, new error codes for new failure modes,
  new webhook event types (ignore types you don't know);
- changes to the text of `message`, to `docUrl` targets, to the order of JSON keys, or to the length
  and format of opaque ids;
- raising a rate limit, or adding response headers.

Security fixes are the one exception: if a behaviour is unsafe, we may change it without a new
version, and we'll say so in the changelog the same day.

## Deprecation

When an endpoint, a field or a whole version is scheduled to go away:

1. It is announced in the [API changelog](https://tickwire.io/docs/changelog-api/) with the date it stops working.
2. From that day, every response from it carries:

   | Header | Standard | Example |
   |---|---|---|
   | `Deprecation` | RFC 9745 | `Deprecation: @1790812800` (when it was deprecated, Unix seconds) |
   | `Sunset` | RFC 8594 | `Sunset: Sat, 01 May 2027 00:00:00 GMT` (when it stops working) |
   | `Link` | RFC 8288 | `Link: <https://tickwire.io/docs/changelog-api>; rel="deprecation"` |

3. The sunset is **at least six months** after the deprecation is announced. A version stays
   supported for at least six months after the next version is published, and in practice until
   usage has moved.
4. We contact organisations we still see calling a deprecated route before its sunset.

Watch for `Deprecation` in your logs or tests: it is the earliest warning you'll get.

## Changelog

[API changelog](https://tickwire.io/docs/changelog-api/) lists every version and every deprecation, newest first. The
general [changelog](https://tickwire.io/docs/changelog/) covers the docs and the product.
