I've built REST APIs in Laravel across a dozen projects now — from simple CRUD endpoints to complex multi-tenant systems. A few patterns keep proving themselves worth the upfront investment. Here they are.
API Resources for consistent response shapes
Never return Eloquent models directly from controllers. Always transform through a Resource class. This gives you a stable contract your frontend can rely on, regardless of what changes in the underlying model.
class ArticleResource extends JsonResource {
public function toArray(Request $request): array {
return [
'id' => $this->id,
'slug' => $this->slug,
'title' => $this->title,
'excerpt' => $this->excerpt,
'published' => $this->published_at?->toIso8601String(),
'author' => new UserResource($this->whenLoaded('author')),
];
}
}Form Requests for validation
Keep validation out of controllers entirely. Form Request classes are testable in isolation and keep the controller focused on orchestration rather than validation logic.
class StoreArticleRequest extends FormRequest {
public function rules(): array {
return [
'title' => ['required', 'string', 'max:255'],
'slug' => ['required', 'string', 'unique:articles,slug'],
'excerpt' => ['required', 'string', 'max:300'],
'body' => ['required', 'string'],
];
}
}API versioning: Prefix all routes with /api/v1/ from day one, even if you only have one version. Retrofitting versioning into an existing API is painful. Adding v2 later when you have breaking changes is trivial if you planned for it.
The Repository pattern
For anything beyond simple CRUD, introduce a repository layer between your controllers and Eloquent. This makes your business logic testable without hitting a real database and keeps your controllers thin. It's more code upfront but pays off within the first significant feature change.
Rate limiting
Laravel's built-in rate limiting is excellent. Use named rate limiters in RouteServiceProvider rather than inline throttle: middleware — it gives you more control and makes it easy to apply different limits to different client types.