Real-world examples of header-based versioning in APIs
Examples of header-based versioning in APIs examples in the wild
Let’s start with what you actually care about: how real APIs do this in production. When people talk about examples of header-based versioning in APIs examples, they usually mean one of three patterns:
- A custom header like
X-API-Version: 2 - A versioned media type like
Accept: application/vnd.myapp.v2+json - A vendor-style header such as
Accept-Version: 2024-11-01
Most serious platforms mix these with good documentation, deprecation policies, and telemetry. Below are several real examples you can adapt.
Stripe-style Stripe-Version header example
Stripe popularized a clean, header-driven approach. Instead of /v1/charges vs /v2/charges, Stripe uses a version header:
GET /v1/charges HTTP/1.1
Host: api.stripe.com
Authorization: Bearer sk_live_...
Stripe-Version: 2023-10-16
The path still contains /v1, but the behavior of the API is driven by the Stripe-Version header. This gives Stripe fine‑grained control over breaking changes while letting them keep a stable URL surface.
Why this matters for you:
- You can ship new behavior tied to a timestamped version.
- Old clients keep working because they send their older
Stripe-Version. - You can roll out per-customer upgrades.
When people ask for best examples of header-based versioning in APIs, this pattern comes up constantly in architecture reviews because it balances stability with evolution.
GitHub vendor media types (Accept header) example
GitHub’s REST API is another example of header-based versioning in APIs examples using the Accept header and vendor media types. A typical request might look like this:
GET /repos/octocat/Hello-World HTTP/1.1
Host: api.github.com
Accept: application/vnd.github+json
When GitHub wants to introduce new behaviors or previews, they use a more specific media type:
Accept: application/vnd.github.v3+json
or for feature previews:
Accept: application/vnd.github.merge-info-preview+json
This is a textbook example of content negotiation used as a versioning mechanism. The URL stays stable; the Accept header signals which representation (and sometimes which version) the client expects.
GitHub documents this approach extensively in their API docs and changelogs, which is part of why it’s often cited as one of the best examples for teams designing public APIs.
Azure and other cloud APIs using api-version headers
Microsoft Azure’s REST APIs famously use an api-version query parameter, but many internal and partner-facing services mirror that value in a header as well. A typical call can look like this in enterprises that standardize around headers:
GET /subscriptions/{subscriptionId}/resources HTTP/1.1
Host: management.azure.com
Authorization: Bearer eyJ0eXAiOiJKV1Qi...
X-API-Version: 2024-05-01
This pattern shows up in a lot of internal platform teams: they keep the public contract query-based for compatibility but enforce header-based versioning for internal consumers and service-to-service calls. If you’re looking for examples include both public and private APIs, this hybrid approach is common in 2024–2025 microservice environments.
E-commerce API with Accept-Version header
Imagine a retail platform with mobile apps that can’t update every week. They adopt a header-based strategy using Accept-Version:
GET /products/12345 HTTP/1.1
Host: api.shop.example
Accept: application/json
Accept-Version: 2023-09
Version 2023-09 might return:
{
"id": "12345",
"name": "Running Shoes",
"price": 89.99,
"currency": "USD"
}
Six months later, the team wants to add regional pricing and metadata without breaking old apps. They introduce version 2024-03:
Accept-Version: 2024-03
and now the response can include:
{
"id": "12345",
"name": "Running Shoes",
"prices": [
{ "region": "US", "amount": 89.99, "currency": "USD" },
{ "region": "EU", "amount": 84.99, "currency": "EUR" }
],
"metadata": {
"category": "Footwear",
"gender": "Unisex"
}
}
Older clients keep sending Accept-Version: 2023-09 and never see the new fields. Newer clients opt in. This is one of the clearest examples of header-based versioning in APIs examples you can show to product managers who worry about breaking changes.
Healthcare API example using custom media types
Healthcare APIs often need very strict contracts. A FHIR-based service (Fast Healthcare Interoperability Resources, widely used in the US and internationally) might use custom media types for versioning. While official FHIR specs are documented by HL7 (hl7.org), many implementers add their own layer of header-based negotiation.
A hospital’s patient API might require:
GET /Patient/123 HTTP/1.1
Host: api.hospital.example
Accept: application/vnd.hospital.fhir.patient.v1+json
Later, when they align with a newer FHIR release, they can introduce:
Accept: application/vnd.hospital.fhir.patient.v2+json
This example of header-based versioning fits tightly regulated environments like healthcare, where you may need to support older EHR systems for years while gradually moving newer clients to more modern resource definitions.
For background on FHIR and versioning concepts in healthcare, you can cross‑reference the US Office of the National Coordinator for Health IT (healthit.gov) and the NIH’s general health IT resources (nih.gov).
Internal microservice API with X-API-Version
Inside companies, the most common examples of header-based versioning in APIs examples are boring but effective. A microservice might expose:
POST /orders HTTP/1.1
Host: orders.internal
Content-Type: application/json
X-API-Version: 2
Version 1 expects:
{
"customerId": "c-1001",
"items": [
{ "sku": "sku-1", "quantity": 2 }
]
}
Version 2 supports additional fields:
{
"customerId": "c-1001",
"items": [
{ "sku": "sku-1", "quantity": 2 }
],
"couponCode": "SPRING24",
"source": "MOBILE_APP"
}
The gateway or service code branches on X-API-Version. This pattern is rarely publicized but shows up in internal documentation, architecture diagrams, and code comments across thousands of companies.
Feature-flagged header versioning for A/B testing
A more advanced example of header-based versioning is when teams combine it with experimentation. Instead of a strict numeric version, they use headers to opt into behavior flags:
GET /search?q=running+shoes HTTP/1.1
Host: api.search.example
Accept: application/json
X-API-Version: 3
X-Experiment-Variant: ranking_v2
The API still guarantees the contract defined by X-API-Version: 3, but within that version, the ranking algorithm behind ranking_v2 can change. This pattern is becoming more common in 2024–2025 as teams ship ML-backed features and need to test them safely.
In practice, these examples include analytics pipelines that track which header versions are in use, how many clients are still on old variants, and when it’s safe to deprecate.
Why teams pick header-based versioning over URL versions
When you line up all these examples of header-based versioning in APIs examples, a few themes emerge about why teams choose headers instead of /v1 in the path.
Cleaner URLs and better resource modeling
Headers keep the URL focused on the resource, not the version. /patients/123 reads like a stable identity. The version becomes part of the HTTP metadata, which is where the HTTP spec expects negotiation to happen anyway.
The IETF’s HTTP semantics and content negotiation discussions (see RFCs linked from ietf.org) consistently treat headers like Accept and Content-Type as the place to express representation details. Versioning via headers is basically leaning into that model.
Independent evolution of clients
In real-world examples include mobile apps, IoT devices, and third‑party integrations that can’t upgrade quickly. Header-based versioning lets you:
- Keep old versions alive for specific clients.
- Upgrade high‑value partners first.
- Gate new features behind opt‑in headers.
Instead of a big‑bang /v2 migration, you can gradually steer traffic to newer header versions while monitoring error rates and performance.
Better fit for API gateways and microservices
In 2024–2025, most serious teams front their services with an API gateway or service mesh. These layers can route based on headers easily:
X-API-Version: 1→ old clusterX-API-Version: 2→ new cluster
That makes blue‑green deployments, canary releases, and region‑specific rollouts more straightforward. Many service meshes and gateways now ship built‑in rules to route by header, which is another reason you see so many examples of header-based versioning in APIs examples in modern architectures.
Design patterns: how to structure your header versions
If you’re trying to move from theory to implementation, the real question is: what should the header actually look like? The examples above fall into three main patterns.
Numeric versions (X-API-Version: 1)
This is the easiest example of header-based versioning to explain to stakeholders:
X-API-Version: 1
X-API-Version: 2
Pros:
- Simple mental model
- Easy logging and metrics
Cons:
- Harder to tie to release dates
- Can become confusing if you have many services (what does “2” mean for each one?)
Date-based versions (2024-11-01)
Stripe and others use date strings:
Stripe-Version: 2024-11-01
Accept-Version: 2023-09-15
Pros:
- You instantly know when a version was introduced.
- You can align with change logs and release notes.
Cons:
- Non‑obvious ordering if you don’t stick to ISO format.
- Might confuse non‑technical stakeholders who expect “v1, v2”.
Media-type versions (application/vnd.myapp.v2+json)
This is the most standards‑aligned example of header-based versioning in APIs examples, because it fully uses content negotiation:
Accept: application/vnd.myapp.v2+json
Content-Type: application/vnd.myapp.v2+json
Pros:
- Clear separation of representations.
- Easy to support multiple representations side‑by‑side.
Cons:
- More verbose for clients.
- Some HTTP clients and API tools need extra configuration.
Common pitfalls when copying these examples
Even the best examples of header-based versioning in APIs can go sideways if you miss a few details.
Forgetting to document default behavior
If a client doesn’t send a version header, what happens?
You should define:
- A default version (often the oldest supported or the newest stable).
- A clear timeline for how long that default will remain unchanged.
Without this, you’ll end up with silent breaking changes when you update the backend, and your telemetry will show mysterious spikes in errors.
Mixing too many versioning strategies
It’s tempting to combine URL versions, query parameters, and headers all at once. The examples include some hybrids, but you should still pick a primary strategy. A good rule of thumb:
- Use headers for behavior and contract.
- Use URLs for resource identity.
- Use query parameters for filtering and search.
Not tracking version usage
All the real examples of header-based versioning in APIs examples that work at scale have one thing in common: they track version usage. That means:
- Logging the version header for every request.
- Building dashboards that show which clients are on which versions.
- Using that data to plan deprecations.
Without this, you’re flying blind when you try to retire X-API-Version: 1.
2024–2025 trends influencing header-based versioning
A few trends are shaping new examples of header-based versioning in APIs you’ll see going forward.
AI and data-heavy APIs
LLM and analytics APIs often need to change schemas and response shapes as models evolve. Header-based versioning lets them:
- Introduce new fields and scoring metadata.
- Phase out deprecated parameters.
- Run A/B tests safely with versioned behaviors.
Regulatory pressure and auditability
In sectors like healthcare and finance, regulators care about which version of an API a client used when a decision was made. Header-based versioning creates a clean audit trail:
- Logs show
X-API-Version: 2024-03. - You can tie that to a documented contract.
For context on how regulators think about data and interoperability, you can look at US government resources like healthit.gov and general policy guidance on usa.gov.
API tooling support
Modern API gateways, observability tools, and client SDK generators increasingly support version headers out of the box. That’s why you see more best examples emerging that lean on headers instead of rewriting URLs or shipping multiple endpoints.
FAQ: examples of header-based versioning in APIs
Q: What are some simple examples of header-based versioning in APIs I can copy today?
A: A very straightforward example of this pattern is adding X-API-Version: 1 to every request and branching on that in your controller or gateway. A slightly more standards-aligned option is using Accept: application/vnd.myapp.v1+json and Accept: application/vnd.myapp.v2+json as you evolve the contract.
Q: Is header-based versioning better than putting versions in the URL?
A: It depends on your priorities. If you want clean, stable URLs and fine‑grained control over contract evolution, the examples of header-based versioning in APIs examples from Stripe and GitHub are hard to ignore. If your clients are very simple or you’re building an internal-only API, a URL version might be easier to reason about.
Q: Can I mix header-based versioning with feature flags?
A: Yes. Many 2024–2025 examples include a base version header (like X-API-Version: 3) plus additional headers for experiments or preview features. Just be clear in your docs which headers affect the contract versus which only tweak behavior.
Q: How long should I support old header-based versions?
A: That’s a product decision, but the pattern from the best public examples of header-based versioning in APIs is to publish a deprecation schedule, send warnings in response headers, and monitor usage before you turn anything off.
Q: Do I have to use custom headers, or can I just use Accept?
A: You don’t have to invent custom headers. Many of the cleaner examples of header-based versioning in APIs examples use Accept and Content-Type with vendor media types. Custom headers like X-API-Version are easier to read but slightly less aligned with HTTP content negotiation.
Related Topics
Explore More API Versioning Strategies
Discover more examples and insights in this category.
View All API Versioning Strategies