Laravel API Development
Agent Workflow (MANDATORY)
Before ANY implementation, use TeamCreate to spawn 3 agents:
- fuse-ai-pilot:explore-codebase - Analyze existing API patterns
- fuse-ai-pilot:research-expert - Verify Laravel API docs via Context7
- mcp__context7__query-docs - Check API Resources and Sanctum patterns
After implementation, run fuse-ai-pilot:sniper for validation.
Overview
Build RESTful APIs with Laravel using API Resources for response transformation and Sanctum for authentication.
| Component |
Purpose |
| Controllers |
Handle requests, delegate to services |
| Form Requests |
Validate input, authorize actions |
| API Resources |
Transform models to JSON |
| Middleware |
Auth, rate limiting, CORS |
| Routes |
Versioned endpoints with groups |
| Pagination |
Offset/cursor pagination |
| HTTP Client |
Consume external APIs |
Critical Rules
- Always use API Resources - Never return Eloquent models directly
- Versioned routes - Prefix with
/v1/, /v2/
- Validate all input - Use Form Requests, not inline validation
- Rate limiting - Configure per-route limits
- Consistent responses - Same structure, proper status codes
- Use services - Keep controllers thin
- Eager load - Prevent N+1 with
with() before pagination
Reference Guide
Core Concepts
| Topic |
Reference |
When to consult |
| Routing |
routing.md |
Defining versioned API routes |
| Controllers |
controllers.md |
Controller patterns, resource methods |
| Middleware |
middleware.md |
Route protection, request filtering |
| Validation |
validation.md |
Form Requests, validation rules |
Request/Response
| Topic |
Reference |
When to consult |
| Requests |
requests.md |
Accessing input, files, headers |
| Responses |
responses.md |
API Resources, status codes |
| Pagination |
pagination.md |
Offset/cursor pagination |
Advanced
Templates (Code Examples)
Controllers & Routes
Validation & Resources
External APIs
Quick Reference
Resource Response
return PostResource::collection($posts);
return PostResource::make($post);
Status Codes
return PostResource::make($post)->response()->setStatusCode(201);
return response()->json(null, 204);
Form Request
public function store(StorePostRequest $request): JsonResponse
{
$post = $this->service->create($request->validated());
return PostResource::make($post)->response()->setStatusCode(201);
}
Rate Limiting
Route::middleware('throttle:60,1')->group(fn () => ...);
Versioned Routes
Route::prefix('v1')->group(function () {
Route::apiResource('posts', PostController::class);
});
Pagination
return PostResource::collection(Post::paginate(15));
Feature Matrix
| Feature |
Status |
Reference |
| RESTful Controllers |
✅ |
controllers.md |
| API Resources |
✅ |
responses.md |
| Form Request Validation |
✅ |
validation.md |
| Route Versioning |
✅ |
routing.md |
| Route Model Binding |
✅ |
routing.md |
| Middleware |
✅ |
middleware.md |
| Rate Limiting |
✅ |
rate-limiting.md |
| Pagination |
✅ |
pagination.md |
| Cursor Pagination |
✅ |
pagination.md |
| HTTP Client |
✅ |
http-client.md |
| Signed URLs |
✅ |
urls.md |
| JSON Responses |
✅ |
responses.md |
Laravel 13 Notes
Attributes pour API Resources
Laravel 13 introduit #[Collects] et #[PreserveKeys] pour configurer les ResourceCollections via attributs PHP.
use Illuminate\Http\Resources\Json\ResourceCollection;
use Illuminate\Http\Resources\Attributes\Collects;
use Illuminate\Http\Resources\Attributes\PreserveKeys;
#[Collects(PostResource::class)]
#[PreserveKeys]
final class PostCollection extends ResourceCollection {}
JSON:API compliance
Pour les APIs JSON:API (sparse fieldsets, inclusion, links), voir [[laravel-jsonapi]] qui couvre ?include=, ?fields[type]=, et la pagination conforme spec.
Best Practices
DO
- Utiliser API Resources (
JsonResource) pour toute réponse JSON publique
- Versionner via URL (
/api/v1) plutôt que via header (lisible, cacheable)
- Rate-limiter par utilisateur ET par IP (
throttle:60,1 + custom limiter)
- Documenter via OpenAPI/Scribe avant de coder l'endpoint
- Préférer
cursor() pagination pour grandes listes (stable, performant)
DON'T
- Retourner directement un Model Eloquent (fuite de colonnes sensibles)
- Mélanger statuts HTTP (toujours 422 pour validation, 401 vs 403)
- Skip Form Request validation (jamais valider en controller)
- Exposer les IDs auto-increment publiquement (préférer UUID/ULID)
- Oublier
PreventRequestForgery exemption pour les webhooks externes