amondar-libs/php-postman

There is no license information available for the latest version (1.0.0) of this package.

Allow to create postman documentation for your API

Maintainers

Package info

github.com/amondar-libs/php-postman

pkg:composer/amondar-libs/php-postman

Statistics

Installs: 0

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

1.0.0 2026-03-18 03:24 UTC

This package is auto-updated.

Last update: 2026-03-18 03:26:18 UTC


README

PHP Version Laravel

A PHP package that generates Postman collections from your application routes. It supports Laravel out of the box and can be extended to work with any PHP framework.

Table of Contents

Installation

Install the package via Composer:

composer require amondar-libs/php-postman

Requirements

  • PHP 8.3 or higher
  • Laravel 10, 11, or 12 (for Laravel integration)

Laravel Auto-Discovery

The package ships with a Laravel service provider that is auto-discovered. No manual registration is needed. The service provider registers route macros (alias, auth, description, additionalHeaders, structureDepth) that you can use directly on your route definitions.

Basic Usage

Laravel Integration

The quickest way to export your Laravel routes to a Postman collection is via the built-in CLI binary:

./vendor/bin/postman export --laravel --base-url=https://api.example.com --output=postman.json

This will bootstrap your Laravel application, parse all registered routes, and write a Postman collection JSON file.

Standalone CLI

For non-Laravel projects, you can provide a custom route parser class:

./vendor/bin/postman export \
    --routes-parser="App\\Documentation\\MyRoutesParser" \
    --base-url=https://api.example.com \
    --output=postman.json

If --routes-parser is not provided and --laravel is not set, the CLI will interactively ask for the parser class name.

Programmatic Usage

You can also generate collections programmatically in your PHP code:

use Amondar\Postman\Export;
use Amondar\Postman\Route\Route;
use Amondar\Postman\Route\RouteCollection;
use Amondar\Postman\Auth\Bearer;

// Build a route collection
$routes = new RouteCollection();
$routes->push(new Route(
    name: 'users.index',
    path: 'api/users',
    methods: ['GET'],
    action: null,
));
$routes->push(new Route(
    name: 'users.store',
    path: 'api/users',
    methods: ['POST'],
    action: null,
));

// Export to JSON
$json = Export::from($routes, 'https://api.example.com')
    ->useDefaultAuth(Bearer::make('your-token'))
    ->toJson('My API Collection');

file_put_contents('postman.json', $json);

Using with Laravel Routes Parser

use Amondar\Postman\Export;
use Amondar\Postman\Laravel\LaravelRoutesParser;

$parser = new LaravelRoutesParser();
$routes = $parser->parseLaravelRoutes(app('router')->getRoutes());

$json = Export::from($routes, config('app.url'))
    ->toJson('My Laravel API');

Deep Dive

Authentication

The package supports multiple authentication types that map directly to Postman's authentication options. Set a default auth for the entire collection or assign auth per route.

Bearer Token

use Amondar\Postman\Auth\Bearer;

$export = Export::from($routes, $baseUrl)
    ->useDefaultAuth(Bearer::make('optional-default-token'));

Basic Auth

use Amondar\Postman\Auth\Basic;

$export = Export::from($routes, $baseUrl)
    ->useDefaultAuth(Basic::make('username', 'password'));

OAuth 2.0 — Password Grant

use Amondar\Postman\Auth\OAuthPassword;

$export = Export::from($routes, $baseUrl)
    ->useDefaultAuth(new OAuthPassword(
        clientId: 'your-client-id',
        clientSecret: 'your-client-secret',
        scope: 'read write',
    ))
    ->useOAuthTokenPath('/oauth/token');

OAuth 2.0 — Client Credentials

use Amondar\Postman\Auth\OAuthClientCredentials;

$export = Export::from($routes, $baseUrl)
    ->useDefaultAuth(new OAuthClientCredentials(
        clientId: 'your-client-id',
        clientSecret: 'your-client-secret',
        scope: 'read write',
    ))
    ->useOAuthTokenPath('/oauth/token');

OAuth 2.0 — Authorization Code with PKCE

use Amondar\Postman\Auth\OAuthCodeWithPKCE;

$export = Export::from($routes, $baseUrl)
    ->useDefaultAuth(new OAuthCodeWithPKCE(
        clientId: 'your-client-id',
        callbackUrl: 'https://app.example.com/callback',
        authUrl: 'https://auth.example.com/authorize',
        scope: 'openid profile',
    ))
    ->useOAuthTokenPath('/oauth/token');

No Authentication

use Amondar\Postman\Auth\None;

