API Contract: What It Is and How to Write One (2026)
An API contract is the agreement between an API and the code that calls it. It says: send these requests, get these responses; this field is required, this field is optional; this version is supported until this date. When the contract is clear and enforced, integrations stay stable across releases. When it is vague, every release breaks something for somebody, and the support load grows in proportion to how many integrations you have shipped.
This guide covers what an API contract actually contains, the difference between a contract and the OpenAPI spec people sometimes confuse it with, the seven steps for writing one from scratch, and how contract testing keeps the implementation honest. The 2026 wrinkle is that AI agents now consume APIs through MCP, which raises the stakes on contract clarity in a way that did not exist five years ago.
What is an API contract?
An API contract is the formal agreement that defines how an API behaves. It covers the endpoints, request and response shapes, authentication, error formats, rate limits, and versioning policy. Both the provider and the consumer build to the contract, and contract tests verify the implementation matches what the contract promises.
The contract is not the same thing as the source code, and it is not the marketing description on your developer portal. It is the precise, machine-readable plus human-readable specification of behavior. A team can change the implementation behind the contract without breaking anything as long as the contract holds; conversely, a tiny change to the contract (a required field becoming optional, a status code changing) can break every consumer in production even if the code looks the same.
What an API contract includes (the 8 required pieces)
Most articles list three or four pieces. A complete contract covers eight:
- Endpoints and methods. Every URL the API exposes and which HTTP methods it accepts on each path. Stable paths matter; renaming an endpoint is a breaking change.
- Request shapes. Required fields, optional fields, types, validation rules, and header expectations for every method on every endpoint.
- Response shapes. What comes back on success, what comes back on each error class, and which status codes are used in which situation.
- Authentication. API keys, OAuth scopes and flows, mTLS, JWT structure. Cover both how to get credentials and how to rotate them.
- Rate limits and quotas. Per-endpoint and per-customer ceilings, the response behavior when exceeded (
429 Too Many Requestswith aRetry-Afterheader is the standard), and how customers see their current usage. - Error catalog. Every error code the API can return, each tied to a machine-readable identifier, a human-readable explanation, and the field or condition that caused it. A contract without an error catalog forces consumers to handle errors by string matching, which is fragile.
- Versioning policy. How versions are named (URI versioning like
/v1/ordersis the most common), how long each version stays live, how breaking changes are signaled, and how customers will be notified about deprecation. - Service-level expectations. Uptime target, latency expectations, support response times. If you do not publish these, customers assume the worst, and your enterprise sales conversations stall.
Some of these belong in a machine-readable spec (OpenAPI). The rest belong in human-readable documentation. Both halves together are the contract.
API contract vs OpenAPI spec vs API documentation
People conflate these three terms constantly, which causes real confusion in API reviews. Here is the disambiguation:
| API contract | OpenAPI spec | API documentation | |
|---|---|---|---|
| What it is | The full agreement | A machine-readable description of endpoints and shapes | Human-readable explanation for developers |
| Format | Spec + docs + SLA together | YAML or JSON | HTML, Markdown, rendered docs |
| Source of truth for | Behavior | Structure | Adoption |
| Tested by | Contract tests | Schema validators | Manual review and analytics |
| Audience | Provider, consumer, agent runtime | Code generators, validators, agents | Human developers |
The cleanest setup in 2026 is to write the OpenAPI spec, generate the documentation from it, and treat the spec plus the documentation plus the deprecation policy as the contract together. The contract is broader than the spec; the spec is the machine-checkable subset of the contract.
How to write an API contract from scratch (step-by-step)
The seven-step sequence that holds up across teams:
- Start from the consumer. Write three to five example calls you expect a real developer (or AI agent) to make. If the example is awkward, the contract is awkward, and no amount of polishing the spec later will fix it.
- Write the OpenAPI spec. Define paths, methods, request and response schemas, security schemes. Pick the spec version (3.0 or 3.1) and stick with it across the API. Use semantic field names, not abbreviations.
- Document the auth scheme separately. OAuth flows, token TTLs, scope semantics, key rotation policy. The OpenAPI
securitySchemesblock describes the shape; the human-readable doc explains why and how. - Define the error catalog. Every endpoint can return certain error codes. Each gets a stable machine-readable identifier (e.g.,
payment_method_declined) and a one-paragraph explanation. - Write the versioning policy. Pick URI versioning (
/v1/orders) or header versioning. State explicitly how long deprecated versions stay live. Twelve months is the standard for paid public APIs. - Publish the SLA. Uptime target, latency expectations, support response times by tier. If you do not publish these, prospects will not trust the API for production workloads.
- Get the contract reviewed before code starts. Have one external consumer (real or stand-in) try to implement against the contract on paper. Their questions are the questions the contract failed to answer; rewrite the contract until the questions go away.
The contract becomes the artifact engineering implements against. Changes to it require change-control, not a casual pull request. This is also where API design principles start paying off, because most design mistakes are visible in the contract before any code exists.
Contract testing (Provider vs Consumer-driven)
A contract is only useful if you can verify the implementation matches it. Contract testing does that mechanically, in CI, on every change.
There are two flavors, and serious teams run both:
- Provider contract tests run against the API server. They send realistic requests, capture the responses, and assert that everything matches the OpenAPI spec. The mature tools in 2026 are Dredd (sends every request in your spec and validates responses), Schemathesis (property-based: generates thousands of valid and edge-case requests from the spec), and the OpenAPI validators built into most API gateways. These run in CI before deployment.
- Consumer-driven contract tests flip the direction. Each consumer team defines what they need from the provider, and the provider runs those tests to ensure changes do not break known consumers. The standard tools are Pact and Spring Cloud Contract. These are the antidote to “we did not know team X was using that field.”
The discipline that has moved up the priority list since 2024: idempotency testing on POST and PATCH endpoints. AI agents retry aggressively, often without the developer’s explicit instruction. If your contract says POST /payments is idempotent when given an Idempotency-Key header, your contract test should send the same request twice and assert that the second call returns the same response (and the same resource ID), not a duplicate charge.
Contract versioning and deprecation (with IETF RFC 8594 and RFC 9745)
Contracts evolve, and the only real question is how visibly that evolution gets communicated to the consumers who depend on them.
Two non-negotiables when a contract changes:
- Breaking changes get a new version. If you change a field’s type, remove an endpoint, or alter required fields, you bump the major version and run old and new in parallel for the published deprecation period.
- Non-breaking changes are documented in a changelog. New optional fields, new endpoints, and new error codes are additive. They do not require a version bump, but they belong in the changelog so consumers can take advantage of them.
The HTTP-native way to communicate deprecation is a pair of standard response headers: Sunset (defined in IETF RFC 8594, published May 2019) and Deprecation (defined in IETF RFC 9745). When set, SDKs and well-behaved clients warn developers automatically. Sunset carries an HTTP-date for when the endpoint goes away; Deprecation indicates the endpoint is deprecated as of a given date. Use both: one says “this is going to be removed,” the other says “here is the exact moment.”
Sensible deprecation periods by category:
| API category | Standard deprecation period |
|---|---|
| Paid public API | 12 months |
| Free public API | 6 months |
| Partner / B2B API | 6-12 months by contract |
| Internal API | 90 days |
Versioning is one of the parts of the contract that compounds the most over time. A contract without a deprecation policy in writing accumulates versions until engineering velocity collapses under the weight of supporting all of them. State the policy on day one of the contract, before you have shipped your first version.
API contracts in 2026: AI agents, MCP, and idempotency
Three things shifted in 2025-2026 that put more weight on the API contract than ever before.
Agents read the contract more carefully than humans do. When an LLM application chooses which endpoint to call from your OpenAPI spec, it reads the summary, description, and operationId fields literally. Vague or marketing-flavored descriptions cause wrong tool selection. A description: "Manages payment objects" is not enough; the agent needs description: "Creates a charge against a saved payment method. Idempotent when called with an Idempotency-Key header." Treat those fields as user-facing copy, because they now are.
Agents retry by default, so idempotency moves up the priority list. The Idempotency-Key header pattern, popularized by Stripe and widely adopted across payments and infrastructure APIs, belongs in the contract for every POST and PATCH. Without it, agent retries produce duplicate resources in production. With it, retries are safe by construction. Document the key TTL, the conflict response, and the supported HTTP methods. The IETF has an ongoing draft “The Idempotency-Key HTTP Header Field” that aims to standardize the convention.
MCP exposes the same contract to a different runtime. The WSO2 AI Gateway auto-generates an MCP server from an OpenAPI spec, so the same API a company already publishes for human developers becomes agent-consumable without a separate build. The MCP and LLM proxy components inside the AI Gateway handle inbound agent calls and outbound LLM calls respectively, but both rely on the source contract being precise. The clearer the OpenAPI spec, the better the agent experience, with no duplicated work and no second source of truth to keep in sync.
Common API contract mistakes
The failure modes that show up most often in real reviews:
- Treating the OpenAPI spec as the entire contract. The spec covers structure; it does not cover auth flows, error semantics, rate limit policy, deprecation period, or SLA. Teams that ship “the spec” and call it done create gaps consumers fill with guesses.
- No error catalog. Returning
400 Bad Requestwith a free-textmessagefield means consumers must string-match to handle errors. Within a year, the support load is dominated by “what does this error mean?” tickets. - Implicit versioning. No version policy means every change is a potential breaking change. The first time a customer is broken by a “harmless tweak,” trust is gone.
- Marketing language in
descriptionfields. “Powerfully manages your payments” tells an agent (or a human) nothing. Descriptions should be operational: what the endpoint does, what side effects it has, what makes it idempotent. - No idempotency on
POST. Acceptable in 2018; not acceptable in 2026 when half your traffic might be coming from an agent that retries on any transient error. - Contract drift in production. The contract says one thing; the live API returns something else. Without contract observation in production, drift accumulates silently until a major consumer breaks.
Most of these are caught by either an external-consumer review (step 7 above) or production observability that compares live traffic to the spec.
How Moesif and WSO2 enforce API contracts in production
A contract is only as good as the runtime that enforces it. WSO2 API Manager applies governance policies against the OpenAPI spec at design time and merge time, so contract violations get caught before the deployment that would have shipped them. Once the API is live, Moesif records every request and response per customer, which gives the data needed to detect contract drift in production: endpoints returning shapes the spec does not describe, status codes that do not match the catalog, deprecated endpoints still being called from named customers.
The combined stack covers contract design and enforcement at the gateway (WSO2) plus contract observation in production traffic (Moesif), which is the loop most API teams are missing. See our API lifecycle guide for how the contract fits into the broader development cycle, from initial design through deprecation.
Next steps
A clear API contract is the cheapest way to keep integrations stable as your API evolves. Once your contract is in production, the next question is whether the implementation actually matches it. Start a 14-day Moesif free trial to monitor live traffic against your contract per endpoint and per customer, and surface drift before it costs you a customer. No credit card required.
Frequently asked questions
What is an API contract in simple terms? It is the agreement between an API and the code that calls it: the endpoints, request shapes, response shapes, authentication, errors, rate limits, and versioning policy. Both sides build to it, and contract tests check that the running API matches what was promised.
Is an OpenAPI spec the same as an API contract? No. The OpenAPI spec is the machine-readable structural part of the contract. The full contract also includes the auth scheme, error catalog, versioning policy, and SLA in human-readable documentation.
How do you write an API contract? Start from three to five example consumer calls. Write the OpenAPI spec. Document auth, errors, versioning, and SLA. Get the contract reviewed by an external consumer before any production code is written, and rewrite until their questions go away.
What is contract testing? Automated verification that the API server’s actual behavior matches the contract. Provider contract tests run against the API and check spec compliance using tools like Dredd or Schemathesis; consumer-driven tests using Pact or Spring Cloud Contract verify that the provider has not broken known consumers.
What is contract-first API development? The practice of writing the API contract (OpenAPI spec plus docs) before any server code. The spec generates server stubs, client SDKs, and documentation by construction, so all three artifacts stay in sync as the contract evolves.
How long should a deprecated API version stay live? Twelve months for paid public APIs, six months for free public APIs, ninety days for internal APIs. State the deprecation period in your contract on day one, and use the Sunset (RFC 8594) and Deprecation (RFC 9745) HTTP response headers to communicate it programmatically.