Team contracts: APIs and data cannot run on trust alone
Why internal interfaces require explicit expectations - around structure, quality, and how changes are handled.
When one team builds an API that another team consumes, the temptation is to skip the formalities. Everyone is in the same company, everyone knows each other - a verbal agreement is enough. That works while both teams are small and sit near each other. The question of why internal integrations should not happen by word of mouth is the starting point - contracts are the natural next step once that principle is in place.
The moment one developer goes on leave or priorities shift, the verbal agreement becomes a source of incidents. A field got renamed. The date format changed. A new version was deployed without warning. The consuming team finds out when production falls over.
What a contract means for an internal product
A contract is an explicit, written expectation between two parties: what exactly one component provides to another, in what format, with what guarantees, and how it behaves when things change.
For an API this could be a description of endpoints and types - documentation that stays current. For data it could be a table or file schema, plus a description of what each field means, what the valid range of values is, and what happens at the edges. At the point where many APIs need governing together, integrations become a managed portfolio - contracts are what make that governance possible.
The contract does not need to be complicated. But it must be written down and known to both sides.
Why trust does not work as a mechanism
The problem with trust is not bad intent. The problem is that each team optimises for its own concerns. The producing team changes internal structure because it is more convenient from their side. The consuming team does not know about the change in advance because nobody was obligated to tell them.
In multi-team systems this accumulates. Each individual change is small. But after a year the consuming team's codebase has dozens of spots that say "if the field is empty that means X, if it is null that means Y, and if it is the string 'N/A' that means something else entirely". These are not bugs. They are adaptations to a contract that was never upheld.
What an explicit contract changes
An explicit contract shifts a few things.
It moves the conversation about changes to a different plane. If a contract exists, changing it is an event that requires coordination. You cannot simply rename a field and deploy. You either agree with the consumer, maintain backward compatibility, or version the interface.
It makes data quality expectations explicit. "This field is always populated" and "may be null if the customer did not provide it" are different contracts, and the consuming team needs to know which one they are working with.
It simplifies diagnosis. When something breaks, the first question is: did someone violate the contract? That is far more specific than a general search for the cause.
What a minimal contract looks like
For most internal systems, a formal 50-page specification is not needed. A few things are sufficient:
- A description of the data structure or interface - types, fields, formats.
- An explicit indication of which fields are required and which are optional.
- A change policy: at minimum, how much notice the consumer gets before a breaking change.
- A description of quality guarantees: what error rate is acceptable, what happens when the service is unavailable.
All of this can live in a README or a Wiki page next to the code. The important thing is that it stays current and both sides know where to find it.
A simple test
If your teams discover interface changes through failed tests or production incidents rather than advance notice - contracts are not working.
A few questions to assess the situation:
- Does the consuming team know where to look to understand what they have been promised?
- Is there a process that requires sign-off when a public interface changes?
- Are data quality expectations documented - not just structure, but the semantics of each field?
- When data does not match expectations, is there explicit handling or silent adaptation?
Where the answers are vague, trust is already doing the work a contract should do. Eventually it breaks.