// This is the default — routes with no auth assigned will use None
$export = Export::from($routes, $baseUrl)
    ->useDefaultAuth(new None());

Per-Route Authentication (Laravel)

When using Laravel, you can set authentication on individual routes or route groups:

use Amondar\Postman\Auth\Bearer;
use Amondar\Postman\Auth\Basic;

// Single route
Route::get('/api/users', [UserController::class, 'index'])
    ->name('users.index')
    ->auth(Bearer::make());

// Route group
Route::auth(Basic::make())->group(function () {
    Route::get('/admin/dashboard', [AdminController::class, 'dashboard'])
        ->name('admin.dashboard');
});

Route Macros (Laravel)

The service provider registers several macros on Laravel's Route, RouteRegistrar, and Router classes:

alias(string $alias)

Override the display name of a route in the Postman collection:

Route::get('/api/v2/users', [UserController::class, 'index'])
    ->name('api.v2.users.index')
    ->alias('List All Users');

description(Stringable|string $description)

Add a description to the route. Accepts a plain string, a \Stringable instance, or a class name that implements Stringable:

Route::get('/api/users', [UserController::class, 'index'])
    ->name('users.index')
    ->description('Returns a paginated list of all users.');

structureDepth(int $depth)

Control how deeply the route name is used for folder nesting in the Postman collection. By default, all segments except the last one are used as folder names:

// Route name: "api.v2.users.index"
// Default folders: api > v2 > users
// With structureDepth(0): api
// With structureDepth(1): api > v2
Route::get('/api/v2/users', [UserController::class, 'index'])
    ->name('api.v2.users.index')
    ->structureDepth(2);

auth(AuthenticationContract $type)

Set the authentication type for a route or route group (see Authentication).

additionalHeaders(array $headers)

Add custom headers to the Postman request:

Route::get('/api/users', [UserController::class, 'index'])
    ->name('users.index')
    ->additionalHeaders([
        ['key' => 'X-Custom-Header', 'value' => 'custom-value', 'type' => 'text'],
        ['key' => 'Accept-Language', 'value' => 'en', 'type' => 'text'],
    ]);

Route Filtering

Filter which routes are included in the exported collection. Filtering is available both via CLI options and programmatically.

CLI Filtering

# Filter by path pattern
./vendor/bin/postman export --laravel --route-paths="api/*"

# Filter by route name
./vendor/bin/postman export --laravel --route-names="users.*"

# Filter by HTTP method. Case-insensitive.
./vendor/bin/postman export --laravel --route-methods="GET;POST"

# Filter by middleware
./vendor/bin/postman export --laravel --route-middlewares="auth:*"

# Combine multiple filters (all conditions must match)
./vendor/bin/postman export --laravel \
    --route-paths="api/*" \
    --route-methods="GET" \
    --route-middlewares="auth"

Multiple values can be separated by semicolons or passed as repeated options.

Programmatic Filtering

use Amondar\Postman\Route\RouteFilter;

$filter = RouteFilter::apply()
    ->byPath('api/*')
    ->byMethod(['GET', 'POST'])
    ->byName('users.*')
    ->byMiddleware('auth');

$filteredRoutes = $routes->filterRoutes($filter)->values();

$json = Export::from($filteredRoutes, $baseUrl)->toJson();

Form Data Attributes

Use the #[PostmanFormData] attribute to define request body data for your routes. The attribute can be applied to controller classes or methods and accepts either an inline array or a class implementing Renderable.

Inline Array

use Amondar\Postman\Attributes\PostmanFormData;

class UserController
{
    #[PostmanFormData([
        'name' => 'John Doe',
        'email' => 'john@example.com'
    ])]
    public function store(Request $request)
    {
        // ...
    }
}

Using a Renderable Class

use Amondar\Postman\Attributes\PostmanFormData;
use Amondar\Postman\Contracts\Renderable;

class StoreUserFormData implements Renderable
{
    public function render(): array
    {
        // There can be complex logic to generate form data.
        // Also, you can use faker here.
        return [
            'name'  => 'John Doe',
            'email' => 'john@example.com',
            'role'  => 'admin',
        ];
    }
}

class UserController
{
    #[PostmanFormData(StoreUserFormData::class)]
    public function store(Request $request)
    {
        // ...
    }
}

To enable attribute scanning, specify the directories to scan using parseDataIn():

$json = Export::from($routes, $baseUrl)
    ->parseDataIn('app/Http/Controllers', 'app/Http/Requests')
    ->toJson();

Or via CLI:

