Skip to content

Data Contracts Matter More Than APIs

An API without a data contract is a suggestion. Architecture Files #13 on who owns field meaning, compatibility, and what happens when consumers disagree about the same payload.

Architecture Files #13 · Part of Binary and Beyond. LinkedIn newsletter edition follows.

Teams celebrate the API.

Swagger is green. Postman returns 200. The integration ticket closes. Someone writes "API complete" in the standup.

Then, three months later, finance and the warehouse disagree about an order that both systems "accepted." The endpoint still works. The JSON still parses. The fight is about what a field was allowed to mean.

That is why data contracts matter more than APIs.

An API is how bytes move. A contract is who is allowed to change meaning, what stays compatible, and what happens when two consumers read the same payload and reach different business conclusions.

The endpoint that "still worked"

Picture a mid-market retailer with a partner catalogue sync.

Commerce exposes GET /products/{sku}. Partners pull nightly. The response includes available_qty, price, and status.

In version one, available_qty means sellable on the website right now.

Six months later, ops wants to reserve stock for VIP wholesale without hiding it from the website. Someone adds a warehouse hold. The field keeps the same name. The partner integration keeps calling the same path.

Website stock and partner stock diverge. Support tickets arrive as "your API is wrong." Engineering opens the endpoint. It returns 200. The schema did not break.

The contract did.

Production Notes #03 argued that truth is owned, not shared. Data contracts are how that ownership travels across a wire. Without them, every consumer invents a private definition of "available," "paid," and "done."

APIs optimise for convenience. Contracts optimise for disagreement.

An OpenAPI file tells you types and required fields.

It rarely tells you:

  • whether null means unknown, not applicable, or deliberately cleared
  • whether status: shipped implies the carrier scan or the warehouse handoff
  • whether adding a field is safe for old consumers, or whether removing one is a breaking event even if the JSON still validates
  • who must be notified before meaning changes — and who has veto

Those answers are the product. The path and the verb are packaging.

I have watched teams version endpoints carefully (/v2/orders) while silently changing what total includes. Tax. Shipping. Discounts. The URL stayed stable. Month-end reconciliation did not.

Versioning the URL is not the same as versioning the meaning.

What a real data contract looks like

Mature integrations treat the payload as a published interface with owners, not a dump of whatever the producer had handy.

That usually means:

Named owners for fields that touch money, inventory, or customer promises. If marketing can rename a segment field without telling billing, you do not have a contract. You have a shared spreadsheet with auth.

Compatibility rules written down. Additive fields only? Deprecation windows? Required vs optional after launch? If the answer is "we'll be careful," consumers will be careful by caching forever and ignoring your emails.

Examples that encode business cases, not just happy JSON. One example for a partial shipment. One for a refund after capture. One for a cancelled order that already reserved stock. Schema without scenarios trains clients to guess.

A place to look when two systems disagree. Production Notes #06 asked what "once" means for a write. Contracts ask what "this field" means for a read. Both need a sentence a human can defend in a war room.

Change process that matches blast radius. A cosmetic label can ship behind a flag. A change to how available_qty is calculated is a product release for every partner who built reports on it.

None of this requires a particular tooling brand.

It requires admitting that the expensive part of an integration is not drawing the arrow. It is keeping the meaning stable while both businesses keep changing.

Why teams skip contracts

Contracts feel like overhead next to "just ship the API."

They also feel political. Someone has to say no when a producer wants to "quickly" overload a field. Someone has to schedule a consumer migration. Someone has to own the awkward email that a partner's dashboard will be wrong for two weeks.

So teams ship the endpoint and hope.

Hope works until the third consumer arrives. Then every silent assumption becomes a negotiation, and the API team becomes a translation desk between departments that never agreed on vocabulary.

When we modernise platforms that grew by "just expose what we have," the salvageable part is usually the transport. The expensive rewrite is the vocabulary: which fields were promises, which were accidents, and which partners built revenue reports on the accidents.

Production Notes #02 made the case that every integration is a distributed system. Distributed systems fail at boundaries. Data contracts are the boundary's constitution.

Producer convenience is consumer debt

Producers favour fields that map cleanly to their database.

Consumers favour fields that map cleanly to their reports.

Those two wishes only align on day one. By month six the producer has added internal flags, renamed enums in the UI but not the feed, and started using notes as a dumping ground for exceptions. Consumers have built alerts, SLAs, and executive decks on the old shape.

A contract is the agreement that neither side gets to silently win that fight.

If you cannot point to a document that says what must stay true for consumers, you are not shipping an API product. You are exporting your schema and hoping nobody builds a business on the wrong column.

Questions to ask before the next "simple API"

Use this when a brief says "expose an endpoint for X" or "let them pull our data."

  1. What business question does each field answer? If you cannot say it in one sentence, consumers will invent three.
  2. Who owns meaning after launch? Name a role, not a Slack channel.
  3. What changes are additive vs breaking — including semantic breaks with the same type?
  4. Which consumers are allowed to cache, and for how long? Stale correct JSON is still wrong.
  5. What does null, empty string, and missing key each mean?
  6. If two consumers disagree about a payload, whose definition wins?
  7. How will we tell partners a meaning change is coming — with enough time to act?

If the answers collapse to "it's in the Swagger," you have documentation. You do not yet have a contract.

A different standard for "API done"

An API is not done when Postman returns 200.

It is done when a new consumer can answer, from the contract alone, what every field means under the ugly cases, who to call when meaning must change, and what will still be true after the next producer release.

That standard feels heavy for a partner feed.

It feels obvious the first time five dashboards cite the same endpoint and none of them match finance.

The integrations I trust are not the ones with the prettiest gateway. They are the ones where the payload's meaning was treated as a product surface — because that is what it always was.


APIs move data.

Contracts decide whether anyone can still agree what the data meant on Tuesday.

Related reading


Architecture Files #13 · Part of Binary and Beyond. LinkedIn newsletter edition follows. Building integrations where payload meaning stays defensible after the third consumer arrives? Start a conversation.

Agency partner

Need delivery stability without adding headcount?

Quick Brown Fox helps agencies ship complex web platforms, tighten QA, and scale engineering capacity—without becoming a liability to your client relationships.