Stability
Since 1.0 there is one promise: an integration written against /api/v1 or
the MCP tools keeps working, on every 1.x release. Versions follow
semver: a patch fixes, a minor adds, and a break would be
a major, served beside the old one rather than instead of it.
Frozen
Section titled “Frozen”- Every route and method under
/api/v1, at the path it has now. - Inputs: every parameter and body property still accepted, with at least the values and sizes it accepted. Nothing optional becomes required.
- Outputs: every property still there, with the type it had. Nothing that was always present becomes optional or null.
- Scopes: no route needs more than it did. What works with a
readkey keeps working with one. - Error shape:
{ "error": { "code", "message", "detail"? } }, and the codes in the REST API table keep their meaning and status. - MCP tools: every tool, by name, with every argument it takes. An argument a tool doesn’t take is refused, since 1.8.0: before, it was dropped without a word, so a misspelled argument did nothing. That was the one change to the tools’ behaviour in 1.x; a call that sends only the arguments its schema lists is unaffected.
- Rendition URLs:
/a/{id}and/a/{id}/{transform}, with the transform keys in use today. Who they serve changed once, at 1.4: people who can see the asset, signed URLs, and public assets (0012).
Free to change
Section titled “Free to change”- New routes, new MCP tools, new optional inputs.
- New properties in responses. Ignore properties you don’t know.
- New values in an enum a response carries, such as a new asset state or type. Handle the ones you know and pass the rest through.
- Error messages: they are for people. Match on
code. - Tool and route descriptions, and the MCP server’s instructions.
- Anything under
/api/auth, which is better-auth’s own surface for signing in; the web app is its only client.
How it’s held
Section titled “How it’s held”The frozen surface is kept as data in the source repository,
contract/api-v1.json and
contract/mcp-v1.json. A test compares
the running spec with them, and CI compares every pull request with the base
branch’s copy, so re-freezing can’t hide a break. Anything added is frozen
with it, by a script that refuses when something breaks
(0010).
Deprecation
Section titled “Deprecation”Something that has to go is deprecated first, never removed in 1.x:
- The OpenAPI operation is marked
deprecated: true, its description says what to use instead, and the release notes say so. - Responses from it carry
Deprecation: trueand aLinkto the replacement. - It keeps working for at least twelve months and until the next major, and is removed there only.
Security fixes are the one exception: if keeping something working keeps a hole open, it closes, and the advisory says what changed.
Supported versions
Section titled “Supported versions”The latest minor of the current major gets fixes; security fixes also go to the previous minor for three months after a new one ships. See SECURITY.md.