Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/charlietyn/openapi-generator/llms.txt

Use this file to discover all available pages before exploring further.

This guide demonstrates practical scenarios for using the Laravel OpenAPI Generator in production environments.

Scenario 1: Generate Admin + Mobile Docs from CLI

Goal: Produce OpenAPI + Postman + Insomnia outputs only for admin and mobile APIs.

Setup

Define API types in config/openapi.php:
'api_types' => [
    'admin' => [
        'prefix' => 'admin',
        'folder_name' => 'API Admin',
        'enabled' => true,
    ],
    'mobile' => [
        'prefix' => 'mobile',
        'folder_name' => 'API Mobile',
        'enabled' => true,
    ],
    'site' => [
        'prefix' => 'api',
        'folder_name' => 'API Public',
        'enabled' => false,  // Not included
    ],
],
Ensure the output directory is writable:
chmod -R 775 storage/app/public/openapi

Execution

1

Publish configuration

php artisan vendor:publish --tag=openapi-config
This creates config/openapi.php where you can customize API types, routes, and environments.
2

Run the generator

php artisan openapi:generate --all --api-type=admin --api-type=mobile
Expected output:
🚀 Generating OpenAPI Specification...

🔍 Filtering API types: admin, mobile
📋 Inspecting routes...
✅ Found 34 unique paths
💾 Writing OpenAPI specification...
✅ OpenAPI specification generated!
📄 File: storage/app/public/openapi/openapi-admin-mobile.json

📮 Generating Postman collection...
✅ Postman collection generated!
📄 File: storage/app/public/openapi/postman-admin-mobile.json
📋 Generating Postman environments...
  ├─ artisan: postman-env-artisan.json
  ├─ local: postman-env-local.json
  └─ production: postman-env-production.json

🛏️  Generating Insomnia workspace...
✅ Insomnia workspace generated!
📄 File: storage/app/public/openapi/insomnia-admin-mobile.json
  ├─ Includes 3 environments (base + artisan + local + production)
  ├─ Minimal API Spec tab
  └─ Automated tests included

✨ Generation complete! (--all mode)

Notes

  • Filenames include the filtered API type suffix (admin-mobile)
  • The generator validates that API types are enabled in config
  • Both Postman and Insomnia files include embedded environment variables

Common Mistakes

Using disabled or missing API typesIf you request an API type that’s disabled or not defined:
php artisan openapi:generate --api-type=unknown
You’ll get an error:
❌ Unknown or disabled API types: unknown. Available types: admin, mobile
Solution: Check config/openapi.php and ensure the API type is defined and enabled.
Forgetting to publish configWithout publishing config, the package uses defaults which may not match your route structure. Always publish config files:
php artisan vendor:publish --tag=openapi-config

Scenario 2: Serve Docs Over HTTP for Internal Tooling

Goal: Allow internal consumers (mobile apps, frontend teams, partner APIs) to fetch documentation via HTTP routes.

Setup

Enable routes in config/openapi.php:
'routes' => [
    'enabled' => true,
    'prefix' => 'documentation',
    'middleware' => [],  // Or ['auth:sanctum'] for protection
],

Execution

curl http://localhost:8000/documentation/openapi.json
Returns the complete OpenAPI 3.0.3 specification.

Notes

  • HTTP endpoints use the same generation logic as the CLI
  • Documentation is generated on-demand (not served from static files)
  • Query parameters apply the same filters as CLI flags

Common Mistakes

Middleware blocking accessIf you add authentication middleware:
'middleware' => ['auth:sanctum'],
Unauthenticated requests return 401:
curl http://localhost:8000/documentation/openapi.json
# {"message":"Unauthenticated."}
Solution: Either remove the middleware for public docs or include authentication headers:
curl -H "Authorization: Bearer YOUR_TOKEN" \
  http://localhost:8000/documentation/openapi.json
Invalid format parameterThe {format} parameter only accepts: json, yaml, yml, postman, insomnia.
curl http://localhost:8000/documentation/openapi.xml
# 404 Not Found

Scenario 3: Custom Endpoint Documentation

Goal: Document a non-CRUD endpoint like api-apps.rotate with custom descriptions and request fields.

Setup

Add custom endpoint configuration in config/openapi-docs.php:
return [
    'custom_endpoints' => [
        'api-apps.rotate' => [
            'summary' => 'Rotate API Key',
            'description' => 'Generates a new API key for the application and revokes the old one.',
            'request_fields' => [
                'reason' => 'Optional reason for key rotation (auditing purposes)',
            ],
            'response_description' => 'Returns the new API key, revocation timestamp, and affected scopes.',
        ],
        'users.export' => [
            'summary' => 'Export Users',
            'description' => 'Generates an export file of users matching the specified filters.',
            'request_fields' => [
                'format' => 'Export format: csv, xlsx, or json',
                'filters' => 'Array of filter conditions (e.g., {"status": "active"})',
                'columns' => 'Array of column names to include',
            ],
            'response_description' => 'Returns download URL and file metadata.',
        ],
    ],
];

