Tunas Akara
Back to Blog

API Versioning When Vendors Don't Version Anything

Vendor APIs change without notice. Tolerant readers, contract tests, an anti-corruption layer, and pinning keep integrations alive.

by RayhanUpdated 8 min read

For Technical Teams

apiintegrationversioningreliability
API Versioning When Vendors Don't Version Anything
On this page

On the evening of January 12, 2023, Tweetbot, Twitterrific, Echofon, Fenix, Twitpane, Feather, and Talon all stopped working at once. Users couldn't log in. Every API call failed, and the apps showed as "Suspended" in Twitter's developer portal — with no advance notice.

Developers guessed at the cause that same evening. A week later, new developer-agreement terms made the ban permanent.

Those integrations stopped when the vendor changed its access policy. Their integrations were fine right up until the vendor changed the rules underneath them — no deprecation notice, no version to roll back to. That's the failure mode this article covers: depending on an API someone else controls, who doesn't feel obligated to version it.

Think of a vendor API like a toll road that can reroute overnight with no signs warning you. Most integrations sit somewhere between "disciplined like Stripe" and "no warning like Twitter in 2023." Assume the worse end. You can't negotiate your way out of someone else's roadmap.

What good versioning looks like

URL path or query-param versioning (/v2/orders) is the most common and easiest to reason about. Custom header versioning keeps URLs stable, but it's easy to forget when a client library doesn't set the header. Media-type versioning (Accept: application/vnd.vendor.v2+json) distinguishes response formats through the Accept header, though relatively few vendors use it.

Stripe provides dated API versions, such as 2024-09-30.acacia. Direct HTTP requests use the account default unless overridden through Stripe-Version; modern SDKs may pin the version associated with their release. Check the versions actually used by the application and webhooks, then test an upgrade in staging. (docs, upgrade guide)

GitHub recommends X-GitHub-Api-Version on every request. Without it, GitHub uses a default version that can change when an older version is retired. A previous version is supported for at least 24 months after a new version is released. Check Deprecation/Sunset warning headers; requests to a retired version return 410 Gone. (docs)

Shopify cuts a dated release quarterly, guarantees 12 months of support with 9 months of overlap, and falls forward instead of hard-failing: for example, if 2026-10 has retired and 2027-01 is then the oldest supported release, a request pinned to 2026-10 is served as 2027-01. (docs)

Most vendors you'll actually integrate with — a regional payment aggregator, a hardware SDK, a channel manager — offer none of this. You get one version, called "the API," and it changes whenever the vendor's roadmap says so.

Pattern 1: the tolerant reader

Martin Fowler's Tolerant Reader pattern applies Postel's Law to parsing. Pull only the fields you need out of a response. Ignore unused extra fields. Default only optional fields. Required payment amounts, order identifiers, status, and signatures must still be validated; stop processing and alert if they are missing or invalid.

Fowler's example uses XPath: query //order instead of a rigid absolute path, so a vendor inserting a wrapper element doesn't break you. Applied to JSON: read response.customer.email directly, don't validate the whole object as a strict struct, and never assume field order.

Fowler links to a post by Ian Cartwright that flags something worth internalizing: strict schema validation gives "a false sense of security." A schema pinning every field rejects a harmless change as hard as a breaking one — it can't tell the difference. The other half of the pattern: centralize that parsing in one place, usually a DTO, so one spot in the codebase knows the vendor's real response shape.

Pattern 2: contract tests as a tripwire

Fowler's Consumer-Driven Contracts pattern was built for internal teams. Each consumer writes assertions describing which fields and behaviors it depends on. The provider runs every contract against its own build, for fast feedback before shipping a breaking change.

You can't insert your contract into a vendor's pipeline. But you can write it and run it yourself against their sandbox on a schedule — a tripwire, not a merge gate. Assert the exact fields, types, and status codes your integration relies on, and run that check nightly. When a field silently disappears or changes type, the next test run can alert you. Detection depends on test frequency and sandbox similarity to production.

Pattern 3: the anti-corruption layer

Give the vendor's data shape exactly one place to enter your system.

Loading diagram…

Without this boundary, a vendor renaming customer_email to contact_email means a grep across every service that ever touched an order. With it, a straightforward rename may be isolated to the parsing layer. Everything downstream never learns the field name changed — the parsing logic lives inside this one boundary, nowhere else.

Pattern 4: pin and monitor

Where the vendor supports it, pin to a specific version instead of floating on whatever the API returns today. Mid-tier vendors increasingly copy Stripe's dated-version model, minus the discipline. Pinning turns an involuntary break into an upgrade you schedule.

Where pinning isn't available — most vendors — monitoring is what's left. Run the pattern-2 contract tests against production too, not just sandbox: the two drift, or sandbox never gets touched at all. A scheduled comparison of response shapes can detect drift at the next run. It does not catch every behavioural or access-policy change.

Put change-notification duties in the contract

Technical defenses address part of the risk. The other half is contractual, and it's worth doing even though most vendors won't reach Stripe or GitHub's discipline.

Microsoft's REST API Guidelines define a breaking change generically as anything affecting the contract or backward compatibility, then require each team to write its own concrete list: Azure treats a new JSON response field as breaking, Office 365 doesn't. Borrow that model. Make the vendor hand you a specific definition, not a vague promise.

LinkedIn's breaking-change policy is easier to lift directly. Breaking changes — removing a field, adding a required parameter with no default, a DELETE switching from soft- to hard-delete — get advance email notice. Non-breaking changes, like a new optional field, ship with no notice.

LinkedIn also reserves the right to skip notice for critical bug, legal, security, or privacy fixes. Read that carve-out closely: it covers exactly the kind of change that breaks integrations.

Ask for three things: a written definition of "breaking," a minimum notice period, and a real notification channel — email or webhook, not a changelog nobody checks. Whether a vendor agrees depends on its policy and your negotiating position. That's why you build the four technical patterns regardless of what the contract says.

What to demand, and what to build anyway

Before signing: a written breaking-change definition, a minimum notice period, a real notification channel, and a pinnable version if they offer one.

Build regardless of what they promise: a tolerant reader as the sole thing touching the vendor's raw response, and contract tests on a schedule against sandbox and production. Add an anti-corruption layer as the single translation point, and monitoring at a frequency suited to operational needs. Scheduled tests can detect a change only on their next run. A vendor's promise is a mitigation. Your own defenses are what holds when it doesn't.

If your integrations span multiple hardware or protocol types rather than one REST API, the same translation-boundary idea shows up in normalizing multi-protocol IoT devices. Different problem, same fix.

Related Posts

Need help applying this approach?

Business Operations System Development

Bring orders, customer data, and staff workflows into a system shaped around your business, with clear permissions and reports.

Explore related services

Describe the operational problem you are facing so we can discuss a suitable next step.

Share this article
Free Initial Discussion