# Compatibility

URL: /code/builders/software/compatibility · Id: `page:code/builders/software/compatibility`

> A Live Startup's API is a contract: every Change is classified, breaking Changes bump the version, and every pinned version keeps serving.

A [Live](/business/lifecycle/states/live) [Startup](/business/nouns/startup)'s API is a contract with every [Customer](/business/nouns/customer) whose code calls it. A gate classifies each [Change](/business/nouns/change) against the published [Interfaces](/business/nouns/interface), so no merge breaks a caller.

## Additive or breaking
Every Change to a Live Startup's [Nouns](/business/nouns/noun) and [Verbs](/business/nouns/verb) is classified at review, from its diff.

| Change | Kind |
| --- | --- |
| A new Noun, Verb, [Event](/business/nouns/event), or optional input | Additive |
| A new property on an output | Additive |
| A removed or renamed Noun, Verb, property, or Event | Breaking |
| A new required input, or a narrower type or enum | Breaking |
| A changed meaning, unit, or default [Mode](/business/nouns/mode) | Breaking |
| A stricter rule on an existing Verb | Breaking |

An additive Change ships to every version at once. A restyle, a copy edit, or a new [Page](/business/nouns/page) is not an API Change at all, and never touches the version.

## Breaking Changes bump the version
A breaking Change merges only as a new API version, `v2` after `v1`, with a version gate: a pair of transforms between the two shapes. Requests at `v1` pass through the gate down, and responses come back up, so `v1` callers see exactly what they saw before.

[SoftwareBuilder](/code/builders/software) writes the gate when the diff is mechanical: a rename, a split field, a new required input with a default. A change of meaning needs a gate written by hand. A breaking Change with no gate is `refused` with reason `breaking_change_unversioned`, and the merge waits.

## Every caller pins a version
A caller always knows which contract it gets.

| Caller | What pins its version |
| --- | --- |
| An API key | The version current when the key was created |
| A request | A version in its path, such as `/v1`, overriding the key |
| The SDK | Its major release |
| A webhook endpoint | The version current when it subscribed, for every Event it receives |
| An [Agent](/business/nouns/agent) over MCP | Its key: tool names and descriptions match that version's reference |

An unversioned path tracks the latest version. Pinned versions keep serving for as long as any caller pins them; nothing retires a version a Customer still calls.

## Upgrading
A Customer upgrades on its own schedule. It points a `test` key at the new version, runs its own code against it, then moves its `live` key's pin. Each version's reference shows the shapes that version serves, and every page marks what changed since the one before.

The [Changelog](/code/systems/changelog) [System](/business/nouns/system) publishes every version the moment it merges. Notes come from the gates: what changed, which Verbs it touches, and the one-line upgrade. Customers subscribe by email, feed, or webhook, and an Agent reads the same notes in Markdown.

## A worked upgrade
ratebook.dev sells sales-tax rates to online checkouts. Its `Rate.lookup` Verb returned one `rate` and one `jurisdiction`. Customers asked for the county share, so the Startup renamed `rate` to `percent` and split `jurisdiction` into `state` and `county`.

SoftwareBuilder classified the Change as breaking and derived the gate from the diff. The merge shipped `v2`, and every existing key stayed on `v1`:

```bash
# Pinned by the key: the v1 shape, unchanged
curl "https://api.sb/ratebook.dev/rates/lookup?zip=94107" \
  -H "Authorization: Bearer $RATEBOOK_KEY"
# { "rate": 8.625, "jurisdiction": "San Francisco, CA" }

# Pinned by the path: the v2 shape
curl "https://api.sb/ratebook.dev/v2/rates/lookup?zip=94107" \
  -H "Authorization: Bearer $RATEBOOK_KEY"
# { "percent": 8.625, "state": "CA", "county": "San Francisco" }
```

## Next
[SoftwareBuilder](/code/builders/software) lists what builds each part, and the [API routes](/code/api/reference) lists every route.