Execution

1

Define route with name

Ensure your route has a name matching the custom endpoint key:
Route::post('api-apps/{app}/rotate', [ApiAppController::class, 'rotate'])
    ->name('api-apps.rotate');

Route::post('users/export', [UserController::class, 'export'])
    ->name('users.export');
2

Regenerate documentation

php artisan openapi:generate
The generator matches route names to custom endpoint keys and applies the custom documentation.
3

Verify in OpenAPI output

Open storage/app/public/openapi/openapi.json and find your endpoint:
{
  "/api-apps/{app}/rotate": {
    "post": {
      "summary": "Rotate API Key",
      "description": "Generates a new API key for the application and revokes the old one.",
      "requestBody": {
        "content": {
          "application/json": {
            "schema": {
              "properties": {
                "reason": {
                  "type": "string",
                  "description": "Optional reason for key rotation (auditing purposes)"
                }
              }
            }
          }
        }
      }
    }
  }
}

Notes

  • Use the entity.action pattern for keys
  • Custom endpoints override template-generated documentation
  • request_fields are merged with FormRequest validation rules

Common Mistakes

Key doesn’t match route nameIf you use a key that doesn’t match the route name:
'custom_endpoints' => [
    'apps.rotate' => [...],  // Route is named 'api-apps.rotate'
],
The custom documentation won’t be applied. Always use the exact route name:
php artisan route:list --name=rotate
# api-apps.rotate | POST | api-apps/{app}/rotate

Scenario 4: Template-Driven CRUD Documentation

Goal: Standardize list/show/create/update/delete descriptions using JSON templates to avoid repetitive manual documentation.

Setup

1

Publish templates

php artisan vendor:publish --tag=openapi-templates
This creates:
  • resources/openapi/templates/generic/list.json
  • resources/openapi/templates/generic/show.json
  • resources/openapi/templates/generic/create.json
  • resources/openapi/templates/generic/update.json
  • resources/openapi/templates/generic/delete.json
2

Enable template system

In config/openapi-templates.php:
return [
    'enabled' => true,
    
    'generic_templates' => [
        'list' => 'list.json',
        'show' => 'show.json',
        'create' => 'create.json',
        'update' => 'update.json',
        'delete' => 'delete.json',
    ],
];
3

Customize templates

Edit resources/openapi/templates/generic/list.json:
{
  "summary": "List {{entity_plural}}",
  "description": "Retrieve a paginated list of {{entity_plural}} with optional filtering and sorting.",
  "parameters": [
    {
      "name": "page",
      "in": "query",
      "schema": {"type": "integer", "default": 1},
      "description": "Page number"
    },
    {
      "name": "per_page",
      "in": "query",
      "schema": {"type": "integer", "default": 15},
      "description": "Items per page"
    },
    {
      "name": "sort",
      "in": "query",
      "schema": {"type": "string"},
      "description": "Sort field and direction (e.g., 'created_at:desc')"
    }
  ]
}

Execution

Generate documentation:
php artisan openapi:generate
The generator applies templates to all CRUD routes:
  • GET /users → uses list.json
  • GET /users/{id} → uses show.json
  • POST /users → uses create.json
  • PUT /users/{id} → uses update.json
  • DELETE /users/{id} → uses delete.json
Placeholders like {{entity_plural}} are replaced with users, {{entity_singular}} with user.

Notes

  • Templates reduce repetitive documentation
  • The generator falls back to metadata extraction when templates are disabled
  • Custom endpoint documentation overrides template output

Common Mistakes

