Modern QA2026Versioning Strategies — tiles
Log inJoin
59 / 65 · 14 API Testing Fundamentals · API Versioning← prev⊞ allnext →☰ Read as one page

8.2Versioning Strategies

Strategy Example Pros Cons
URL path /v1/users, /v2/users Clear, easy to route URL pollution, hard to remove old versions
Header Accept: application/vnd.api+json; version=2 Clean URLs Harder to test manually, easy to miss
Query param /users?version=2 Simple URL pollution, caching complications
Content negotiation Accept: application/vnd.company.v2+json RESTful Complex to implement and test

URL Path Versioning (Most Common)

def test_v1_users_endpoint(api):
    r = api.get("/v1/users")
    assert r.status_code == 200
    user = r.json()["items"][0]
    assert "name" in user  # v1 returns "name"

def test_v2_users_endpoint(api):
    r = api.get("/v2/users")
    assert r.status_code == 200
    user = r.json()["items"][0]
    assert "first_name" in user  # v2 splits into first/last
    assert "last_name" in user

Header-Based Versioning

def test_header_versioning(api, base_url):
    # Default version (no header)
    r = api.get("/users")
    assert r.status_code == 200
    default_fields = set(r.json()["items"][0].keys())

    # Explicit v2
    r = api.get("/users", headers={"API-Version": "2"})
    assert r.status_code == 200
    v2_fields = set(r.json()["items"][0].keys())

    # v2 should have new fields
    assert "first_name" in v2_fields
    assert "last_name" in v2_fields

def test_missing_version_header_uses_default(api):
    """When no version header is sent, the API should use the default version."""
    r = api.get("/users")
    assert r.status_code == 200
    # Verify it returns the default version's response format