# Versioning Strategies — API Design and Versioning

Source: https://www.geekswithgeeks.com/en/api-design/ver-strategies

> Compare URL, header, media-type and date-based versioning and pick one deliberately.

## Four common approaches

**URI versioning** (`/v1/orders`, `/v2/orders`) is the most visible and easiest to route, cache, test in a browser and document; the trade-off is that a "version" applies to the whole API. **Header versioning** (`API-Version: 2` or a custom header) keeps URLs clean but is less visible. **Media-type versioning** (`Accept: application/vnd.example.v2+json`) fits REST purists using content negotiation. **Date-based versioning** (used by some payment APIs): each account is pinned to the API date at which it started (`API-Version: 2026-01-10`), and breaking changes ship as new dated versions that clients opt into when ready. Whatever you pick, version **sparingly**: prefer additive changes, bump the **major** version only for breaking ones, and keep the number of supported versions small.

## Comparing the approaches

Choose by your audience and tooling, then document the choice.

```text
Style          Example                                  Pros                         Cons
URI            GET /v2/orders                           visible, easy routing/cache  whole-API versions
Header         API-Version: 2                           clean URLs                   hidden, harder to test
Media type     Accept: application/vnd.x.v2+json        content-negotiation purity   tooling/caching friction
Date-based     API-Version: 2026-01-10                  fine-grained, gradual opt-in complex to implement
```

## Picking a date-based version, run

I ran this plain-Python example. Given a list of released versions, a request for `2025-12-31` gets the latest version released on or before that date (`2025-06-15`); `2026-10-01` gets `2026-01-10`; a date before the first release gets `None`.

```python
import hmac, hashlib, json, time, bisect

VERSIONS = ["2024-03-01", "2025-06-15", "2026-01-10"]
def pick(requested):
    i = bisect.bisect_right(VERSIONS, requested)
    return VERSIONS[i - 1] if i else None
print(pick("2025-12-31"), pick("2026-10-01"), pick("2023-01-01"))

```

Output:

```
2025-06-15 2026-01-10 None
```

**Quiz:** What is a main advantage of URI versioning?

- [ ] It needs no documentation
- [ ] It hides the version completely
- [x] The version is visible and easy to route, cache and test
- [ ] It is invisible to proxies

*Answer:* The version is visible and easy to route, cache and test. Putting the version in the path makes it explicit in logs, links and tools.
