Introduction
A REST API rarely needs the create and edit methods that serve HTML forms. Route::apiResource is a variant of Route::resource that drops those methods and gives you a clean, five-route RESTful API.
Key Concepts
Route::apiResource: Registers onlyindex,store,show,update, anddestroy.--apiflag: Generates a controller with just those five methods.Route::apiResources([...]): Register multiple API resources in a single array.middlewareFor(): Apply middleware to specific methods of a resource (Laravel 13 API).
Real World Context
Every mobile app and SPA backend is shaped like this: five endpoints per resource, responding with JSON. Using apiResource keeps your routes file short and consistent so developers can navigate a new service in seconds.
Deep Dive
Generating the Controller
bashphp artisan make:controller Api/PostController --api --model=Post
The --api flag skips the form methods; --model=Post pre-fills the parameter types for route model binding.
Registering the Routes
php// routes/api.php use App\Http\Controllers\Api\PostController; Route::apiResource('posts', PostController::class); // Multiple at once Route::apiResources([ 'posts' => PostController::class, 'comments' => CommentController::class, ]);
This generates five routes:
| Verb | URI | Action | Name |
|---|---|---|---|
| GET | /api/posts | index | posts.index |
| POST | /api/posts | store | posts.store |
| GET | /api/posts/{post} | show | posts.show |
| PUT/PATCH | /api/posts/{post} | update | posts.update |
| DELETE | /api/posts/{post} | destroy | posts.destroy |
Protecting Specific Methods
Laravel 13 introduced middlewareFor() so you can attach middleware to just the methods that need it:
phpRoute::apiResource('posts', PostController::class) ->middlewareFor(['store', 'update', 'destroy'], 'auth:sanctum');
index and show remain public; mutations require a valid token.
A Real Controller
phpnamespace App\Http\Controllers\Api; use App\Http\Controllers\Controller; use App\Http\Requests\StorePostRequest; use App\Http\Resources\PostResource; use App\Models\Post; class PostController extends Controller { public function index() { return PostResource::collection(Post::latest()->paginate(20)); } public function store(StorePostRequest $request) { $post = $request->user()->posts()->create($request->validated()); return new PostResource($post); } public function show(Post $post) { return new PostResource($post); } public function destroy(Post $post) { $post->delete(); return response()->noContent(); // HTTP 204 } }
PostResource is an Eloquent API Resource that shapes the JSON response. response()->noContent() returns a 204 with an empty body — the correct response for a successful DELETE.
Common Pitfalls
- Using
Route::resourcefor an API — The extracreateandeditroutes clutter your route list and advertise HTML-only endpoints that do not exist. - Returning models directly — It works, but it exposes every field. Wrap responses in API Resources so the shape is explicit and stable.
Best Practices
- Name your controllers under
App\Http\Controllers\Api— Keeps web and API controllers separate so they can evolve independently. - Use
middlewareForfor mixed public/private APIs — It is cleaner than splitting the resource into individual routes.
Summary
Route::apiResourceregisters 5 RESTful routes (nocreate/edit).- Use
--apiwithmake:controllerto generate matching controller methods. - Laravel 13's
middlewareFor()targets specific resource actions. - Wrap responses in API Resources and return 204 No Content from destructive actions.
Code Examples
// routes/api.php
use App\Http\Controllers\Api\PostController;
Route::apiResource('posts', PostController::class)
->middlewareFor(['store', 'update', 'destroy'], 'auth:sanctum');
// This yields:
// GET /api/posts (public)
// GET /api/posts/{post} (public)
// POST /api/posts (auth:sanctum)
// PUT /api/posts/{post} (auth:sanctum)
// DELETE /api/posts/{post} (auth:sanctum)