Skip to navigation

Versioning

What may change without notice, what may not, and how you find out.

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, where a tool can read it and your URLs do not have to change.

Additive: expect these, do not break on them

ChangeWhat your code must tolerate
a new optional response fieldignore unknown fields rather than rejecting them
a new optional request fieldnothing; omitting it keeps current behaviour
a new endpointnothing
a new error codefall back to the status class — Error reference
a new details key on an errorread details defensively; it is contextual, not contractual
a wider numeric range or a longer stringdo 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

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, 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

SignalWhere
the contract itself, diffablethe API reference and its OpenAPI document
an operation that is going awaydeprecated: true in the contract, and Deprecation / Sunset response headers
a change that needs action from youonly on a new major path (/v2), announced before it exists