APIs are often described as contracts between systems.
That is only partly true.
An API can describe how to send a request, what fields to include, and what response structure to expect.
But that does not make it a complete contract.
An API is a technical interface.
A contract defines meaning, responsibilities, and guarantees.
Confusing the two creates systems that appear well documented but remain tightly coupled and difficult to change.
An API specification may tell us that a client can call:
POST /payments
It may define fields such as:
amount
currency
creditor account
execution date
payment reference
It may also describe possible responses:
201 Created
400 Bad Request
409 Conflict
500 Internal Server Error
That information is useful.
But it does not answer the most important questions.
What does it mean for a payment to be created?
Has it been validated?
Has the customer’s account been debited?
Has the payment been accepted for processing?
Can it still be cancelled?
Has it been sent to the clearing system?
Is the operation idempotent?
What happens if the client receives a timeout?
These are contract questions.
They are not simply API questions.
A field can be technically valid and still be wrong.
Consider this request:
{
"amount": 100.00,
"currency": "SEK",
"executionDate": "2026-08-15"
}
The JSON may be valid.
The schema may accept it.
But the business operation may still be invalid.
Perhaps the account does not support SEK.
Perhaps the execution date is not a banking day.
Perhaps the customer has exceeded a transaction limit.
Perhaps the payment requires additional approval.
Perhaps the amount includes fees—or perhaps it does not.
The API describes the structure.
The contract defines what that structure means.
A meaningful contract should define more than endpoints and schemas.
It should explain:
the meaning of each operation
the meaning of each field
the business rules that apply
the state transitions that may occur
the guarantees made by the provider
the obligations placed on the consumer
the error and retry behaviour
the idempotency rules
the compatibility policy
the ownership of change
Without these, consumers are forced to build assumptions.
Those assumptions become hidden dependencies.
Hidden dependencies create coupling.
HTTP status codes describe technical results.
They rarely describe the complete business outcome.
A 201 Created response may mean that a database record was created.
It does not necessarily mean that the payment was approved, executed, settled, or completed.
A 200 OK response may confirm that the request was processed.
It does not tell the consumer whether the requested business outcome was achieved.
Technical success and business success are not the same thing.
A good contract makes that distinction explicit.
Many API definitions focus almost entirely on successful requests.
Real contracts are often defined by what happens when something goes wrong.
What should the consumer do after a timeout?
Can the same request be sent again?
Will a repeated request create a duplicate payment?
How long is an idempotency key valid?
Can the provider return a successful result after the client has already timed out?
Will errors use stable codes that software can act on?
Can a previously accepted operation later be rejected?
These behaviours matter more than the shape of the JSON.
Yet they are often missing from the API specification.
Adding a field may appear backward compatible.
But that depends on what the field means.
Changing a field from optional to effectively required can break consumers without changing the schema.
Adding a new enumeration value can break clients that assumed the previous list was complete.
Changing the interpretation of a status can be more damaging than removing an endpoint.
Technical compatibility is not enough.
A contract must preserve semantic compatibility.
Consumers should be able to continue operating without unexpectedly changing their behaviour.
An API without clear ownership becomes difficult to evolve.
Someone must be responsible for:
defining its business meaning
maintaining compatibility
communicating changes
managing deprecation
documenting guarantees
resolving ambiguity
The provider does not merely own the endpoint.
The provider owns the promises made through it.
This does not mean that an API can never change.
It means that change must respect the consumers who depend on the contract.
Consumer-driven contract testing can verify that a provider still produces the fields and responses expected by its consumers.
That is valuable.
But it normally validates observable technical behaviour.
It does not automatically validate whether both sides still agree on the business meaning.
A test may confirm that a response contains:
{
"status": "COMPLETED"
}
But what does COMPLETED mean?
Completed by the API?
Completed by the payment engine?
Sent to clearing?
Booked?
Settled?
Irrevocable?
The syntax may match while the meaning has drifted.
The distinction is the same one we repeatedly encounter in architecture.
The contract is policy.
The API is an implementation detail.
The contract defines what the systems agree to do.
The API defines one way of expressing that agreement.
The same contract might be implemented through:
REST
gRPC
messaging
file transfer
a command-line interface
an internal method call
The transport and interface can change.
The business agreement should remain stable.
That is the architectural boundary.
AI can generate OpenAPI specifications, endpoints, clients, validation code, and automated tests.
But it cannot infer all the promises your business intends to make.
If the contract is unclear, AI will generate a precise implementation of an ambiguous agreement.
That does not remove uncertainty.
It automates it.
AI can accelerate implementation.
It cannot replace the need to define meaning.
An API tells a consumer how to communicate with a system.
A contract tells the consumer what it can depend on.
Endpoints are not promises.
Schemas are not meaning.
Status codes are not business outcomes.
An API is the surface.
The contract is the agreement behind it.
Good architecture protects that agreement while allowing the technical interface to evolve.
An API is not a contract.
It is one implementation of one.