> ## Documentation Index
> Fetch the complete documentation index at: https://unif.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Versioning

> What can change without warning, and what cannot.

The API is versioned by date. Your workspace is pinned to the version current when it was created,
and it stays there until you move it.

```
2026-09-01
```

Pin explicitly per request with a header, which is what you want in a deployed service:

```bash theme={null}
curl https://api.unif.dev/v1/me \
  -H "Authorization: Bearer $UNIF_API_KEY" \
  -H "Unif-Version: 2026-09-01"
```

Every response echoes the version it was served under:

```
Unif-Version: 2026-09-01
```

<Note>
  The `/v1` in the path is the *major* version and changes only for a redesign of the whole API.
  Ordinary evolution happens through dated versions inside it.
</Note>

## What can change without a new version

Treat these as expected, and write clients that tolerate them. They are additive — nothing you
already read stops working.

<CardGroup cols={2}>
  <Card title="New fields on a response" icon="plus">
    Parse permissively. A strict parser that rejects unknown keys will break on a Tuesday.
  </Card>

  <Card title="New enum values" icon="list">
    New channels, markets, error codes and event types. Handle an unrecognized value by falling
    back, not by raising.
  </Card>

  <Card title="New endpoints and parameters" icon="code">
    New optional parameters keep their previous default behavior when omitted.
  </Card>

  <Card title="Coverage changes" icon="eye">
    A field moving from `partial` to `full`, or a new market appearing. Read
    [`GET /coverage`](/docs/concepts/coverage) rather than hard-coding.
  </Card>
</CardGroup>

```python theme={null}
CHANNEL_LABELS = {"tiktok_shop": "TikTok Shop"}

def label(channel: str) -> str:
    return CHANNEL_LABELS.get(channel, channel.replace("_", " ").title())   # degrades, not raises
```

## What requires a new version

These only ever happen behind a new dated version, and your pinned workspace is unaffected until
you move:

* Removing or renaming a field
* Changing a field's type, or a metric's definition
* Removing an enum value
* Making an optional parameter required
* Changing a default that alters results

<Warning>
  A change to how a **metric is calculated** is a breaking change and gets a new version, even
  though the field name and type stay identical. A number that silently changes meaning is worse
  than one that disappears.
</Warning>

## Upgrading

<Steps>
  <Step title="Read the changelog entry">
    Every version has an entry in the [changelog](/changelog) listing each breaking change and what
    to do about it.
  </Step>

  <Step title="Test with the header">
    Send `Unif-Version` with the new date from a staging deployment. Your workspace default is
    untouched, so you can run both side by side.
  </Step>

  <Step title="Compare real responses">
    Run the same requests under both versions and diff. This catches the changes that matter to
    your code rather than the ones that looked important in a list.
  </Step>

  <Step title="Move the workspace default">
    Update it in the dashboard. Requests that pin a version keep getting it.
  </Step>
</Steps>

## Support window

A dated version is supported for **12 months** after its successor ships. Within that window
nothing changes about how it behaves.

You get notice at 90, 30 and 7 days before a version is retired, by email to workspace owners and
in a `Unif-Deprecation` response header:

```
Unif-Deprecation: version=2025-06-01; sunset=2026-11-01; docs=https://unif.dev/changelog
```

<Tip>
  Log that header if it is present. It is the earliest automated signal that a deployment is
  running against something with an end date, and it costs one line to catch.
</Tip>

## Preview features

Some capabilities ship behind a header before they are part of a dated version:

```bash theme={null}
-H "Unif-Preview: creator-audience-demographics"
```

Preview features can change or be withdrawn at any time, including within a version. They are for
evaluation — do not build a production dependency on one, and never enable one by default in a
shared client library.
