> ## 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.

# Common Scenarios

> Real-world examples for multi-API generation, team workflows, CI/CD pipelines, and custom documentation

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`:

```php theme={null}
'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:

```bash theme={null}
chmod -R 775 storage/app/public/openapi
```

### Execution

<Steps>
  <Step title="Publish configuration">
    ```bash theme={null}
    php artisan vendor:publish --tag=openapi-config
    ```

    This creates `config/openapi.php` where you can customize API types, routes, and environments.
  </Step>

  <Step title="Run the generator">
    ```bash theme={null}
    php artisan openapi:generate --all --api-type=admin --api-type=mobile
    ```

    Expected output:

    ```text theme={null}
    🚀 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)
    ```
  </Step>
</Steps>

### 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

<Warning>
  **Using disabled or missing API types**

  If you request an API type that's disabled or not defined:

  ```bash theme={null}
  php artisan openapi:generate --api-type=unknown
  ```

  You'll get an error:

  ```text theme={null}
  ❌ Unknown or disabled API types: unknown. Available types: admin, mobile
  ```

  **Solution**: Check `config/openapi.php` and ensure the API type is defined and enabled.
</Warning>

<Warning>
  **Forgetting to publish config**

  Without publishing config, the package uses defaults which may not match your route structure. Always publish config files:

  ```bash theme={null}
  php artisan vendor:publish --tag=openapi-config
  ```
</Warning>

***

## 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`:

```php theme={null}
'routes' => [
    'enabled' => true,
    'prefix' => 'documentation',
    'middleware' => [],  // Or ['auth:sanctum'] for protection
],
```

### Execution

<Tabs>
  <Tab title="OpenAPI JSON">
    ```bash theme={null}
    curl http://localhost:8000/documentation/openapi.json
    ```

    Returns the complete OpenAPI 3.0.3 specification.
  </Tab>

  <Tab title="OpenAPI YAML">
    ```bash theme={null}
    curl http://localhost:8000/documentation/openapi.yaml
    ```

    Returns the same specification in YAML format.
  </Tab>

  <Tab title="Filtered by API Type">
    ```bash theme={null}
    curl "http://localhost:8000/documentation/openapi.json?api_type=admin,mobile"
    ```

    Returns only routes matching `admin` or `mobile` API types.
  </Tab>

  <Tab title="Postman Collection">
    ```bash theme={null}
    curl "http://localhost:8000/documentation/postman?api_type=mobile&environment=production"
    ```

    Returns a Postman collection filtered to `mobile` routes with `production` environment variables.
  </Tab>
</Tabs>

### 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

<Warning>
  **Middleware blocking access**

  If you add authentication middleware:

  ```php theme={null}
  'middleware' => ['auth:sanctum'],
  ```

  Unauthenticated requests return 401:

  ```bash theme={null}
  curl http://localhost:8000/documentation/openapi.json
  # {"message":"Unauthenticated."}
  ```

  **Solution**: Either remove the middleware for public docs or include authentication headers:

  ```bash theme={null}
  curl -H "Authorization: Bearer YOUR_TOKEN" \
    http://localhost:8000/documentation/openapi.json
  ```
</Warning>

<Warning>
  **Invalid format parameter**

  The `{format}` parameter only accepts: `json`, `yaml`, `yml`, `postman`, `insomnia`.

  ```bash theme={null}
  curl http://localhost:8000/documentation/openapi.xml
  # 404 Not Found
  ```
</Warning>

***

## 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`:

```php theme={null}
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

<Steps>
  <Step title="Define route with name">
    Ensure your route has a name matching the custom endpoint key:

    ```php theme={null}
    Route::post('api-apps/{app}/rotate', [ApiAppController::class, 'rotate'])
        ->name('api-apps.rotate');

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

  <Step title="Regenerate documentation">
    ```bash theme={null}
    php artisan openapi:generate
    ```

    The generator matches route names to custom endpoint keys and applies the custom documentation.
  </Step>

  <Step title="Verify in OpenAPI output">
    Open `storage/app/public/openapi/openapi.json` and find your endpoint:

    ```json theme={null}
    {
      "/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)"
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
    ```
  </Step>
</Steps>

### Notes

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

### Common Mistakes

<Warning>
  **Key doesn't match route name**

  If you use a key that doesn't match the route name:

  ```php theme={null}
  'custom_endpoints' => [
      'apps.rotate' => [...],  // Route is named 'api-apps.rotate'
  ],
  ```

  The custom documentation won't be applied. Always use the exact route name:

  ```bash theme={null}
  php artisan route:list --name=rotate
  # api-apps.rotate | POST | api-apps/{app}/rotate
  ```
