For scaling Laravel applications, it gets difficult to adjust API functionalities to match modern web development requirements. You can configure and make changes to your APIs to adjust to the new features, bug fixes or changes in business logic. However, you can’t risk breaking existing client applications that depend on older versions.
API versioning in Laravel helps maintain backward compatibility while introducing changes safely. With help of skilled Laravel developers you can set up different versions of API to coexist.
Laravel provides flexible ways to manage API versioning effectively, such as:
- URL-based versioning (e.g., /api/v1/)
- Namespace-based controller separation
- Header-based versioning (for advanced use cases)
- Shared logic services to avoid code duplication
Let’s break down how to manage API versioning in Laravel with clear examples and simple explanations.
Why is API Versioning Important?
You don’t want a new change to break existing apps that rely on your API.
Your API will grow, and you’ll need to add or modify features.
It provides a clean way to transition users from old to new functionality.
Strategies for API Versioning in Laravel
URI-based Versioning (Recommended and Common)
This is the most common and easiest way to manage versioning.
Example:
PHP:
// routes/api.php
Route::prefix('v1')->group(function () { Route::get('/users', [\App\Http\Controllers\Api\V1\UserController::class, 'index']);
});
Route::prefix('v2')->group(function () { Route::get('/users', [\App\Http\Controllers\Api\V2\UserController::class, 'index']);
});
Your clients can call /api/v1/users or /api/v2/users based on the version they want.
Inside app/Http/Controllers/Api/V1/UserController.php and V2/UserController.php, you can have different logic.
Controller Namespace Separation
Organize your code in separate folders to make maintenance easier.
Folder structure:
app/
└── Http/
└── Controllers/
└── Api/
├── V1/
│ └── UserController.php
└── V2/
└── UserController.php
Each controller handles logic specific to that API version.
Accept Header Versioning (Advanced Option)
You can version your API using request headers instead of the URL.
Client sends this header:
Accept: application/vnd.myapp.v1+json
You’ll need middleware to parse the header and route accordingly (less common but used in enterprise APIs).
Maintaining Shared Business Logic
Even though the API controllers are split, don’t duplicate logic. Extract shared business logic into services, repositories, or actions.
Example:
PHP:
class UserService { public function getAllUsers() { return User::all(); }
}
Then in V1 and V2 controllers, just call the same service.
Deprecating Old Versions Gracefully
Notify clients about deprecated APIs and provide a timeline for retirement.
Example: In V1/UserController, return a warning:
PHP:
return response()->json([ 'data' => $users, 'message' => 'v1 is deprecated, please upgrade to v2 by Dec 2025'
]);
Real-World Example
Let’s say your /api/v1/users endpoint returns:
JSON:
{ "id": 1, "name": "John Doe"
}
But in v2, you want to return:
JSON:
{ "id": 1, "full_name": "John Doe", "email": "john@example.com"
}
Just create a new V2/UserController with updated logic, without affecting your existing v1 clients.
Summary
Versioning Strategy | Description |
URL Prefixing (/v1) | Easiest and most common method |
Header Versioning | Cleaner URLs, but requires custom middleware |
Namespace Separation | Organize code by version folders |
Shared Business Logic | Avoid duplicating code using services |
Graceful Deprecation | Inform clients of older versions being phased out |