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 Startup's API is a contract with every Customer whose code calls it. A gate classifies each Change against the published Interfaces, so no merge breaks a caller.
Additive or breaking
Every Change to a Live Startup's Nouns and Verbs is classified at review, from its diff.
| Change | Kind |
|---|---|
| A new Noun, Verb, 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 | 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 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 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 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 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:
# 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 lists what builds each part, and the API routes lists every route.