puchan / laravel-api-docs
Automatic API documentation generator for Laravel applications
Installs: 81
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/puchan/laravel-api-docs
Requires
- php: ^8.1|^8.2|^8.3
- laravel/framework: ^10.0|^11.0|^12.0
README
Automatic API documentation generator for Laravel applications. Generate beautiful, interactive API documentation by simply installing the package - zero configuration required!
✨ Features
- ✅ Zero Configuration - Works immediately after installation
- ✅ Auto Route Scanning - Automatically discovers all your API routes
- ✅ Database Schema Integration - Shows available fields from database tables with toggle option
- ✅ Advanced Parameter Detection - Auto-detects query params from:
- FormRequests validation rules
- Method signatures and type hints
- Controller method body (
$request->has(),$request->input(), etc.) - Pagination patterns
- ✅ Real Data Examples - Fetches actual data from database for response examples with security sanitization
- ✅ Smart Response Detection - Detects custom response patterns:
Resource::collection()for arraysnew Resource()for single objectssendResponse()custom methods
- ✅ Laravel Resource Support - Uses your Resource classes for accurate response examples
- ✅ Multiple Formats - HTML, JSON, and OpenAPI/Swagger formats
- ✅ Compact UI - Space-efficient table format with optimized spacing and typography
- ✅ URL Persistence - Bookmarkable URLs with controller selection state
- ✅ Pagination Detection - Automatically identifies paginated endpoints
- ✅ Highly Configurable - Customize everything via config file and environment variables
📋 Requirements
- PHP 8.1 or higher
- Laravel 10.x, 11.x, or 12.x
- PostgreSQL (for database schema reading)
📦 Installation
Install the package via Composer:
composer require puchan/laravel-api-docs
The package will be auto-discovered by Laravel. No additional setup required!
🚀 Quick Start
After installation, your API documentation is immediately available at:
http://your-app.test/api-docs
That's it! The package automatically:
- Scans all your API routes
- Reads database schemas (PostgreSQL)
- Detects query parameters from FormRequests AND controller code
- Fetches real data from database for response examples
- Detects Resource::collection() vs single Resources
- Generates response examples with security sanitization
- Creates beautiful, compact documentation with URL persistence
📖 Available Endpoints
1. HTML Documentation (Interactive UI)
GET /api-docs
Beautiful, responsive web interface with:
- Collapsible route sections
- Color-coded HTTP methods
- Compact parameter tables
- Database field information (toggleable)
- Real data examples with security sanitization
- URL persistence for bookmarking
- One-click cURL and Postman export
- Syntax-highlighted JSON examples
- Optimized spacing for maximum content visibility
2. JSON Format (Programmatic Access)
GET /api-docs/json
Complete API documentation in JSON format for:
- Custom documentation tools
- CI/CD integration
- API testing tools
3. OpenAPI/Swagger Format
GET /api-docs/swagger
OpenAPI 3.0 compliant format for:
- Swagger UI
- Postman import
- API clients generation
⚙️ Configuration
Publishing Config (Optional)
While the package works without configuration, you can customize it:
php artisan vendor:publish --tag=api-docs-config
This creates config/api-docs.php:
<?php return [ // API Documentation Title 'title' => env('API_DOCS_TITLE', config('app.name') . ' API Documentation'), // API Version 'version' => env('API_DOCS_VERSION', '1.0.0'), // API Base URL 'base_url' => env('API_DOCS_BASE_URL', config('app.url') . '/api'), // Enable/disable documentation routes 'enabled' => env('API_DOCS_ENABLED', true), // Route prefix for documentation 'route_prefix' => env('API_DOCS_ROUTE_PREFIX', 'api-docs'), // Middleware to apply to documentation routes 'middleware' => ['web'], // Route Filters 'route_filters' => [ // Only include routes starting with these prefixes 'include_prefixes' => ['api/'], // Exclude routes matching these patterns 'exclude_patterns' => [ 'sanctum/*', 'telescope/*', 'horizon/*', ], ], // Resource Detection 'resources' => [ // Automatically detect and use Laravel Resources 'auto_detect' => true, // Namespace where resources are located 'namespace' => 'App\\Http\\Resources', ], // Database Schema 'database' => [ // Schema name for PostgreSQL 'schema' => 'public', // Show database schema in documentation // Set to false to hide database schema tab (useful in production) 'show_in_docs' => env('API_DOCS_SHOW_DATABASE_SCHEMA', true), // Use actual data from database for response examples // Set to false to use generated dummy data instead 'use_actual_data' => env('API_DOCS_USE_ACTUAL_DATA', true), ], ];
Environment Variables
Configure via .env file:
API_DOCS_ENABLED=true API_DOCS_TITLE="My Awesome API" API_DOCS_VERSION="2.0.0" API_DOCS_BASE_URL="https://api.example.com" API_DOCS_ROUTE_PREFIX="docs" API_DOCS_SHOW_DATABASE_SCHEMA=true API_DOCS_USE_ACTUAL_DATA=true
Publishing Views (Optional)
Customize the HTML documentation:
php artisan vendor:publish --tag=api-docs-views
Views will be published to resources/views/vendor/api-docs/.
📚 How It Works
1. Route Detection
The package automatically scans all registered routes:
// Your routes/api.php Route::get('/api/products', [ProductController::class, 'index']); Route::post('/api/products', [ProductController::class, 'store']); Route::get('/api/products/{id}', [ProductController::class, 'show']);
Automatically detected:
- HTTP methods (GET, POST, PUT, PATCH, DELETE)
- Route parameters (
{id},{slug}, etc.) - Middleware applied to routes
- PHPDoc comments from controller methods
2. Parameter Detection
From FormRequests:
class StoreProductRequest extends FormRequest { public function rules() { return [ 'name' => 'required|string|max:255', 'price' => 'required|numeric|min:0', 'status' => 'required|in:active,inactive', 'category_id' => 'required|exists:categories,id', ]; } }
From Method Signatures:
public function show(Request $request, int $id) { // $id automatically detected as path parameter }
From Controller Method Body:
public function index(Request $request) { $query = Product::query(); if ($request->has('search') && $request->search) { $query->where('name', 'like', "%{$request->search}%"); } if ($request->input('category_id')) { $query->where('category_id', $request->category_id); } if ($request->branch_ids) { $query->whereIn('branch_id', $request->branch_ids); } return $query->get(); }
Automatically detects:
search(string) - from$request->has('search')category_id(integer) - from$request->input('category_id')branch_ids(array) - from$request->branch_ids(smart type detection)
Supported patterns:
$request->has('param')$request->input('param')$request->get('param')$request->query('param')$request->param(magic property access)
Pagination Auto-Detection:
public function index() { return Product::paginate(20); // Automatically adds 'page' and 'per_page' parameters }
3. Database Schema
Automatically reads table schemas:
class ProductController extends Controller { public function index() { return Product::all(); // Automatically shows 'products' table schema } }
Displays:
- Column names and types
- Nullable fields
- Default values
- Maximum lengths
- Indexes and foreign keys
4. Response Examples
Detects Collection vs Single Resource:
// Collection - returns array public function index() { return $this->sendResponse( RoleResource::collection($roles), 'Roles retrieved successfully' ); } // Generates: { "data": [{...}, {...}] } // Single Resource - returns object public function show($id) { return $this->sendResponse( new UserResource($user), 'User retrieved successfully' ); } // Generates: { "data": {...} }
Uses Real Database Data:
class ProductResource extends JsonResource { public function toArray($request) { return [ 'id' => $this->id, 'name' => $this->name, 'price' => $this->price, 'status' => $this->status, 'category' => new CategoryResource($this->whenLoaded('category')), 'created_at' => $this->created_at, 'updated_at' => $this->updated_at, ]; } }
The package automatically:
- Fetches the first record from the database table
- Maps it to your Resource structure
- Sanitizes sensitive fields (passwords, tokens, API keys)
Generated Response:
{
"success": true,
"status": 200,
"message": "Success",
"data": [
{
"id": 1,
"name": "string value",
"price": 99.99,
"status": "active",
"category": "string value",
"created_at": "2025-01-15T12:00:00Z",
"updated_at": "2025-01-15T12:00:00Z"
}
],
"meta": {
"size": 20,
"page": 1,
"total_pages": 1,
"total_items": 1
}
}
💡 Usage Examples
Adding DocBlocks for Better Documentation
/** * Get all products with filtering and pagination * * Returns a paginated list of products. You can filter by category, * status, and search by name. */ public function index(ProductIndexRequest $request) { return ProductResource::collection( Product::with('category') ->paginate($request->input('per_page', 20)) ); }
Filtering Routes
Include only specific API versions:
// config/api-docs.php 'route_filters' => [ 'include_prefixes' => ['api/v1/', 'api/v2/'], ],
Exclude internal or admin routes:
'route_filters' => [ 'exclude_patterns' => [ 'api/internal/*', 'api/admin/*', 'telescope/*', ], ],
Custom Route Prefix
Change the documentation URL:
API_DOCS_ROUTE_PREFIX=documentation
Access documentation at: http://your-app.test/documentation
🎨 UI Features
Compact Table Format
Parameters are displayed in space-efficient tables instead of card grids:
| Parameter | Type | Required | Description |
|---|---|---|---|
| search | string | No | Search by name |
| category_id | integer | No | Filter by category |
URL Persistence
When you select a controller, the URL updates automatically:
http://your-app.test/api-docs?controller=ProductController
Benefits:
- Bookmark specific controllers
- Share direct links with your team
- Browser back/forward navigation works
- Refresh page maintains your selection
Optimized Spacing
- Compact typography (10px base font)
- Reduced padding throughout
- Smaller badges and buttons
- More content visible on screen
Copy to Clipboard
One-click copy for:
- cURL commands with all parameters
- Postman collection export
- Response examples
🔒 Security
Protect Documentation in Production
Using Middleware:
// config/api-docs.php 'middleware' => ['web', 'auth', 'admin'],
Disable in Production:
# .env.production API_DOCS_ENABLED=false
Hide Database Schema in Production:
# .env.production API_DOCS_SHOW_DATABASE_SCHEMA=false
This keeps the documentation accessible but hides sensitive database structure information.
Disable Real Data Examples in Production:
# .env.production API_DOCS_USE_ACTUAL_DATA=false
This prevents exposing real database records in documentation. The package will use generated dummy data instead.
Automatic Security Sanitization:
When using real data, sensitive fields are automatically hidden:
// Original database value 'password' => '$2y$10$92IXUNpkjO0rOQ5byMi...', 'api_key' => 'sk_live_51H7...', 'access_token' => 'eyJhbGciOiJIUzI1NiIsInR...', // In documentation 'password' => '***HIDDEN***', 'api_key' => '***HIDDEN***', 'access_token' => '***HIDDEN***',
Protected field patterns:
password,secret,tokenapi_key,private_keyaccess_token,refresh_tokencredit_card,ssn,salt
Conditional Enabling:
// config/api-docs.php 'enabled' => env('API_DOCS_ENABLED', !app()->isProduction()),
IP Whitelist Example
// config/api-docs.php 'middleware' => ['web', 'ip.whitelist'],
🔄 Integration with Swagger UI
Use the OpenAPI endpoint with Swagger UI:
<!DOCTYPE html> <html> <head> <link rel="stylesheet" href="https://unpkg.com/swagger-ui-dist@5/swagger-ui.css" /> </head> <body> <div id="swagger-ui"></div> <script src="https://unpkg.com/swagger-ui-dist@5/swagger-ui-bundle.js"></script> <script> SwaggerUIBundle({ url: '/api-docs/swagger', dom_id: '#swagger-ui', }); </script> </body> </html>
🛠️ Troubleshooting
Documentation Not Appearing
-
Clear Laravel cache:
php artisan config:clear php artisan route:clear php artisan cache:clear
-
Verify routes are registered:
php artisan route:list | grep api-docs -
Check if package is discovered:
php artisan package:discover
Database Schema Not Loading
PostgreSQL Configuration:
DB_CONNECTION=pgsql DB_HOST=127.0.0.1 DB_PORT=5432 DB_DATABASE=your_database DB_SCHEMA=public
Update config:
// config/api-docs.php 'database' => [ 'schema' => env('DB_SCHEMA', 'public'), ],
Resources Not Detected
Ensure your Resource classes:
- Extend
Illuminate\Http\Resources\Json\JsonResource - Are in the configured namespace (default:
App\Http\Resources) - Follow naming convention:
{Model}Resource
Example:
// app/Http/Resources/ProductResource.php class ProductResource extends JsonResource { public function toArray($request) { return [ 'id' => $this->id, 'name' => $this->name, ]; } }
No Routes Showing
Check route filters:
// config/api-docs.php 'route_filters' => [ 'include_prefixes' => ['api/'], // Make sure your routes match ],
Verify routes exist:
php artisan route:list --path=api
🎯 Best Practices
1. Use FormRequests for Validation
class StoreProductRequest extends FormRequest { public function rules() { return [ 'name' => 'required|string|max:255', 'price' => 'required|numeric|min:0', ]; } }
Benefits:
- Automatic parameter documentation
- Type detection (string, integer, array, etc.)
- Validation rules displayed in Request Body tab
Note: Even without FormRequests, the package detects parameters from your controller code using $request->has(), $request->input(), etc.
2. Use Laravel Resources
class ProductResource extends JsonResource { public function toArray($request) { return [ 'id' => $this->id, 'name' => $this->name, 'price' => (float) $this->price, ]; } }
Benefits:
- Accurate response examples with real database data
- Proper data transformation
- Consistent API responses
- Automatic detection of array vs single object responses
Pro Tip: Use Resource::collection() for list endpoints and new Resource() for single items. The package automatically generates correct response structures.
// List endpoint - returns array return RoleResource::collection($roles); // Documentation shows: { "data": [{...}, {...}] } // Single endpoint - returns object return new RoleResource($role); // Documentation shows: { "data": {...} }
3. Add Meaningful DocBlocks
/** * Update product details * * Updates an existing product with the provided data. * Requires authentication and product ownership. * * @param UpdateProductRequest $request * @param int $id Product ID * @return JsonResponse */ public function update(UpdateProductRequest $request, int $id) { // ... }
4. Use Resource Controllers
Route::apiResource('products', ProductController::class);
Benefits:
- Standard RESTful routes
- Consistent naming
- Better documentation organization
📝 Changelog
Please see CHANGELOG for more information on what has changed recently.
🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
🔗 Links
- GitHub Repository: https://github.com/bunthondev/laravel-api-docs
- Packagist: https://packagist.org/packages/puchan/laravel-api-docs
- Issues: https://github.com/bunthondev/laravel-api-docs/issues
📄 License
The MIT License (MIT). Please see License File for more information.
💖 Support
If you find this package helpful, please consider:
- ⭐ Starring the repository on GitHub
- 🐛 Reporting bugs and issues
- 💡 Suggesting new features
- 🔀 Contributing code improvements
🙏 Credits
Built with ❤️ for the Laravel community