How to Build RESTful API in Laravel 11 with CRUD Example

Building RESTful APIs is one of the core requir whether you are working with frontend frameworks, mobile applications, or third-party integrations. Laravel 11 makes API development easier as it provides a clean structure, powerful routing, built-in validation, and elegant database handling through Eloquent ORM.

In this article we will cover everything about RESTful, its definition, and how to set it up with an example.

Build RESTful API CRUD in Laravel 11 Best Practices

What is RESTful API?

RESTful API stands for Representational State Transfer–based Application Programming Interface. The RESTful API treats data as resources, uses resource-based URLs, follows stateless communication, and performs actions using standard HTTP methods like GET, POST, PUT, PATCH, and DELETE.


Steps to Build RESTful API CRUD in Laravel 11

Now we will go step by step to build a complete RESTful API CRUD application in Laravel 11.

Step 1: Setting Up Laravel

Before getting started, first we create a Laravel project by composer using the below command.

composer create-project --prefer-dist laravel/laravel rest-api-crud

Step 2: Creating an API file inside the routes folder

Laravel 11 doesn't have api.php in the routes folder. In the previous version of Laravel, the api.php is there, so now we will create the api.php file by using the below command.

php artisan install:api

This command will create routes/api.php. In this file we will define our API routes.

Step 3: Configure the MySQL database.

By default, Laravel 11 uses SQLite, but if you want to use MySQL, you can set up the database in the configuration .env file, which is located in the root directory. Open the .env file and set up your database credentials.

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=your_database_name
DB_USERNAME=your_username
DB_PASSWORD=your_password

Step 4: Create the Product Model with Migration

In this blog we will do CRUD for product. So we will create a modal and migration by using the below command.

php artisan make:model Product -m

It will create two files.

  1. app/Models/Product.php – Product model
  2. database/migrations/2026_01_15_XXXXXX_create_products_table.php – Products table migration

We will set up the 2026_01_15_XXXXXX_create_products_table.php migration file as shown below:

public function up(): void {
    Schema::create('products', function (Blueprint $table) {
        $table->id();
        $table->string('name');
        $table->string('details');
        $table->timestamps();
    });
}

Run the migration, and it will create a products table in the database.

php artisan migrate

Open the Product.php file and add the fields to the$fillable property. Without this, Laravel will not allow mass assignment, and the data will not be saved.

<?php

namespace AppModels;

use IlluminateDatabaseEloquentFactoriesHasFactory;
use IlluminateDatabaseEloquentModel;

class Product extends Model
{
    use HasFactory;

    protected $fillable = [
        'name',
        'details',
    ];
}

Step 6: Create the ProductController

We will write our all CRUD related logic in the controller. Run the below command for creating controller

php artisan make:controller ProductController

This command will create app/Http/Controllers/ProductController.php

<?php

namespace AppHttpControllers;

use AppModelsProduct;
use IlluminateHttpRequest;
use IlluminateHttpJsonResponse;

class ProductController extends Controller
{
    /**
     * Display a listing of products.
     */
    public function index(): JsonResponse
    {
        $products = Product::all();

        return response()->json([
            'status' => true,
            'data' => $products
        ], 200);
    }

    /**
     * Store a newly created product.
     */
    public function store(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'name' => 'required|string|max:255',
            'details' => 'required|string',
        ]);

        $product = Product::create($validated);

        return response()->json([
            'status' => true,
            'message' => 'Product created successfully',
            'data' => $product
        ], 201);
    }

    /**
     * Display the specified product.
     */
    public function show(int $id): JsonResponse
    {
        $product = Product::findOrFail($id);

        return response()->json([
            'status' => true,
            'data' => $product
        ], 200);
    }

    /**
     * Update the specified product.
     */
    public function update(Request $request, int $id): JsonResponse
    {
        $product = Product::findOrFail($id);

        $validated = $request->validate([
            'name' => 'sometimes|required|string|max:255',
            'details' => 'sometimes|required|string',
        ]);

        $product->update($validated);

        return response()->json([
            'status' => true,
            'message' => 'Product updated successfully',
            'data' => $product
        ], 200);
    }

    /**
     * Remove the specified product.
     */
    public function destroy(int $id): JsonResponse
    {
        $product = Product::findOrFail($id);
        $product->delete();

        return response()->json([
            'status' => true,
            'message' => 'Product deleted successfully'
        ], 200);
    }
}

What this controller covers

  • index() → Get all products
  • store() → Create a product
  • show() → Get a single product
  • update() → Update a product
  • destroy() → Delete a product
  • Proper HTTP status codes
  • Validation
  • Clean JSON responses

Step 6: Define Routes in api.php

Now we will define our API routes in the routes/api.php file as shown below:

use AppHttpControllersProductController;
use IlluminateSupportFacadesRoute;

/*
|--------------------------------------------------------------------------
| Product API Routes
|--------------------------------------------------------------------------
*/

// Get all products
Route::get('/products', [ProductController::class, 'index']);

// Get a single product by ID
Route::get('/products/{id}', [ProductController::class, 'show']);

// Create a new product
Route::post('/products', [ProductController::class, 'store']);

// Update an existing product
Route::put('/products/{id}', [ProductController::class, 'update']);
Route::patch('/products/{id}', [ProductController::class, 'update']);

// Delete a product
Route::delete('/products/{id}', [ProductController::class, 'destroy']);

Step 7: Test Your RESTful API

Now that we have completed the setup of the controller and routes, it’s important to test your API endpoints to make sure they work correctly. You can use tools like Postman, API Tester Tool or even curl from the terminal.

1. Test GET All Products

GET http://your-app.test/api/products

It should return a JSON response with all products.

2. Test GET Single Product

GET http://your-app.test/api/products/{id}

Replace {id} with the product ID you want to fetch.

3. Test POST (Create Product)

POST http://your-app.test/api/products
Body (JSON):
{
    "name": "Product Name",
    "details": "Product details here"
}

4. Test PUT / PATCH (Update Product)

PUT http://your-app.test/api/products/{id}
Body (JSON):
{
    "name": "Updated Name",
    "details": "Updated details"
}

5. Test DELETE (Remove Product)

DELETE http://your-app.test/api/products/{id}

Conclusion

By following these steps, you’ve built a RESTful API CRUD application in Laravel 11 using best practices like the Repository pattern, request validation, and resource classes. This ensures your API is scalable, maintainable, and secure.

Implement these practices in your projects and take your Laravel API development to the next level.


Frequently Asked Questions

What is full form of RESTful API ?+
What is the Repository pattern in Laravel?+
How do I validate requests in Laravel 11 APIs?+
What is a Resource class in Laravel?+
How do I bind a repository interface to its implementation?+