Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Laravel: Sanctum, Resources, and API Versioning

Laravel’s default approach is more manual than API Platform’s, and that’s often the point: routes, controllers, and response shapes stay explicit and easy to reason about, at the cost of writing a bit more per endpoint.

Sanctum handles authentication for both SPA/mobile clients (session-based) and third-party API consumers (token-based), from one package.

composer require laravel/sanctum
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
php artisan migrate
// issuing a token
$token = $user->createToken('mobile-app')->plainTextToken;

// protecting a route
Route::middleware('auth:sanctum')->get('/api/user', fn (Request $r) => $r->user());

API Resources shape a model into a consistent JSON response, decoupling your database columns from your API’s public contract:

class ProductResource extends JsonResource
{
    public function toArray(Request $request): array
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'price_usd' => number_format($this->price, 2),
        ];
    }
}

// in a controller
return ProductResource::collection(Product::paginate());

Versioning is typically just route prefixing, kept deliberately simple:

Route::prefix('v1')->group(base_path('routes/api_v1.php'));
Route::prefix('v2')->group(base_path('routes/api_v2.php'));

When to reach for this

The default choice for a Laravel project exposing an API alongside a web app, or a small-to-medium standalone API where explicit control over each response shape matters more than automatic generation.

When it’s the wrong fit

A large, rapidly evolving data model where writing a Resource class by hand for every model becomes real maintenance overhead. That’s the case API Platform is built for.

Under the hood: Sanctum’s API tokens are stored hashed, like passwords, but with PHP’s hash() function rather than password_hash(): tokens are high-entropy random strings rather than user-chosen passwords, so a fast hash is an appropriate and sufficient defense here.