API Versioning Strategies Compared: URL, Header, and Query Parameter
Every API handles versioning differently. Here's a practical comparison of URL path, header-based, and query parameter versioning — with real examples and monitoring implications.
Torstein Skulbru
How an API handles versioning directly affects how breaking changes reach your code. Understanding the versioning strategy of each API you depend on helps you anticipate risks and monitor effectively.
The Three Main Strategies
1. URL Path Versioning
The version number is part of the URL:
GET https://api.example.com/v1/users
GET https://api.example.com/v2/users
Real-world examples: Twilio (/2010-04-01/), Slack (/api/), most REST APIs
Pros:
- Extremely clear which version you're using
- Easy to test both versions simultaneously
- Simple to route in API gateways and proxies
- Caching works naturally since URLs are different
Cons:
- Requires URL changes for every version bump
- Can lead to URL proliferation
- Major version bumps require updating every API call
- SDKs typically need major version releases to change base URLs
Monitoring implication: Breaking changes only affect you when you explicitly upgrade your base URL. But you need to monitor for deprecation notices about your current version.
2. Header-Based Versioning
The version is specified in a request header:
GET https://api.example.com/users
Stripe-Version: 2024-11-20
Accept: application/vnd.github.v3+json
Real-world examples: Stripe (Stripe-Version header), GitHub (Accept header with media type)
Pros:
- Clean URLs that don't change between versions
- Fine-grained control — can version per-request if needed
- Account-level pinning means you don't break until you opt in
Cons:
- Less visible — you can't tell the version from the URL alone
- SDK configuration determines your version, which can change silently on upgrade
- Webhook payloads may not respect your pinned version — this is a common source of breaking changes with Stripe
Monitoring implication: The most dangerous pattern. You might be on an old version and not realize a new version has changed field names or payload structures. Automated changelog monitoring is especially valuable here.
3. Query Parameter Versioning
The version is passed as a query parameter:
GET https://api.example.com/users?api-version=2024-01-01
GET https://maps.googleapis.com/maps/api/geocode/json?key=...&v=3.56
Real-world examples: Azure (api-version parameter), some Google APIs
Pros:
- Easy to switch versions without changing URL structure or headers
- Can be tested directly in a browser
- Simple to implement on the provider side
Cons:
- Clutters the URL with non-resource parameters
- Can conflict with caching if the parameter is ignored by CDNs
- Easy to forget — what happens when you don't specify a version?
Monitoring implication: Similar to URL versioning — you control when you upgrade. But default-version behavior (when parameter is omitted) can change without warning.
How Major APIs Handle Versioning
| API | Strategy | Version Format | Breaking Change Risk |
|---|---|---|---|
| Stripe | Header | Dated (2024-11-20) | Medium — webhooks can mismatch |
| GitHub | Header + URL | v3, v4 (GraphQL) | Low — versions are stable |
| Twilio | URL | Dated (2010-04-01) | Low — versions are long-lived |
| AWS | URL + Header | Service-specific | Medium — services deprecate independently |
| Vercel | URL | Numeric (v1, v2) | Low — clear migration paths |
| Cloudflare | URL | Numeric (v4) | Low — stable API |
| Supabase | URL | v1 | Medium — auth changes |
Stripe's Versioning: A Case Study
Stripe deserves special attention because its versioning model is both sophisticated and potentially surprising.
When you create a Stripe account, it pins to the latest API version. All API calls from your server use this pinned version by default. So far, so good.
The complexity arises with webhooks. When Stripe sends a webhook event, it uses the API version that was active when the webhook endpoint was created — not necessarily your account's pinned version. If you update your account version but don't recreate your webhook endpoints, you can receive events in a different format than your API calls return.
This is exactly the kind of subtle breaking change that automated monitoring catches. When Stripe publishes a new API version that renames fields in the payment_intent.succeeded event, you need to know — even if you're not planning to upgrade yet.
What This Means for Monitoring
Different versioning strategies require different monitoring approaches:
For URL-versioned APIs: Monitor for deprecation notices about your current version. When a new major version launches, you'll need to migrate eventually.
For header-versioned APIs: Monitor aggressively. Changes can affect you through SDK upgrades, webhook payload mismatches, or account version changes. This is where automated AI classification adds the most value.
For query parameter APIs: Monitor for default version changes and parameter deprecations.
Automated Monitoring Across All Strategies
Regardless of the versioning strategy, the changelog is your early warning system. Every breaking change, every deprecation, every sunset date appears in the changelog first.
APIDrift monitors changelogs across all these versioning strategies, classifying each change by type and severity. Whether it's a new Stripe API version, a GitHub endpoint deprecation, or an AWS service sunset, you'll see it in your digest before it affects your code.
Start monitoring your API dependencies — free plan, no credit card required.