Card 04/ 09
Path vs Header vs Media Type vs Query Versioning
Four places to put a version, each trading visibility against how cleanly a URL names a resource.
When a change must break, the API publishes a new version beside the old one, and each request has to say which version it wants. There are four common places for that: the path, a header, the media type and a query parameter. All four work; they differ in how visible the version is, how caches and routers handle it, and whether a URL still names one resource.
| Strategy | Example request | Strengths | Costs |
|---|---|---|---|
| Path | GET /v2/orders/1001 | Visible in every link and log; simple to route and cache | Every URL changes between versions; the same order has two URLs |
| Header | GET /orders/1001 with Api-Version: 2 | URLs stay stable | Invisible in a link; caches need Vary on the header; easy to forget in a browser |
| Media type | Accept: application/vnd.example.v2+json | Versions the representation, which is what changed | Clients must set a custom content type; awkward to try by hand |
| Query parameter | GET /orders/1001?version=2 | Visible and easy to try | Easy to leave off by accident; mixes the version with filters |
Which to choose. Path versioning is the most common for public APIs, because it is the easiest for clients to see and use, and its costs fall mainly on people who care about URLs as stable names. Header and media type versioning suit teams that want one URL per resource and clients able to set headers.
Dated versions are a variant. Stripe sends a date such as Stripe-Version: 2024-06-20 in a header, and pins each account to the version it started on. GitHub's REST API does the same with X-GitHub-Api-Version. A date says when the behaviour was defined, and lets an API make many small breaking changes without a major number for each.
What every strategy needs. A default for requests that send no version, which should be the oldest supported or the version pinned to the client rather than the newest, so a client that forgot is not broken by the next release. And a version only for breaking changes; additive changes go into the current version.
So choose one place, use it everywhere, and create a version only when something must break.
← → move through sections and cards