Back to Tutorials
APIsIntermediate

Building REST APIs with Laravel

A comprehensive guide to building secure and scalable RESTful APIs using the Laravel framework.

James Wilson
January 4, 2026
60 min read

Building REST APIs with Laravel

Learn how to build production-ready RESTful APIs using Laravel's powerful features and best practices.

Setting Up Your API Project

Install Laravel

bash
1composer create-project laravel/laravel api-project
2cd api-project
3php artisan serve

Configure Database

Edit your .env file:

env
1DB_CONNECTION=mysql
2DB_HOST=127.0.0.1
3DB_PORT=3306
4DB_DATABASE=api_db
5DB_USERNAME=root
6DB_PASSWORD=

Creating API Resources

Generate Model and Migration

bash
1php artisan make:model Post -m
2php artisan make:controller Api/PostController --api
3php artisan make:resource PostResource

Define Migration

php
1public function up(): void
2{
3    Schema::create('posts', function (Blueprint $table) {
4        $table->id();
5        $table->string('title');
6        $table->text('content');
7        $table->foreignId('user_id')->constrained()->onDelete('cascade');
8        $table->boolean('published')->default(false);
9        $table->timestamps();
10    });
11}

API Controller

php
1namespace App\Http\Controllers\Api;
2
3use App\Http\Controllers\Controller;
4use App\Http\Resources\PostResource;
5use App\Models\Post;
6use Illuminate\Http\Request;
7
8class PostController extends Controller
9{
10    public function index()
11    {
12        $posts = Post::with('user')->paginate(15);
13        return PostResource::collection($posts);
14    }
15    
16    public function store(Request $request)
17    {
18        $validated = $request->validate([
19            'title' => 'required|max:255',
20            'content' => 'required',
21            'published' => 'boolean'
22        ]);
23        
24        $post = $request->user()->posts()->create($validated);
25        
26        return new PostResource($post);
27    }
28    
29    public function show(Post $post)
30    {
31        return new PostResource($post->load('user'));
32    }
33    
34    public function update(Request $request, Post $post)
35    {
36        $this->authorize('update', $post);
37        
38        $validated = $request->validate([
39            'title' => 'sometimes|required|max:255',
40            'content' => 'sometimes|required',
41            'published' => 'boolean'
42        ]);
43        
44        $post->update($validated);
45        
46        return new PostResource($post);
47    }
48    
49    public function destroy(Post $post)
50    {
51        $this->authorize('delete', $post);
52        $post->delete();
53        
54        return response()->json(['message' => 'Post deleted'], 200);
55    }
56}

API Resources

Transform your models into JSON:

php
1namespace App\Http\Resources;
2
3use Illuminate\Http\Resources\Json\JsonResource;
4
5class PostResource extends JsonResource
6{
7    public function toArray($request): array
8    {
9        return [
10            'id' => $this->id,
11            'title' => $this->title,
12            'content' => $this->content,
13            'published' => $this->published,
14            'author' => new UserResource($this->whenLoaded('user')),
15            'created_at' => $this->created_at->toISOString(),
16            'updated_at' => $this->updated_at->toISOString(),
17        ];
18    }
19}

Authentication with Sanctum

Install Sanctum

bash
1php artisan install:api

Login Controller

php
1public function login(Request $request)
2{
3    $request->validate([
4        'email' => 'required|email',
5        'password' => 'required'
6    ]);
7    
8    if (!Auth::attempt($request->only('email', 'password'))) {
9        return response()->json(['message' => 'Invalid credentials'], 401);
10    }
11    
12    $user = User::where('email', $request->email)->first();
13    $token = $user->createToken('api-token')->plainTextToken;
14    
15    return response()->json([
16        'user' => new UserResource($user),
17        'token' => $token
18    ]);
19}

API Routes

php
1// routes/api.php
2Route::post('/login', [AuthController::class, 'login']);
3Route::post('/register', [AuthController::class, 'register']);
4
5Route::middleware('auth:sanctum')->group(function () {
6    Route::apiResource('posts', PostController::class);
7    Route::get('/me', [UserController::class, 'me']);
8});

Rate Limiting

php
1// app/Providers/RouteServiceProvider.php
2RateLimiter::for('api', function (Request $request) {
3    return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
4});

Testing Your API

php
1public function test_can_create_post(): void
2{
3    $user = User::factory()->create();
4    
5    $response = $this->actingAs($user)->postJson('/api/posts', [
6        'title' => 'Test Post',
7        'content' => 'This is a test post',
8        'published' => true
9    ]);
10    
11    $response->assertStatus(201)
12        ->assertJsonStructure([
13            'data' => ['id', 'title', 'content', 'published']
14        ]);
15}

Conclusion

You now have a solid foundation for building RESTful APIs with Laravel. Remember to implement proper validation, authentication, and error handling in production!