Real‑world examples of versioning APIs with Swagger: practical examples that actually work
Most teams don’t start by arguing about versioning theory. They start with a problem:
“We need to change a field, but 200,000 clients already depend on the current response. How do we not break them?”
That’s where examples of versioning APIs with Swagger: practical examples matter. Let’s start with concrete patterns you’ll see in production systems today.
Example of simple URL versioning in OpenAPI 3
The most common example of API versioning you’ll find in Swagger docs is URL versioning. It’s blunt, obvious, and easy to debug.
openapi: 3.0.3
info:
title: Orders API
version: 1.0.0
servers:
- url: https://api.example.com/v1
paths:
/orders:
get:
summary: List orders (v1)
operationId: listOrdersV1
responses:
'200':
description: A list of orders
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/OrderV1'
components:
schemas:
OrderV1:
type: object
properties:
id:
type: string
total:
type: number
format: float
A typical example of a v2 evolution adds fields without breaking v1. You publish a second spec:
openapi: 3.0.3
info:
title: Orders API
version: 2.0.0
servers:
- url: https://api.example.com/v2
paths:
/orders:
get:
summary: List orders (v2)
operationId: listOrdersV2
responses:
'200':
description: A list of orders with currency and status
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/OrderV2'
components:
schemas:
OrderV2:
allOf:
- $ref: '#/components/schemas/OrderV1'
- type: object
properties:
currency:
type: string
example: USD
status:
type: string
enum: [PENDING, PAID, CANCELED]
This is one of the best examples for teams starting out: two Swagger documents, two base URLs, one codebase behind them. You can even reuse schemas with allOf to keep duplication tolerable.
Path‑segment versioning inside a single Swagger file
Sometimes you don’t want multiple specs. Maybe you’re a small team, or your CI pipeline isn’t ready for multi‑spec publishing. You can keep examples of versioning APIs with Swagger: practical examples in a single OpenAPI file by versioning in the path.
openapi: 3.0.3
info:
title: Customer API
version: 1.1.0
servers:
- url: https://api.example.com
paths:
/v1/customers/{id}:
get:
summary: Get customer (v1)
operationId: getCustomerV1
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/CustomerV1'
/v2/customers/{id}:
get:
summary: Get customer (v2)
operationId: getCustomerV2
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/CustomerV2'
In Swagger UI, consumers see both /v1/... and /v2/... side by side. This is a nice example of how to:
- Keep everything visible in one place
- Document deprecation notes directly in
descriptionfields - Gradually migrate clients from v1 to v2
You can mark older endpoints clearly:
description: |
Get customer (legacy v1).
**Deprecated:** Use `/v2/customers/{id}` instead.
deprecated: true
This pattern shows up frequently in public APIs from fintech and logistics companies where they want new and old versions visible in the same developer portal.
Header‑based versioning: real examples when URLs must stay stable
Some teams can’t change URLs easily. Maybe there’s a firewall rule, a partner contract, or an app store policy tying you to /api. In that case, examples of versioning APIs with Swagger: practical examples often rely on headers.
A common pattern is a custom header like X-API-Version:
openapi: 3.0.3
info:
title: Inventory API
version: 2024.1.0
servers:
- url: https://api.example.com
paths:
/inventory/items:
get:
summary: List inventory items
parameters:
- in: header
name: X-API-Version
required: false
schema:
type: string
enum: ['1', '2']
description: |
Optional API version header.
If omitted, defaults to version 1.
responses:
'200':
description: Items for requested version.
To give a best example of clarity, some teams split this into separate operations using oneOf in the response schema, but that can get messy. A cleaner approach is to maintain two Swagger specs that share the same path but describe different behavior, and route by header at the gateway (for example, using an API gateway like Kong or Apigee).
Even the Microsoft REST API guidelines discuss versioning strategies, and header‑based approaches remain popular when you can’t afford URL churn.
Media‑type versioning: vendor‑specific content types
Another class of examples of versioning APIs with Swagger: practical examples comes from media‑type versioning. Instead of versioning the URL or a custom header, you version the Accept header:
Accept: application/vnd.example.orders.v2+json
In Swagger / OpenAPI:
paths:
/orders:
get:
summary: List orders with media-type versioning
responses:
'200':
description: Orders response
content:
application/vnd.example.orders.v1+json:
schema:
$ref: '#/components/schemas/OrderV1'
application/vnd.example.orders.v2+json:
schema:
$ref: '#/components/schemas/OrderV2'
This is a favorite in some large enterprises because:
- You keep a clean, stable URL surface
- You can serve multiple representations from the same endpoint
But it’s also easier to misconfigure, and many client libraries make vendor media types awkward. Still, as real examples go, this is common in internal platforms and microservice ecosystems.
Versioning schemas, not just endpoints
One of the subtler examples of versioning APIs with Swagger: practical examples is schema‑only versioning. Instead of advertising new versions via URLs, you evolve the schemas and keep the path stable.
For example, you might keep /users/{id} unchanged, but add a new UserProfileV2 schema used only when a query parameter is present:
paths:
/users/{id}:
get:
summary: Get user
parameters:
- in: query
name: profileVersion
schema:
type: string
enum: ['v1', 'v2']
description: Optional profile version.
responses:
'200':
description: User profile
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/UserProfileV1'
- $ref: '#/components/schemas/UserProfileV2'
You then document the behavior clearly in descriptions and examples. This pattern often appears when a team wants to run an A/B test or gradually introduce additional fields without formally calling it “v2” at the URL level.
Multi‑version Swagger UI: one portal, many specs
By 2024, a lot of API platforms have adopted a pattern where Swagger UI (or ReDoc) presents multiple versioned specs in a single portal. This is one of the best examples of versioning APIs with Swagger: practical examples that scale to dozens of services.
Typical setup:
openapi-orders-v1.yamlopenapi-orders-v2.yamlopenapi-payments-v1.yamlopenapi-payments-v2.yaml
Swagger UI can be configured with a list of URLs:
const ui = SwaggerUIBundle({
urls: [
{ url: '/specs/openapi-orders-v1.yaml', name: 'Orders API v1' },
{ url: '/specs/openapi-orders-v2.yaml', name: 'Orders API v2' },
{ url: '/specs/openapi-payments-v1.yaml', name: 'Payments API v1' },
{ url: '/specs/openapi-payments-v2.yaml', name: 'Payments API v2' }
],
dom_id: '#swagger-ui'
});
This isn’t just convenient; it’s a documentation strategy. It lets you:
- Keep each version’s contract frozen
- Show deprecation timelines in descriptions
- Give partner teams a stable reference for each integration
In 2024–2025, larger organizations often pair this with contract testing (for example, using tools inspired by consumer‑driven contracts) to ensure no breaking changes slip into a “frozen” spec.
Real migration example: evolving a healthcare‑style API safely
Consider a hypothetical healthcare API inspired by public data APIs like those described by the CDC and NIH. You start with patient lab results:
## v1
paths:
/v1/lab-results/{patientId}:
get:
summary: Get lab results (v1)
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/LabResultV1'
Later, you need richer metadata, units, and reference ranges. Instead of breaking v1, you add v2:
## v2
paths:
/v2/lab-results/{patientId}:
get:
summary: Get lab results (v2)
description: Includes units, reference ranges, and LOINC codes.
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/LabResultV2'
This example mirrors how real health APIs evolve: keep v1 stable for existing EHR integrations while new partners adopt v2. Swagger makes the contract for each version explicit, which is critical in regulated environments where you may need to document exactly what changed and when.
If you need to support research workflows or public health dashboards, you can also version by date in the info.version field (for example, 2024-09-01) while keeping URL versions shorter. That’s a pattern you’ll see in some open data APIs.
Versioning strategy trends in 2024–2025
If you look across modern API platforms, a few trends stand out:
- OpenAPI 3.x has become the default for new examples of versioning APIs with Swagger: practical examples. OpenAPI 2.0 (Swagger 2) is still around, but new tooling is clearly optimized for 3.x.
- More teams use semantic versioning in
info.version(1.2.3) paired with coarse‑grained URL versions (/v1,/v2). This gives them room for non‑breaking changes without forcing a URL change. - Contract testing and CI validation are now normal. Many pipelines run
openapi-diffor similar tools to check for breaking changes between versions before deploy. - There’s a noticeable shift toward backward‑compatible evolution. Instead of constant v2, v3, v4 churn, teams add fields, keep old ones, and only cut a new major version when absolutely necessary.
These trends all favor having clear, well‑maintained Swagger definitions for each version. Your OpenAPI specs become the source of truth for what changed.
Practical tips: picking the right versioning pattern
With all these examples of versioning APIs with Swagger: practical examples in mind, how do you pick a strategy?
Think about:
- Who are your consumers? Public partners often prefer obvious URL versioning; internal teams might tolerate header or media‑type versioning.
- How often will you change things? If change is frequent, plan for multiple specs and automated diffing.
- Regulatory or audit needs? In domains like healthcare or finance, clear versioned contracts help when you need to explain behavior at a specific point in time. That’s one reason public health data APIs from organizations like the CDC tend to document versions explicitly.
In practice, URL versioning plus separate OpenAPI specs gives you the cleanest paper trail and the least confusion.
FAQ: common questions about Swagger and API versioning
Q: Can you give more examples of versioning APIs with Swagger: practical examples for internal microservices?
For internal microservices, teams often skip visible /v2 URLs and instead version by service name and spec file. For example, billing-service-v1.yaml and billing-service-v1.1.yaml, both pointing at the same URL paths. Deployments are coordinated so that consumers know which spec they target. This keeps URLs stable inside the cluster while still giving you explicit contracts.
Q: What’s a good example of avoiding breaking changes without bumping the version?
Additive changes are your friend. Adding new optional fields, new endpoints, or new enum values (if clients ignore unknown values safely) usually doesn’t require a new major version. A concrete example: adding a currency field to OrderV1 while keeping the original fields and defaults. You document the field in Swagger, but keep info.version at 1.1.0 instead of jumping to 2.0.0.
Q: Do I need a new Swagger file for every minor version?
Not necessarily. Many teams only create a new spec when they introduce a breaking change or a new URL version. Minor, backward‑compatible updates can stay in the same file with an updated info.version and a changelog section in the description.
Q: Are there examples include both URL and header versioning together?
Yes. A pattern you see in larger platforms is /v1 and /v2 URLs combined with a header that selects a minor variant, such as X-Feature-Version. Swagger can describe both: versioned paths and optional headers that toggle experimental behavior.
Q: Where can I learn more about API versioning patterns beyond Swagger examples?
While not Swagger‑specific, resources like the Microsoft REST API Guidelines and articles by practitioners such as Martin Fowler provide solid background on versioning strategies and trade‑offs.
Versioning isn’t about finding the “perfect” pattern; it’s about picking a strategy you can live with for years and then documenting it clearly. Swagger and OpenAPI give you the language to express that strategy. The real value comes from how you use that language in your own examples of versioning APIs with Swagger: practical examples that match your constraints, your tooling, and your consumers.
Related Topics
The best examples of webhook documentation in Swagger – 3 core examples and more
Practical examples of adding response examples in Swagger documentation
Real‑world examples of versioning APIs with Swagger: practical examples that actually work
Practical examples of integrating Swagger with Spring Boot applications
Explore More Using Swagger for API Definition
Discover more examples and insights in this category.
View All Using Swagger for API Definition