Laravel API Documentation is a powerful package that automatically generates OpenAPI 3.0 documentation from your Laravel application code. It eliminates the need to manually write and maintain API documentation by intelligently analyzing your routes, controllers, requests, and responses.
- Zero-Config Operation: Works out of the box with standard Laravel conventions
- Automatic Route Analysis: Scans all routes and extracts path parameters, HTTP methods, and middleware
- Smart Request Analysis: Extracts validation rules from FormRequest classes to document request parameters
- Dynamic Response Detection: Analyzes controller return types and method bodies to document responses
- Spatie Data Integration: First-class support for Spatie Laravel Data DTOs
- Resource Collection Support: Handles JsonResource and ResourceCollection responses
- Attribute Enhancement: Optional PHP 8 attributes for additional documentation control
composer require jkbennemann/laravel-api-documentation
php artisan vendor:publish --tag="api-documentation-config"
The package stores documentation in your storage directory. Make it accessible with:
php artisan storage:link
Out of the box, the package:
- Ignores vendor routes and
HEAD
/OPTIONS
methods - Disables Swagger/ReDoc UIs by default (can be enabled in config)
- Stores documentation at
storage/app/public/api-documentation.json
To include the generated documentation in version control, update your .gitignore
:
# storage/app/public/.gitignore
*
!.gitignore
!api-documentation.json
For a more accessible location, add a custom disk in config/filesystems.php
:
'documentation' => [
'driver' => 'local',
'root' => public_path('docs'),
'url' => env('APP_URL') . '/docs',
'visibility' => 'public',
],
Then update your config:
// config/laravel-api-documentation.php
'storage' => [
'disk' => 'documentation',
'filename' => 'api-documentation.json',
],
Add documentation generation to your deployment workflow:
# In your deployment script
php artisan documentation:generate
Or add to your composer.json
scripts:
"scripts": {
"post-deploy": [
"@php artisan documentation:generate"
]
}
php artisan documentation:generate
This command scans your application routes and generates an OpenAPI 3.0 specification file at your configured location.
By default, the documentation is accessible at:
/documentation
- Default UI (Swagger if enabled)/documentation/swagger
- Swagger UI (if enabled)/documentation/redoc
- ReDoc UI (if enabled)
To enable the UIs, update your configuration:
// config/laravel-api-documentation.php
'ui' => [
'enabled' => true,
'swagger' => true,
'redoc' => true,
],
Generate documentation for specific files only:
php artisan documentation:generate --file=api-v1
This generates api-v1.json
based on your configuration settings.
The package analyzes your Laravel application using several intelligent components:
- Route Analysis: Scans all registered routes to identify controllers, HTTP methods, and path parameters
- Controller Analysis: Examines controller methods to determine response types and structures
- Request Analysis: Processes FormRequest classes to extract validation rules and convert them to OpenAPI parameters
- Response Analysis: Detects return types and analyzes method bodies to determine response structures
The package automatically detects and documents your API with minimal configuration:
- Analyzes controller return types (
JsonResponse
,ResourceCollection
, etc.) - Examines method bodies when return types aren't declared
- Supports union types (
@return UserData|AdminData
) - Generates proper paginated response structures with
data
,meta
, andlinks
- Works with traditional and invokable controllers
- Processes class-level and method-level attributes
- Handles mixed controller architectures seamlessly
- Extracts validation rules from FormRequest classes
- Detects route parameters (
{id}
,{user}
) automatically - Supports nested parameter structures (
user.profile.name
) - Handles parameters merged from route values in
prepareForValidation
- Converts Laravel validation rules to OpenAPI types and formats
- Intelligently determines required vs. optional parameters
- Maps validation rules to appropriate formats (
email
βstring
withemail
format)
- Distinguishes between arrays and object responses
- Analyzes ResourceCollection for contained DTO types
- Supports
DataCollectionOf
attributes for nested collections
- Route Value Detection: Properly handles parameters merged from route values in
prepareForValidation
- Parameter Exclusion: Supports the
IgnoreDataParameter
attribute to exclude fields from body parameters
- Clean Schema Generation: Excludes internal Spatie Data fields (
_additional
and_data_context
) from documentation - DataCollectionOf Support: Properly documents nested collection structures with correct item types
- Union Type Support: Handles PHP 8+ union types in Spatie Data objects
- JsonResource Analysis: Improved detection of dynamic properties in JsonResource responses
- Method Body Parsing: Enhanced analysis of controller method bodies for response structure detection
- Paginated Response Support: Accurate documentation of paginated responses with proper structure
For more information on the OpenAPI specification, see OpenAPI Specification.
While the package works automatically, you can enhance your documentation using PHP 8 attributes.
use JkBennemann\LaravelApiDocumentation\Attributes\Tag;
use JkBennemann\LaravelApiDocumentation\Attributes\Summary;
use JkBennemann\LaravelApiDocumentation\Attributes\Description;
use JkBennemann\LaravelApiDocumentation\Attributes\AdditionalDocumentation;
use JkBennemann\LaravelApiDocumentation\Attributes\DataResponse;
#[Tag('Authentication')]
#[Summary('Login a user')]
#[Description('Logs a user in with email and password credentials.')]
#[AdditionalDocumentation(url: 'https://example.com/auth', description: 'Auth documentation')]
#[DataResponse(200, description: 'Logged in user information', resource: UserResource::class)]
#[DataResponse(401, description: 'Failed Authentication', resource: ['error' => 'string'])]
public function login(LoginRequest $request)
{
// Method implementation
}
Available parameters:
- (required)
status
(int) - The status code of the response description
(string) - A description of the response; default:''
resource
(null | string | array) - The resource class or Spatie Data object class that is returned by the route (e.g.UserResource::class
,['id' => 'string']
,null
); default:[]
headers
(null | array) - An array of response headers that are returned by the route (e.g.['X-Token' => 'string']
); default:[]
# SampleController.php
use JkBennemann\LaravelApiDocumentation\Attributes\DataResponse;
//..
#[DataResponse(200, description: 'Logged in user information', resource: UserResource::class, headers: ['X-Token' => 'Token for the user to be used to issue API calls',])]
#[DataResponse(401, description: 'Failed Authentication', resource: ['error' => 'string'])]
public function index()
{
//...
}
This will add a new field to the route object in the OpenAPI file:
{
//...
"\/login": {
"post": {
//...
"responses": {
"200": {
"description": "Logged in user information",
"headers": {
"X-Token": {
"description": "Token for the user to be used to issue API calls",
"schema": {
"type": "string"
}
}
},
"content": {
"application\/json": {
"schema": {
//data of the UserResource.php
}
}
}
},
"401": {
"description": "Failed Authentication",
"headers": {},
"content": {
"application\/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string"
}
}
}
}
}
}
}
//...
}
}
}
For request or resource classes the same attributes can be used as for the routes, except for the Tag
attribute.
In addition to that the following attributes are available:
This attribute can be used to specify additional information about path parameters in your routes.
It can be applied to controller methods to enhance the documentation of route parameters like {id}
, {user}
, etc.
Available parameters:
- (required)
name
(string) - The name of the path parameter (must match the route parameter) required
(boolean) - Whether the parameter is required or not; default:true
description
(string) - A description of the parameter; default:''
type
(string) - The type of the parameter; default:'string'
format
(string) - The format of the parameter, considered as the sub-type as of OpenAPI; default:null
example
(mixed) - An example value for the parameter; default:null
# UserController.php
use JkBennemann\LaravelApiDocumentation\Attributes\PathParameter;
//..
#[PathParameter(name: 'id', type: 'string', format: 'uuid', description: 'The user ID', example: '123e4567-e89b-12d3-a456-426614174000')]
#[PathParameter(name: 'status', type: 'string', description: 'Filter users by status', example: 'active')]
public function show(string $id, string $status)
{
//...
}
This attribute can be used to specify additional information about request or response parameters.
It can be applied at both class level and method level (e.g., on the rules()
method of FormRequest classes).
Available parameters:
- (required)
name
(string) - The name of the parameter required
(boolean) - Whether the parameter is required or not; default:false
description
(string) - A description of the parameter; default:''
type
(string) - The type of the parameter; default:'string'
format
(string) - The format of the parameter, considered as the sub-type as of OpenAPI; default:null
example
(mixed) - An example value for the parameter; default:null
deprecated
(boolean) - Whether the parameter is deprecated or not; default:false
Method Level Usage (FormRequest):
# LoginUserRequest.php
use JkBennemann\LaravelApiDocumentation\Attributes\Parameter;
//..
#[Parameter(name: 'email', required: true, format: 'email', description: 'The email of the user', example: 'hello@example.com')]
#[Parameter(name: 'password', required: true, description: 'The password of the user')]
#[Parameter(name: 'confirm_token', required: true, description: 'The confirmation token. This is not used any longer!', deprecated: true)]
public function rules(): array
{
return [
'email' => [
'required',
'email',
],
'password' => 'required',
];
}
Class Level Usage (Resource):
# UserResource.php
use JkBennemann\LaravelApiDocumentation\Attributes\Parameter;
#[Parameter(name: 'id', type: 'string', format: 'uuid', description: 'The user ID', example: '123e4567-e89b-12d3-a456-426614174000')]
#[Parameter(name: 'email', type: 'string', format: 'email', description: 'The users email address')]
#[Parameter(name: 'attributes', type: 'array', description: 'Additional attributes assigned to the user', example: [])]
public function toArray($request): array|JsonSerializable|Arrayable
{
return [
'id' => $this->id,
'email' => $this->email,
'attributes' => $this->userAttributes ?? [],
];
}
In addition to attributes, the package supports @queryParam
annotations for documenting query parameters:
# UserController.php
/**
* Get a list of users
*
* @queryParam per_page integer Number of users per page. Example: 15
* @queryParam search string Search term for filtering users. Example: john
* @queryParam status string Filter by user status. Example: active
*/
public function index(Request $request)
{
//...
}
This automatically generates query parameter documentation in the OpenAPI specification.
Here are some comprehensive examples showing how to leverage the automatic detection features:
<?php
namespace App\Http\Controllers;
use App\Http\Requests\CreateUserRequest;
use App\Http\Resources\UserResource;
use App\Models\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\ResourceCollection;
use JkBennemann\LaravelApiDocumentation\Attributes\{Tag, Summary, Description, PathParameter, DataResponse};
#[Tag('Users')]
class UserController extends Controller
{
/**
* Get a paginated list of users
*
* @queryParam per_page integer Number of users per page. Example: 15
* @queryParam search string Search term for filtering users. Example: john
* @queryParam status string Filter by user status. Example: active
*
* @return ResourceCollection<UserResource>
*/
#[Summary('List all users')]
#[Description('Retrieves a paginated list of users with optional filtering capabilities')]
public function index(Request $request): ResourceCollection
{
$users = User::query()
->when($request->search, fn($q) => $q->where('name', 'like', "%{$request->search}%"))
->when($request->status, fn($q) => $q->where('status', $request->status))
->paginate($request->per_page ?? 15);
return UserResource::collection($users);
}
/**
* Get a specific user by ID
*/
#[PathParameter(name: 'id', type: 'string', format: 'uuid', description: 'The user ID', example: '123e4567-e89b-12d3-a456-426614174000')]
#[DataResponse(200, description: 'User found successfully', resource: UserResource::class)]
#[DataResponse(404, description: 'User not found', resource: ['message' => 'string'])]
public function show(string $id): UserResource|JsonResponse
{
$user = User::findOrFail($id);
return new UserResource($user);
}
/**
* Create a new user
*/
#[Summary('Create user')]
#[DataResponse(201, description: 'User created successfully', resource: UserResource::class)]
#[DataResponse(422, description: 'Validation failed')]
public function store(CreateUserRequest $request): UserResource
{
$user = User::create($request->validated());
return new UserResource($user);
}
}
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use JkBennemann\LaravelApiDocumentation\Attributes\Parameter;
class CreateUserRequest extends FormRequest
{
#[Parameter(name: 'name', required: true, description: 'The full name of the user', example: 'John Doe')]
#[Parameter(name: 'email', required: true, format: 'email', description: 'Unique email address', example: 'john@example.com')]
#[Parameter(name: 'profile.bio', description: 'User biography', example: 'Software developer with 5 years experience')]
#[Parameter(name: 'profile.avatar', type: 'string', format: 'uri', description: 'Avatar image URL')]
#[Parameter(name: 'preferences.notifications', type: 'boolean', description: 'Enable email notifications', example: true)]
public function rules(): array
{
return [
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'email', 'unique:users'],
'profile.bio' => ['nullable', 'string', 'max:1000'],
'profile.avatar' => ['nullable', 'url'],
'preferences.notifications' => ['boolean'],
'preferences.theme' => ['string', 'in:light,dark'],
];
}
}
Laravel's invokable controllers (single-action controllers) are fully supported with class-level attribute processing:
<?php
namespace App\Http\Controllers;
use App\Http\Requests\CreatePostRequest;
use App\Http\Resources\PostResource;
use App\Models\Post;
use Illuminate\Http\JsonResponse;
use JkBennemann\LaravelApiDocumentation\Attributes\{Tag, Summary, Description, DataResponse};
#[Tag('Posts')]
#[Summary('Create a new blog post')]
#[Description('Creates a new blog post with the provided content and metadata')]
#[DataResponse(PostResource::class, 201, 'Post created successfully')]
class CreatePostController extends Controller
{
/**
* Handle the incoming request to create a new post.
*
* @param CreatePostRequest $request
* @return JsonResponse
*/
public function __invoke(CreatePostRequest $request): JsonResponse
{
$post = Post::create($request->validated());
return PostResource::make($post)
->response()
->setStatusCode(201);
}
}
Key Features for Invokable Controllers:
- Class-Level Attributes:
#[Tag]
,#[Summary]
,#[Description]
placed on the class are automatically detected - Automatic Route Processing: Both
Controller@method
andController
(invokable) route formats supported - Response Type Detection: Same automatic detection as traditional controllers
- Request Validation: FormRequest classes processed normally
- Mixed Controller Support: Traditional and invokable controllers work seamlessly together
Route Registration:
// Traditional route registration for invokable controllers
Route::post('/posts', CreatePostController::class);
// Mixed with traditional controllers
Route::get('/posts', [PostController::class, 'index']);
Route::post('/posts', CreatePostController::class); // Invokable
Route::get('/posts/{id}', [PostController::class, 'show']);
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
use JkBennemann\LaravelApiDocumentation\Attributes\Parameter;
class UserResource extends JsonResource
{
#[Parameter(name: 'id', type: 'string', format: 'uuid', description: 'Unique user identifier')]
#[Parameter(name: 'name', type: 'string', description: 'Full name of the user')]
#[Parameter(name: 'email', type: 'string', format: 'email', description: 'User email address')]
#[Parameter(name: 'profile', type: 'object', description: 'User profile information')]
#[Parameter(name: 'created_at', type: 'string', format: 'date-time', description: 'Account creation timestamp')]
public function toArray($request): array
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
'profile' => [
'bio' => $this->profile?->bio,
'avatar' => $this->profile?->avatar,
],
'preferences' => [
'notifications' => $this->preferences['notifications'] ?? true,
'theme' => $this->preferences['theme'] ?? 'light',
],
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
];
}
}
<?php
namespace App\Http\Controllers;
use App\DTOs\UserData;
use App\DTOs\AdminData;
- Leverage Automatic Detection: Let the package automatically detect response types and validation rules
- Use Attributes for Enhancement: Add
#[Parameter]
and#[PathParameter]
attributes only when you need to provide additional context - Document Complex Scenarios: Use
@queryParam
annotations for query parameters and union return types for multiple response formats - Structured Validation: Use nested validation rules for complex request structures
- Consistent Naming: Use consistent parameter naming across your API for better documentation
- Advanced Response Type Detection: Automatic detection of return types, union types, and method body analysis
- Smart Request Parameter Extraction: FormRequest validation rule processing and parameter attribute support
- Invokable Controller Support: Full support for Laravel invokable controllers with class-level attribute processing
- Path Parameter Documentation:
#[PathParameter]
attribute for route parameter enhancement - Query Parameter Support:
@queryParam
annotation processing - Nested Parameter Handling: Complex nested parameter structures with proper grouping
- Spatie Data Integration: Full support for Spatie Data objects with automatic schema generation
- Resource Collection Intelligence: Smart detection of collection types and pagination
- Union Type Processing: DocBlock union type analysis with
oneOf
schema generation - Class Name Resolution: Automatic resolution of short class names to fully qualified names
- Validation Rule Conversion: Laravel validation rules to OpenAPI type conversion
- Enhanced Examples: More comprehensive example generation for request/response bodies
- Custom Validation Rules: Support for custom Laravel validation rules
- Advanced Response Headers: Automatic detection of response headers from controller methods
- File Upload Documentation: Automatic detection and documentation of file upload endpoints
- Middleware Documentation: Enhanced middleware detection and security scheme generation
- Custom Storage Options: Support for external storages (e.g., GitHub, S3 Bucket, etc.)
- Multi-version API Support: Support for API versioning in documentation
- Performance Optimization: Caching mechanisms for large applications
- Integration Testing: Built-in API testing capabilities based on generated documentation
Please review our security policy on how to report security vulnerabilities.
The MIT License (MIT). Please see License File for more information.