Years ago I was integrating against a carrier's SOAP web service, and I did the most routine thing in the world: I pointed wsimport at their WSDL and let it generate a Java client.
wsimport -keep -s src/generated https://partner.example.com/service?wsdl
Clean build. Every type resolved. The generated proxy looked exactly like what the contract described — because it was exactly what the contract described.
Then the first real call failed. Not a compile error, not a serialization warning. A flat rejection from the server at runtime. One of the generated methods was missing a parameter that the server actually required. The client I'd built faithfully matched the published contract, and the published contract was wrong.
The contract lied, not the tooling
This is the part that stuck with me. wsimport didn't malfunction. My code didn't have a bug in any normal sense. The WSDL — the third party's own machine-readable description of their service — was incomplete. It advertised a method signature the running service didn't accept. Every tool in the chain did its job perfectly, and I still shipped a broken integration, because every tool trusted the contract, and the contract lied.
Here's the uncomfortable general lesson: a machine-readable API contract is only as trustworthy as its agreement with the running service. And almost nothing in your toolchain checks that agreement. Your compiler validates your code against the contract. Your codegen validates the client against the contract. Your tests, if you're disciplined, validate your assumptions against the contract. Every layer validates against the contract — and no layer validates the contract against reality.
What is API contract drift?
API contract drift is when a live API's responses stop matching the contract that describes them — a field changes type, a documented field disappears, an undocumented status code appears — while the endpoint keeps returning a perfectly valid response. It isn't an outage. Nothing errors. The endpoint answers with a clean 200. It just no longer returns the shape your code was written to expect.
Common forms of drift:
- A field changes type — a numeric ID starts arriving as a string
- A field that was always present becomes optional, or vanishes under some conditions
- An undocumented status code or enum value appears
- A date or currency format changes — ISO to epoch, dollars to cents
- Pagination or envelope structure shifts underneath you
None of these trip a status code. All of them can silently corrupt the data flowing into your systems — into billing, reporting, or anything downstream — long before anyone notices.
How API drift shows up in REST and OpenAPI
That original incident was SOAP, and mine was a request-side bug — I was failing to send something the server wanted. It's not the exact failure I'd build a product around. But the shape of it is everywhere, and it didn't stay in the SOAP era.
Swap WSDL for OpenAPI and the story repeats itself constantly. A provider's spec says a field is a string; the live endpoint started returning null last Tuesday. The spec documents six status codes; production quietly added a seventh. An endpoint the spec still lists was deprecated and now returns a 404. Your generated client, your typed models, your contract tests — all green, all validated against a spec that no longer describes what the service actually does.
How to detect API drift in production
The only reliable way to catch this is to continuously detect API drift in production: check the live endpoint against its spec, on a schedule, and get told the moment they diverge. Not at your next release. Not when a customer opens a ticket. The moment it happens.
Two defensive practices help limit the damage in the meantime: validate every external response against an explicit schema at the boundary, so bad data fails loudly instead of propagating silently, and pin to versioned endpoints where a provider offers them, so you control when you adopt changes.
The day you find out
The lesson from that carrier integration never changed. Contracts drift from reality, they do it quietly, and your build is the last place that will ever tell you.
If you depend on third-party APIs — or you publish your own — the question isn't whether the spec is accurate today. It's whether you'll find out the day it stops being accurate, or the day your customer does.
This post was originally published on the DriftSignal blog. DriftSignal continuously checks your live APIs against their OpenAPI specs and alerts you the moment they drift — see how it works.
Top comments (0)