# Versioning

The v3 API is additive. Changes that would break a working integration ship as
a new major version.

## The three surfaces

| Surface | How it is versioned | Status |
| --- | --- | --- |
| **v3 REST** | in the URL: every endpoint lives under `/api/v3`. | Current |
| **Webhooks** | per webhook, by the `apiVersion` you register it with (`latest` or a dated value such as `2026-03-20`). Nifty echoes it back on every delivery as the `X-Api-Version` header. | Current |
| **v1.0 REST** | in the URL: `/api/v1.0`. | Frozen. Sunset 1 September 2027 |

The path carries the major version. Additive changes ship under the same path;
a breaking change ships as a new major version.

## v3 is additive-only

Within `/api/v3` we add; we do not remove or rename. Concretely, **these can
change at any time and are not breaking changes** — write your client so they
do not break it:

- new endpoints, new resources and new verbs;
- new **optional** request fields;
- new fields in a response object — parse leniently and ignore what you do not
  recognise;
- new values in an open vocabulary. Enumerated values published as
  `x-known-values` (webhook event names, for example) are open by
  construction: the list tells you what exists today, not what is allowed
  forever. A closed `enum` in the reference is closed;
- new `expand` targets and new list filters;
- the order of keys in a JSON object, and the wording of an error `detail`.

**These will not change inside `/api/v3`:** removing a field or an endpoint,
renaming anything on the wire, tightening a type, making an optional request
field required, changing an error `code`, or changing what a value means.

Every release gets a line in the [Changelog](/changelog).

## When something has to break

- **REST:** a breaking change ships as a **new base path** (`/api/v4`), never as
  a silent change under `/api/v3`. The two run side by side; nothing about your
  `/api/v3` calls changes on the day `/api/v4` appears.
- **Webhooks:** a breaking change to a payload ships as a **new dated
  `apiVersion`**. Webhooks registered on a dated version keep receiving the
  format they were registered with. Webhooks registered as `latest` follow the
  newest format and can change without notice. Pin a dated `apiVersion` if you
  need a stable payload shape:

  ```bash
  curl -X PATCH https://openapi.niftypm.com/api/v3/webhooks/{id} \
    -H "Authorization: Bearer $NIFTY_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{"apiVersion": "2026-03-20"}'
  ```

## v1.0

**v1.0 will be retired on 1 September 2027.** It stays available unchanged
until then, and receives no new fields, no new endpoints and no behaviour
changes.

Migrate to v3 before that date — see [Getting started](/getting-started) for the
differences and [Migrating from v1](/getting-started#migrating-from-v1) for how
the resource names map across. Changes to the schedule are announced here and on
[r/NiftyPM](https://www.reddit.com/r/NiftyPM/).

v1.0 responses carry `Deprecation: true`, `Sunset: Wed, 01 Sep 2027 00:00:00
GMT` and a `Link` header pointing at this page.

## Staying informed

- [Changelog](/changelog) — every v3 contract release.
- [status.niftypm.com](https://status.niftypm.com) — incidents and degradations.
- [r/NiftyPM](https://www.reddit.com/r/NiftyPM/) — announcements, alongside
  this page.
- [team@niftypm.com](mailto:team@niftypm.com) — questions about a change, or a
  breakage you think we caused.
