Skip to main content
RESTful Principles
CHAPTER 23 Beginner

API Versioning Strategies

Updated: May 13, 2026
5 min read

# CHAPTER 23

API Versioning Strategies

1. Introduction

Once an API is live and being used by mobile apps and external companies, you cannot simply change the rules. If you rename a database column from firstname to firstName, every mobile app relying on firstname will instantly crash. In Chapter 23, we will discuss API Versioning—the practice of managing "breaking changes" gracefully so older clients keep working while new clients get the latest features.

2. Learning Objectives

By the end of this chapter, you will be able to:
  • Define what constitutes a "Breaking Change" in an API.
  • Implement URL-based versioning (e.g., /v1/, /v2/).
  • Understand Header-based versioning.
  • Explain the concept of Backward Compatibility.
  • Implement basic version routing in a PHP application.

3. Beginner-Friendly Explanation

Imagine a TV manufacturer. They release the "Model 1" remote control. Millions of people buy it. Later, they design a much better "Model 2" remote control. They don't sneak into everyone's house and destroy the Model 1 remotes. Instead, they support *both* remotes. If a customer uses Model 1, the TV responds one way. If a customer buys Model 2, the TV responds with new features.

In APIs, "Model 1" is Version 1 (v1). When we make massive changes, we don't delete v1; we create v2 and run them side-by-side until everyone upgrades.

4. Real-World Examples

  • Twitter API: Look at Twitter's endpoints: https://api.twitter.com/2/tweets. That /2/ means they are on Version 2 of their entire architectural design.
  • Stripe API: Stripe uses date-based versioning passed in the headers. You send a header like Stripe-Version: 2023-10-16, and Stripe transforms the response to match how the API worked on that specific date!

5. Detailed Code Examples

The most common and developer-friendly approach is URL Versioning. Let's adapt our PHP index.php router to handle versions.
php
123456789101112131415161718192021222324252627282930
<?php
// Get the requested URL path: /api/v1/users
$uri = parse_url($_SERVER[&#039;REQUEST_URI'], PHP_URL_PATH);
$uri = explode(&#039;/', $uri);

// $uri[1] is 'api', $uri[2] is 'v1', $uri[3] is 'users'
$version = $uri[2] ?? &#039;v1';
$resource = $uri[3] ?? null;

if ($resource === &#039;users') {
    if ($version === &#039;v1') {
        // Old Version logic
        echo json_encode([
            "id" => 5,
            "first_name" => "Jane",
            "last_name" => "Doe"
        ]);
    } elseif ($version === &#039;v2') {
        // New Version logic (combining names)
        echo json_encode([
            "id" => 5,
            "full_name" => "Jane Doe",
            "created_at" => "2023-10-01"
        ]);
    } else {
        http_response_code(404);
        echo json_encode(["error" => "Unsupported API version"]);
    }
}
?>

6. Request/Response Examples

By using URL versioning, developers can clearly see which version of the data contract they are subscribing to.

Client A Request: GET /api/v1/users/5 Response: {"firstname": "Jane", "lastname": "Doe"}

Client B Request: GET /api/v2/users/5 Response: {"full_name": "Jane Doe"}

7. HTTP Examples

Another approach is Header Versioning (also called Content Negotiation Versioning). This keeps URLs perfectly clean but makes testing slightly harder.
http
123
GET /api/users/5 HTTP/1.1
Host: api.example.com
Accept: application/vnd.myapi.v2+json

*Here, the client specifies they want version 2 inside the Accept header instead of the URL.*

8. JSON Examples

When deprecating an old version, it is good practice to include warning headers or metadata in the JSON response so developers know they need to upgrade soon.
json
12345678
{
  "meta": {
    "warning": "API v1 is deprecated and will be shut down on Dec 31, 2026. Please migrate to v2."
  },
  "data": {
    "first_name": "Jane"
  }
}

9. Best Practices

  • Version from Day 1: Always put /v1/ in your base URL from the very beginning (https://api.yourapp.com/v1/). If you don't, adding /v2/ later creates a messy, inconsistent architecture.
  • Maintain Backward Compatibility: Do not increment to v2 for minor changes. Adding a *new* field to a JSON response is backward compatible (old apps just ignore the new field). Removing or renaming a field is a *breaking change* and requires a new version.
  • Deprecation Schedules: Never turn off v1 overnight. Give developers 6 to 12 months' notice via email and API headers before turning off an old version.

10. Common Mistakes

  • Creating a v2 for bug fixes: Versions should only change for structural data changes. Bug fixes and performance improvements should be applied directly to v1.
  • Duplicating all code: When making v2, don't copy/paste your entire codebase. v1 and v2 should share the same database and core models; only the *Controllers* (the formatting of the JSON) should differ.

11. Mini Exercises

  1. 1. Determine if this is a breaking change: You have an endpoint GET /products. You decide to add a new "stock_count": 50 field to the JSON response.
*(Answer: No, this is non-breaking. Old clients will just ignore the new key. You do NOT need a v2 for this.)*
  1. 2. Determine if this is a breaking change: You decide to change the "price" field from a string "$10.00" to an integer 1000 (cents).
*(Answer: Yes! Any mobile app trying to display that string will crash or display incorrectly. You MUST create v2 for this).*

12. Coding Challenges

Challenge 1: Write a PHP if/else block that checks if the incoming header Accept-Version is set to 3. If it is, output {"format": "new"}, otherwise output {"format": "old"}.

13. MCQs with Answers

Question 1

What is the most common and visible method for versioning a REST API?

Question 2

Which of the following is considered a "Breaking Change"?

Question 3

Why should you include /v1/ in your URLs from the very start of a project?

14. Interview Questions

  • Q: Explain the difference between URL Versioning and Header Versioning. Which do you prefer and why?
  • Q: Give three examples of "Breaking Changes" that would require bumping the API version.
  • Q: How do you handle the codebase when supporting both v1 and v2 simultaneously without duplicating massive amounts of code?

15. FAQs

Q: How many versions should I maintain at once? A: Try to maintain no more than two (the current version and the immediate legacy version). Maintaining v1, v2, v3, and v4 simultaneously becomes an administrative and testing nightmare.

16. Summary

In Chapter 23, we learned how to future-proof our APIs through Versioning. We defined what breaking changes are (renaming, deleting, or changing data types) and learned that adding new fields is perfectly safe. We explored URL versioning (/v1/), header versioning, and how to structure our PHP router to serve different JSON formats based on the requested version, ensuring mobile apps never crash unexpectedly.

17. Next Chapter Recommendation

Our API is architecturally sound and future-proofed. Now, we must lock it down. Proceed to Chapter 24: REST API Security Best Practices to learn about CORS, XSS, HTTPS, and defending against the most common web attacks.

Finish this Chapter

Save your progress on your learning path and prepare for coding interview challenges.

Discussion

Join the discussion

Log in or create a free account to participate.

Sort: ·