./vendor/bin/postman export --laravel --attributes-in=app/Domain --attributes-in=app/Infrastructure

Descriptions

Route descriptions support both plain strings and Stringable objects. This allows integration with markdown libraries or any custom description generator:

use Amondar\Postman\Contracts\Renderable;

// Plain string
Route::get('/api/users', [UserController::class, 'index'])
    ->description('Returns a list of users.');

// Stringable class (e.g., from amondar-libs/php-markdown)
Route::get('/api/users', [UserController::class, 'index'])
    ->description(Markdown::line('Returns a **list** of users.'));

// Class name that implements Stringable — will be instantiated automatically
Route::get('/api/users', [UserController::class, 'index'])
    ->description(UserIndexDescription::class);

CLI Options Reference

Option Alias Description
--laravel Bootstrap and parse a Laravel application
--routes-parser -parser Fully qualified class name of a custom route parser
--attributes-in -attributes Directories to scan for PostmanFormData attributes (repeatable)
--collection-name -name Name of the Postman collection (default: postman.json)
--collection-description -description Description of the Postman collection
--base-url -url Base URL for requests, stored as {{base_url}} variable
--oauth-token-url -oauth-url OAuth token endpoint, stored as {{oauth_full_url}} variable
--route-paths -paths Filter routes by path patterns (semicolon-separated)
--route-names -names Filter routes by name patterns (semicolon-separated)
--route-methods -methods Filter routes by HTTP methods (semicolon-separated)
--route-middlewares -middlewares Filter routes by middleware (semicolon-separated)
--output File path to write the collection to (prints to stdout if omitted)
--format Output format: json (default) or pretty-json

Extending the Package

Custom Route Parser

To support frameworks other than Laravel, implement the RouteParserContract interface:

use Amondar\Postman\Contracts\RouteParserContract;
use Amondar\Postman\Route\Route;
use Amondar\Postman\Route\RouteCollection;

class SymfonyRoutesParser implements RouteParserContract
{
    public function parse(string $rootPath): RouteCollection
    {
        $collection = new RouteCollection();

        // Parse your framework's routes and convert them
        foreach ($this->getSymfonyRoutes($rootPath) as $sfRoute) {
            $collection->push(new Route(
                name: $sfRoute->getName(),
                path: $sfRoute->getPath(),
                methods: $sfRoute->getMethods(),
                action: null, // or create a RouteAction if applicable
                middleware: [],
            ));
        }

        return $collection;
    }
}

Use it via CLI:

./vendor/bin/postman export \
    --routes-parser="App\\Documentation\\SymfonyRoutesParser" \
    --base-url=https://api.example.com

Or programmatically:

$parser = new SymfonyRoutesParser();
$routes = $parser->parse('/path/to/project/can/be/ignored');

$json = Export::from($routes, 'https://api.example.com')->toJson();

Custom Authentication

Create your own authentication type by implementing the AuthenticationContract interface:

use Amondar\Postman\Contracts\AuthenticationContract;

class ApiKeyAuth implements AuthenticationContract
{
    public function __construct(
        public readonly string $headerName = 'X-API-Key',
        public readonly ?string $value = null,
    ) {}

    public function toArray(): array
    {
        return [
            'type'   => 'apikey',
            'apikey' => [
                [
                    'key'   => 'key',
                    'value' => $this->headerName,
                    'type'  => 'string',
                ],
                [
                    'key'   => 'value',
                    'value' => $this->value ?? '',
                    'type'  => 'string',
                ],
                [
                    'key'   => 'in',
                    'value' => 'header',
                    'type'  => 'string',
                ],
            ],
        ];
    }
}

Then use it as default auth or per-route:

$export = Export::from($routes, $baseUrl)
    ->useDefaultAuth(new ApiKeyAuth('X-API-Key', 'secret'));

// Or in Laravel routes:
Route::get('/api/data', [DataController::class, 'index'])
    ->auth(new ApiKeyAuth());

Custom Form Data Renderable

Implement the Renderable interface to create reusable form data definitions:

use Amondar\Postman\Contracts\Renderable;

class PaginationFormData implements Renderable
{
    public function render(): array
    {
        return [
            'page' => 1,
            'per_page' => 15,
            'sort_by' => 'created_at',
            'sort_order' => 'desc',
        ];
    }
}

Then reference it in the PostmanFormData attribute:

use Amondar\Postman\Attributes\PostmanFormData;

class UserController
{
    #[PostmanFormData(PaginationFormData::class)]
    public function index()
    {
        // ...
    }
}

License

Please see LICENSE.md for details.