# Versioning and deprecation

AI moves quickly, and the platform behind this API keeps pace. That only benefits you if
the API itself stays stable, so the two are deliberately separated: new capability arrives
as it becomes available, while the endpoints you already call keep behaving as they did
the day you wrote against them.

In practice, almost everything we ship is additive: it appears, and nothing you depend on
changes underneath you. Anything that could break a working client is announced first,
dated, and carried on headers your code can read.

The version is in the URL:

```
https://api.genuineai.app/api/v1
```

## Summary

- **Additive changes ship whenever they are ready, without notice.** In practice that
  means capability appearing rather than existing behavior changing.
- **Anything that could break a working client is announced first**, on a schedule your
  code can read off the response headers.
- **Minimum notice** is 90 days for a stable endpoint, 30 days for beta, and none for
  preview. Retiring `/api/v1` altogether would carry 12 months.

## What ships without notice

The following are all additive. They ship continuously and are not announced:

- New endpoints and new resources
- **New fields in responses**
- New optional request fields, query parameters and headers
- New values in an enum a request may *send*
- New error `code` values on a failure path that could already fail
- New response headers
- Relaxed validation, so a request that used to fail now succeeds
- Anything under the hood: performance, infrastructure, model routing

### Five habits that keep a client compatible

Nearly every integration that breaks on an additive change breaks for one of these
reasons. All five are cheap to get right now and difficult to retrofit later:

1. **Ignore fields you do not recognize.** A response gaining a field is routine. A
   client that rejects unknown fields (a strict parser, or a schema with
   `additionalProperties: false`) will break on a change we ship as a matter of course.
2. **Handle enum values you have not seen.** Fall back to a default rather than throwing.
   We will not add a value to an existing response field within a version, but new
   endpoints and new fields carry values your code has not encountered.
3. **Branch on `code`, never on prose.** `title`, `detail` and validation `msg` keys are
   written for people, and they are rewritten for people. See [errors](/errors).
4. **Read limits from `RateLimit-Policy`** rather than hard-coding the numbers in the
   [rate limits](/rate-limits) table.
5. **Do not depend on ordering you did not request.** That covers JSON key order and
   the order of a collection fetched without a `sort`.

## Not part of the contract

The reference is the boundary. Anything not in it is unpublished and can change or
disappear on any deploy:

- Endpoints outside `/api/v1`
- Fields you can observe in a response but that no operation's schema declares
- Prose: `title`, `detail`, and translation keys
- The order of a collection returned without an explicit `sort`
- Rate limit quotas, which are tuned as traffic changes and published in a header for
  that reason
- The `errorId` format, response header order, and latency
- Beta and preview endpoints, described below

## Stability levels

Most of the surface is stable. The other two levels exist so a new capability can reach
you while it is still changing, rather than being withheld until it is finished:

| Level | Marked in the reference | If it has to change |
|---|---|---|
| **Stable** | nothing (the default) | Announced, with a `Sunset` date at least **90 days** out |
| **Beta** | `beta` | Announced, at least **30 days** |
| **Preview** | `preview` | May change or be withdrawn at any time |

No marker means stable, and everything on this page applies to it. Preview is for
evaluation rather than for a production path you cannot change quickly.

## What counts as a breaking change

On a stable endpoint, none of the following happen without going through the deprecation
process below:

- Removing an endpoint, or changing its method or path
- Removing a field from a response, or changing its type
- Adding a required request field, or making an optional one required
- Removing a value from an enum a response can return
- Removing an error `code`, or reusing one to mean something else
- Tightening validation so a request that worked now fails
- Changing the success status an endpoint answers with
- Narrowing the permission or the plan an endpoint requires

## The deprecation process

1. **It is marked in the reference.** The operation is labeled deprecated and the entry
   names its replacement.
2. **We announce it**, with the replacement and the removal date, to the contacts we have
   for affected integrations.
3. **Every response says so.** The endpoint returns `Deprecation` and `Sunset`
   headers ([RFC 9745](https://www.rfc-editor.org/rfc/rfc9745),
   [RFC 8594](https://www.rfc-editor.org/rfc/rfc8594)) on every call, so a client can
   pick it up without anyone reading an email:

   ```http
   Deprecation: @1786320000
   Sunset: Wed, 12 Aug 2026 00:00:00 GMT
   Link: <https://docs.genuineai.app/reference/v1/agents#operation/listAgents>; rel="successor-version"
   ```

   `Deprecation` is when it was deprecated, `Sunset` is when it stops answering, and
   the `Link` points at the replacement.
4. **It keeps working until the `Sunset` date**, at least 90 days from the
   announcement for a stable endpoint and 30 for a beta one.
5. **After that it answers `410 resource_gone`**, not `404`, so you can tell
   "removed on purpose" from "wrong URL".

Log those two headers wherever you log responses. They are the earliest warning
available, they arrive on every call, and they do not depend on an email reaching the
right person at your end.

**The notice period is measured against your integration.** Announcements go to the
integrations a change affects, so what you are promised is about the operations *you*
call: if one of them has to change, you get the full period for it. We do not hold an
endpoint still on behalf of callers who are not there.

An endpoint enters the guarantee the first time you call it. There is no separate list of
protected operations, and nothing you build on is provisional because of how anyone else
happens to use it.

The notice periods are minimums rather than targets. A deprecation usually runs longer,
and the `Sunset` header on the endpoint is always the authoritative date.

## Shortened notice periods

Four circumstances can shorten or remove a notice period:

- A security vulnerability that cannot be fixed compatibly
- A legal or regulatory obligation
- An endpoint returning incorrect data, where continuing to serve it is worse than
  withdrawing it
- Abuse

In those cases we make the change as soon as necessary and notify you as soon as we can.
This exception is for emergencies rather than for convenience, and we treat it that way.

## A future `/api/v2`

`/api/v1` is not being retired. A second version would appear only if something had to
break for everyone at once, and the separation described above means most changes never
require that. If a second version does appear:

- `/api/v2` appears alongside `/api/v1` rather than in place of it. Both stay in the
  reference, behind a version selector.
- `/api/v1` keeps working for at least **12 months** after `/api/v2` is stable, with
  `Sunset` headers tracking the countdown.
- You migrate endpoint by endpoint. There is no cutover date.
