Membangun REST API menggunakan Laravel 11 & Sanctum
Laravel has long been the go-to framework for PHP developers who need to ship production-quality APIs fast. With Laravel 11 and the built-in Sanctum package, setting up stateless token authentication is smoother than ever. In this guide we will go from a fresh project to a fully working, protected REST API.
Prerequisites
- PHP 8.2+ and Composer installed
- A database (MySQL 8 or PostgreSQL 15 recommended)
- An HTTP client such as Postman or Bruno
1. Create the Project
Spin up a fresh Laravel 11 project and install Sanctum:
composer create-project laravel/laravel my-api
cd my-api
composer require laravel/sanctum
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
php artisan migrate
2. Configure the Database
Open .env and point it at your database:
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=my_api
DB_USERNAME=root
DB_PASSWORD=secret
3. Create the User Model & Controller
Generate an API controller for authentication:
php artisan make:controller Api/AuthController
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Validation\ValidationException;
class AuthController extends Controller
{
public function register(Request $request)
{
$data = $request->validate([
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'email', 'unique:users'],
'password' => ['required', 'min:8', 'confirmed'],
]);
$user = User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
]);
$token = $user->createToken('api-token')->plainTextToken;
return response()->json(['token' => $token], 201);
}
public function login(Request $request)
{
$data = $request->validate([
'email' => ['required', 'email'],
'password' => ['required'],
]);
$user = User::where('email', $data['email'])->first();
if (!$user || !Hash::check($data['password'], $user->password)) {
throw ValidationException::withMessages([
'email' => ['The provided credentials are incorrect.'],
]);
}
$token = $user->createToken('api-token')->plainTextToken;
return response()->json(['token' => $token]);
}
public function logout(Request $request)
{
$request->user()->currentAccessToken()->delete();
return response()->json(['message' => 'Logged out successfully.']);
}
}
4. Define the Routes
In routes/api.php, register your endpoints:
use App\Http\Controllers\Api\AuthController;
Route::prefix('auth')->group(function () {
Route::post('register', [AuthController::class, 'register']);
Route::post('login', [AuthController::class, 'login']);
Route::middleware('auth:sanctum')->group(function () {
Route::post('logout', [AuthController::class, 'logout']);
Route::get('me', fn ($req) => response()->json($req->user()));
});
});
5. Test with Postman
Start the dev server and hit your first endpoint:
php artisan serve
Send a POST request to http://localhost:8000/api/auth/register with a JSON body:
{
"name": "Didik Prabowo",
"email": "didik@example.com",
"password": "password",
"password_confirmation": "password"
}
You will receive a Bearer token that you can attach to all subsequent authenticated requests. The same token can be verified on GET /api/auth/me.
Wrapping Up
You now have a secure, token-based REST API ready for production. From here, consider adding rate limiting via throttle middleware, response resources with php artisan make:resource, and proper API versioning under a v1 prefix.
