> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.morphiaone.ai/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.morphiaone.ai/_mcp/server.

# Versioning

This page is the promise the rest of the site relies on. Every "branch on the code, not
the message" and "handle an unfamiliar code gracefully" elsewhere is only advice
because of what is written here.

## The unit of compatibility is `/v1`

`/v1` is the HTTP major version. Additive changes stay on `/v1`. A breaking change
means `/v2`, announced before it exists, served alongside `/v1`.

There is no `/v1.1` and there will not be. A path that grows minor versions turns one
integration decision into a recurring migration, and the number in the path stops
meaning anything. The contract's own release version lives in `info.version` inside the
[OpenAPI document](/api-reference), where a tool can read it and your URLs do not have
to change.

## Additive: expect these, do not break on them

| Change                                   | What your code must tolerate                                             |
| ---------------------------------------- | ------------------------------------------------------------------------ |
| a new optional response field            | ignore unknown fields rather than rejecting them                         |
| a new optional request field             | nothing; omitting it keeps current behaviour                             |
| a new endpoint                           | nothing                                                                  |
| a new error code                         | fall back to the status class — [Error reference](/api-reference/errors) |
| a new `details` key on an error          | read `details` defensively; it is contextual, not contractual            |
| a wider numeric range or a longer string | do not assume a length you were not given                                |

Strict schema validation that rejects unknown fields will break on a routine release.
If your stack validates responses, configure it to allow additional properties.

## Breaking: these get a new major and a notice first

* removing an endpoint, or an operation's `operationId`;
* removing a response field, or making an optional request field required;
* changing a field's type, or narrowing an accepted value range;
* removing a member of a closed enum — `JobStatus` is closed at
  `queued | running | succeeded | failed | cancelled`, so adding a state is breaking
  too;
* renaming or removing an error code;
* changing what authentication is required, or which scope an operation needs;
* changing the meaning of an existing field while keeping its name and type.

The last one is the dangerous entry, because it passes every mechanical check. It is
treated as breaking anyway.

## `error.code` is the contract; `error.message` is not

`error.code` is stable and machine-readable. `error.message` is human text that is
rewritten whenever it can be made clearer, in a patch release, without notice. Code
that matches on message substrings will break, and the break will look like ours.
[Errors](/concepts/errors)

`request_id` is always present and always opaque. Log it; do not parse it.

## What the enum promise actually is

A field documented with a fixed set of values will not lose one of them without a major
version. It may gain one if the field is documented as open. Where that matters for a
product — the skin issue list, the makeup product matrix — the page for that product
says which it is.

## Deprecation

Nothing is removed from `/v1` without first being marked deprecated in the contract. A
deprecated operation keeps working exactly as documented, is flagged `deprecated: true`
in the [API reference](/api-reference), and answers `Deprecation` and `Sunset` headers
so your monitoring can see it before your users do. The notice period for a specific
change is stated with the change; a binding one belongs in your agreement.

## How you find out

| Signal                              | Where                                                                             |
| ----------------------------------- | --------------------------------------------------------------------------------- |
| the contract itself, diffable       | the [API reference](/api-reference) and its OpenAPI document                      |
| an operation that is going away     | `deprecated: true` in the contract, and `Deprecation` / `Sunset` response headers |
| a change that needs action from you | only on a new major path (`/v2`), announced before it exists                      |