What this prompt does
This prompt makes Claude Code build a complete API slice for one resource instead of a lone controller you then have to wire up by hand. By naming six artifacts explicitly — controller, Form Request validation, API Resource transformers, routes, feature tests, and OpenAPI/Swagger comments — it forces the model to deliver the whole vertical: the request comes in validated, the response goes out shaped, the route is registered, and a test proves each endpoint works.
It works because it's prescriptive, not vague. Generic "write me an API" prompts produce inconsistent shapes and skip the boring-but-critical parts (validation, error envelopes, tests). Here you pin the [framework], [auth_method], the exact [actions], and the [filter_fields], so the output matches your project's conventions rather than the model's defaults. The explicit asks for pagination, sorting, and consistent JSON error responses close the gaps that usually become bug tickets later.
When to use it
- Scaffolding a brand-new resource (Product, Booking, Order) and you want validation, tests, and docs in one pass.
- Standing up a public or mobile-facing API where pagination and filtering are required, not optional.
- Replacing an inconsistent hand-rolled endpoint with a conventional controller + Form Request + Resource trio.
- Onboarding a teammate who needs a reference implementation that follows your house style.
- Building the read API a Flutter or SPA client will consume, where stable response shapes matter.
Example output
For Create a complete RESTful API for Product in my Laravel project … index, store, show, update, destroy … Sanctum auth … filter by category_id, status, Claude Code returns:
app/Http/Controllers/Api/ProductController.php (5 actions, eager-loaded)
app/Http/Requests/StoreProductRequest.php (rules + messages)
app/Http/Requests/UpdateProductRequest.php
app/Http/Resources/ProductResource.php
tests/Feature/ProductApiTest.php (one test per endpoint)
routes/api.php → Route::apiResource('products', …)
->middleware('auth:sanctum')
// index: ?category_id=3&status=active&sort=-created_at&page=2
{ "data": [ … ], "meta": { "current_page": 2, "total": 57 } }
Pro tips
- Set
[filter_fields]to an explicit allow-list and ask the controller to validate against it — never let raw query params reach the query builder, or you've shipped a filtering injection. - Keep the Form Requests even though the controller validates: your Filament resources and admin forms can reuse the same rules, so you get one source of truth.
- Tell it which paginator you want (
paginatevscursorPaginate); cursor pagination is the right default for large, mobile-fed lists. - Make the tests assert
assertJsonStructureand the error envelope, not justassertOk— that's what catches a Resource field rename before production does. - Pair this with a follow-up "now add rate limiting and an idempotency key to
store" once the slice is green.