</Warning>

***

## Scenario 4: Template-Driven CRUD Documentation

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

### Setup

<Steps>
  <Step title="Publish templates">
    ```bash theme={null}
    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`
  </Step>

  <Step title="Enable template system">
    In `config/openapi-templates.php`:

    ```php theme={null}
    return [
        'enabled' => true,
        
        'generic_templates' => [
            'list' => 'list.json',
            'show' => 'show.json',
            'create' => 'create.json',
            'update' => 'update.json',
            'delete' => 'delete.json',
        ],
    ];
    ```
  </Step>

  <Step title="Customize templates">
    Edit `resources/openapi/templates/generic/list.json`:

    ```json theme={null}
    {
      "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')"
        }
      ]
    }
    ```
  </Step>
</Steps>

### Execution

Generate documentation:

```bash theme={null}
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

<Warning>
  **JSON templates not found**

  If template files are missing or paths are wrong:

  ```text theme={null}
  ❌ Failed to load template: resources/openapi/templates/generic/list.json
  ```

  **Solution**: Verify template paths in `config/openapi-templates.php` match actual file locations.
</Warning>

<Warning>
  **Invalid JSON syntax**

  Invalid JSON in templates causes parsing errors:

  ```json theme={null}
  {
    "summary": "List {{entity_plural}}",  // Missing closing brace
  ```

  **Solution**: Validate JSON using [jsonlint.com](https://jsonlint.com) or your IDE.
</Warning>

***

## 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`:

```php theme={null}
'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

<Tabs>
  <Tab title="Generate All Environments">
    ```bash theme={null}
    php artisan openapi:generate --with-postman
    ```

    Creates:

    * `postman-all.json` - Main collection
    * `postman-env-artisan.json`
    * `postman-env-local.json`
    * `postman-env-production.json`
  </Tab>

  <Tab title="Specific Environment">
    ```bash theme={null}
    php artisan openapi:generate --with-postman --environment=production
    ```

    Still generates all three environment files, but the main collection embeds production variables.
  </Tab>
</Tabs>

### Import to Postman

<Steps>
  <Step title="Import collection">
    1. Open Postman
    2. Click **File > Import**
    3. Select `postman-all.json`
  </Step>

  <Step title="Import environments">
    1. Click **Environments** in left sidebar
    2. Click **Import**
    3. Select all `postman-env-*.json` files
  </Step>

  <Step title="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
  </Step>
</Steps>

### 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

<Warning>
  **Defining tracking variables in sub-environments**

  Don't repeat tracking variables in each sub-environment:

  ```php theme={null}
  // ❌ 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.
</Warning>

***

## Scenario 6: CI/CD Pipeline Integration

**Goal**: Automatically generate and publish documentation on every deployment.

### GitHub Actions Example

```yaml theme={null}
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

```yaml theme={null}
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

<Steps>
  <Step title="Developer adds new endpoint">
    Backend developer creates a new route with FormRequest validation:

    ```php theme={null}
    Route::post('products', [ProductController::class, 'store'])
        ->name('products.store');
    ```

    ```php theme={null}
    class StoreProductRequest extends FormRequest
    {
        public function rules()
        {
            return [
                'name' => 'required|string|max:255',
                'price' => 'required|numeric|min:0',
                'category_id' => 'required|exists:categories,id',
            ];
        }
    }
    ```
  </Step>

  <Step title="Generate documentation locally">
    ```bash theme={null}
    php artisan openapi:generate --with-postman
    ```

    Developer reviews the generated docs to ensure accuracy.
  </Step>

  <Step title="Commit generated files">
    Add documentation files to version control:

    ```bash theme={null}
    git add storage/app/public/openapi/
    git commit -m "Add product creation endpoint"
    git push origin feature/add-products
    ```
  </Step>

  <Step title="CI/CD publishes docs">
    On merge to main, CI pipeline generates and publishes docs to a shared location:

    ```bash theme={null}
    https://docs.example.com/api/openapi.json
    https://docs.example.com/api/postman-all.json
    ```
  </Step>

  <Step title="Frontend/mobile teams consume docs">
    Teams import the latest Postman collection or view the OpenAPI spec in Swagger UI.
  </Step>
</Steps>

### Best Practices

<Tip>
  **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
</Tip>

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Edge Cases" icon="triangle-exclamation" href="/guides/edge-cases">
    Learn how to handle config caching issues, concurrent generation, large route sets, and multi-tenant deployments.
  </Card>

  <Card title="API Reference" icon="code" href="/api-reference/public-api">
    Explore the programmatic API for advanced integration scenarios.
  </Card>
</CardGroup>
