API Routing

Installing API Routing and Versioning Endpoints

A new application has no routes/api.php. Run php artisan install:api to add it. On 13.33 the command installs Sanctum 4.3.3 2,988 , publishes config/sanctum.php, migrates the personal_access_tokens table, adds api: to withRouting(), and asks you to add HasApiTokens to User. Its routes get the /api prefix and the stateless api group (Global and Group Middleware). Put the version in the URL and freeze it; a breaking change goes into v2, beside v1:

routes/api.php: the public catalog in two versionsPHP
Route::prefix('v1')->name('v1.')->group(function () {
    Route::get('/products', fn () => new ProductCollection(
        Product::with('category')->orderBy('id')->paginate(2)))->name('products.index');
    Route::get('/products/{product}', fn (Product $product) =>
        new ProductResource($product->load('category')))->name('products.show');
    // ... tokens and orders, Section 5.20.5
});
Route::prefix('v2')->group(function () {
    Route::get('/products/{product}', fn (Product $product) => new V2\ProductResource($product));
});

Larger APIs move the closures into Api\V1 controllers (Resource Controllers). The api group has no rate limit until $middleware->throttleApi() in bootstrap/app.php adds throttle:api. The bookshop's limiter, Limit::perMinute(60)->by($request->user()?->id ?: $request->ip()), is registered in AppServiceProvider exactly as in Rate Limiting Routes:

Output of 196
$ curl -si $B/api/v1/products/2 | grep -E '^(HTTP|X-RateLimit|Retry-After)|message'
HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
Retry-After: 59

The first call carried X-RateLimit-Remaining: 59; the 61st in the minute got the 429.