JSON templates not foundIf template files are missing or paths are wrong:
❌ Failed to load template: resources/openapi/templates/generic/list.json
Solution: Verify template paths in config/openapi-templates.php match actual file locations.
Invalid JSON syntaxInvalid JSON in templates causes parsing errors:
{
  "summary": "List {{entity_plural}}",  // Missing closing brace
Solution: Validate JSON using jsonlint.com or your IDE.

Scenario 5: Generate Postman Environments

Goal: Export Postman environments for local development, staging, and production to use in API testing.

Setup

Define environments in config/openapi.php:
'environments' => [
    'base' => [
        'app_name' => env('APP_NAME', 'Laravel API'),
        'app_url' => env('APP_URL', 'http://localhost:8000'),
    ],
    
    'sub_environments' => [
        'artisan' => [
            'app_url' => 'http://localhost:8000',
        ],
        'local' => [
            'app_url' => 'http://localhost:8000',
        ],
        'production' => [
            'app_url' => 'https://api.example.com',
        ],
    ],
    
    'tracking_variables' => [
        'api_token' => '',
        'device_id' => '',
        'user_id' => '',
    ],
],

Execution

php artisan openapi:generate --with-postman
Creates:
  • postman-all.json - Main collection
  • postman-env-artisan.json
  • postman-env-local.json
  • postman-env-production.json

Import to Postman

1

Import collection

  1. Open Postman
  2. Click File > Import
  3. Select postman-all.json
2

Import environments

  1. Click Environments in left sidebar
  2. Click Import
  3. Select all postman-env-*.json files
3

Select environment

  1. Click the environment dropdown (top right)
  2. Select artisan, local, or production
  3. All requests now use that environment’s base URL and variables

Notes

  • The environment generator merges base + tracking variables into each sub-environment
  • Tracking variables appear in all environments with empty default values
  • You can set actual token values in Postman’s environment editor

Common Mistakes

Defining tracking variables in sub-environmentsDon’t repeat tracking variables in each sub-environment:
// ❌ Wrong
'sub_environments' => [
    'local' => [
        'app_url' => 'http://localhost:8000',
        'api_token' => '',  // Don't do this
    ],
    'production' => [
        'app_url' => 'https://api.example.com',
        'api_token' => '',  // Don't do this
    ],
],

// ✅ Correct
'tracking_variables' => [
    'api_token' => '',  // Define once here
],
Tracking variables are automatically merged into all sub-environments.

Scenario 6: CI/CD Pipeline Integration

Goal: Automatically generate and publish documentation on every deployment.

GitHub Actions Example

name: Generate API Documentation

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  docs:
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v3
      
      - name: Setup PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: '8.2'
      
      - name: Install dependencies
        run: composer install --no-dev --optimize-autoloader
      
      - name: Generate documentation
        run: |
          php artisan openapi:generate --all --no-cache
      
      - name: Upload to S3
        uses: jakejarvis/s3-sync-action@master
        with:
          args: --acl public-read --follow-symlinks
        env:
          AWS_S3_BUCKET: ${{ secrets.AWS_S3_BUCKET }}
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          AWS_REGION: 'us-east-1'
          SOURCE_DIR: 'storage/app/public/openapi'
          DEST_DIR: 'docs/api'

GitLab CI Example

generate-docs:
  stage: deploy
  image: php:8.2-cli
  
  before_script:
    - curl -sS https://getcomposer.org/installer | php
    - php composer.phar install --no-dev --optimize-autoloader
  
  script:
    - php artisan openapi:generate --all --no-cache
    - aws s3 sync storage/app/public/openapi s3://your-bucket/docs/api --acl public-read
  
  only:
    - main

Notes

  • Always use --no-cache in CI/CD to ensure fresh output
  • Consider using --all to generate all formats
  • Upload to S3, CDN, or documentation hosting platform

Scenario 7: Team Workflow for API Development

Goal: Establish a workflow where backend developers generate docs, and frontend/mobile teams consume them.

Workflow

1

Developer adds new endpoint

Backend developer creates a new route with FormRequest validation:
Route::post('products', [ProductController::class, 'store'])
    ->name('products.store');
class StoreProductRequest extends FormRequest
{
    public function rules()
    {
        return [
            'name' => 'required|string|max:255',
            'price' => 'required|numeric|min:0',
            'category_id' => 'required|exists:categories,id',
        ];
    }
}
2

Generate documentation locally

php artisan openapi:generate --with-postman
Developer reviews the generated docs to ensure accuracy.
3

Commit generated files

Add documentation files to version control:
git add storage/app/public/openapi/
git commit -m "Add product creation endpoint"
git push origin feature/add-products
4

CI/CD publishes docs

On merge to main, CI pipeline generates and publishes docs to a shared location:
https://docs.example.com/api/openapi.json
https://docs.example.com/api/postman-all.json
5

Frontend/mobile teams consume docs

Teams import the latest Postman collection or view the OpenAPI spec in Swagger UI.

Best Practices

Tips for teams:
  • Keep docs in version control: Commit generated files so teams can see changes in PRs
  • Automate generation: Run generation in CI/CD to ensure docs are always up-to-date
  • Use custom endpoints: Document complex actions that don’t fit CRUD templates
  • Review generated output: Check that FormRequest rules and model properties are accurately reflected

Next Steps

Edge Cases

Learn how to handle config caching issues, concurrent generation, large route sets, and multi-tenant deployments.

API Reference

Explore the programmatic API for advanced integration scenarios.