API Contracts That Survive Three Product Pivots
Versioning strategy, error shapes and documentation habits that keep integrators happy long after launch.
An API contract is a promise you make to people who cannot read your commit history. The goal is not perfection at launch — it is changeability without breakage.
Version at the edge, not in the domain
Put the version in the URL prefix and keep it out of your domain layer. Controllers and resources translate between versions; the services underneath stay single-shaped. Two versions of a transformer are cheap. Two versions of your business logic are not.
Standardise the error envelope on day one
Every non-2xx response should have the same shape: a stable machine code, a human message, and an optional field map.
code— never localised, never renamedmessage— safe to show a usererrors— field-keyed validation details
Integrators build retry and display logic against code. Changing it later is a breaking change even when the status stays the same.
Additive changes are free, everything else is not
New optional fields, new endpoints and new enum values that clients can ignore are safe. Removing a field, tightening validation or changing a default is not — those need a new version and a deprecation window with dates in the changelog.
Document from the source of truth
Generate the reference from schemas or annotations so the docs cannot drift. Then hand-write the part generators cannot produce: authentication, pagination, rate limits, idempotency and a worked example for the three most common flows.
Test the contract, not just the code
Contract tests that assert response shape catch the accidental rename that unit tests happily ignore. Run them in CI against every version you still support.
Building something that has to scale?
I help teams design architecture, tighten performance and ship products that keep working as the business grows.