bhaveshsoni26 / laravel-postman-sync
Automatically scan Laravel API routes and generate a Postman Collection, environment, docs and tests.
Package info
github.com/Bhaveshsoni26/Laravel-Postman-Sync
pkg:composer/bhaveshsoni26/laravel-postman-sync
Requires
- php: >=8.2
- illuminate/console: ^10.0|^11.0|^12.0
- illuminate/http: ^10.0|^11.0|^12.0
- illuminate/routing: ^10.0|^11.0|^12.0
- illuminate/support: ^10.0|^11.0|^12.0
- illuminate/validation: ^10.0|^11.0|^12.0
Requires (Dev)
- laravel/pint: ^1.0
- orchestra/testbench: ^8.0|^9.0|^10.0
- pestphp/pest: ^2.0|^3.0
- phpstan/phpstan: ^1.11
This package is auto-updated.
Last update: 2026-06-20 13:17:13 UTC
README
Turn your Laravel API routes into a complete, importable Postman Collection โ docs, examples, tests, environments, and one-command push โ with zero manual annotations.
๐ Documentation ย ยทย Packagist ย ยทย Issues
php artisan postman:sync
That's it. The package scans every API route, reads your controllers and FormRequest classes, and writes a Postman Collection v2.1 (with embedded docs and test scripts), per-stage environment files, and an OpenAPI document โ then, with --push, syncs it straight to your Postman workspace.
๐ Full documentation, guides and examples: postman-sync.bhaveshdev.in
Why
Keeping a Postman collection in step with a growing API is tedious and always out of date. This package makes the collection a build artifact: re-run one command and your routes, request bodies, auth, examples, docs, and tests regenerate deterministically. Add 10 new endpoints and --push appends just those โ without clobbering the manual edits your team made in Postman.
Features
- ๐ Automatic route scanning โ every
GET/POST/PUT/PATCH/DELETE,apiResource, andresource; derives version, group, controller, and middleware. - ๐งฌ Reflection-based analysis โ finds each controller's
FormRequestand reads itsrules(); no annotations required. - ๐งพ Typed request bodies + examples โ
required|email|min:8|in:โฆ|confirmed|nullable|fileโฆ mapped to types and realistic example values, including nested/wildcard keys. - ๐ Auth detection โ
auth:<guard>โ Bearer{{guard_token}}; collection-level auth with per-request overrides; public routes setnoauth. - ๐ฆ Postman Collection v2.1 โ folder-grouped, fully variable-driven (
{{base_url}},:idpath vars) โ no hardcoded hosts or secrets. - ๐ Docs in Postman โ endpoint summary, field table, and example responses embedded in each request's Docs tab (plus folder/collection descriptions).
- ๐งช Generated test scripts โ status / response-time / JSON assertions, login-token capture into the environment, and validation/CRUD stubs.
- ๐ฑ Environment files โ one per stage (
local/staging/production) with secret-typed guard tokens. - ๐ OpenAPI 3.0.3 โ
openapi.jsongenerated alongside. - ๐ One-command push โ
--pushuploads to the Postman API with incremental merge (append new, regenerate changed, preserve unchanged + manual edits) or--freshfull replace. - ๐ Never breaks your build โ closures, missing FormRequests, and bad controllers degrade gracefully with warnings; exits
0.
Requirements
| PHP | 8.2+ |
| Laravel | 10, 11, or 12 |
Installation
composer require bhaveshsoni26/laravel-postman-sync
The service provider auto-registers via package discovery. Publish the config:
php artisan vendor:publish --tag=postman-sync-config
Not on Packagist yet? Install from a local path repository โ see INSTALLATION.md for the one-time
repositoriessetup.
Quick start
# Generate collection + environments + openapi.json (into storage/app/postman/)
php artisan postman:sync
+---------------------+-------+
| Metric | Value |
+---------------------+-------+
| Routes Found | 164 |
| Requests Generated | 164 |
| Warnings | 0 |
| Files Written | 5 |
+---------------------+-------+
Synced Successfully
Import storage/app/postman/collection.json and an environment file into Postman, fill in the token variables, and send.
What it generates
storage/app/postman/
โโโ collection.json # Postman Collection v2.1 (docs + test scripts embedded)
โโโ openapi.json # OpenAPI 3.0.3
โโโ local.postman_environment.json # one per configured stage
โโโ staging.postman_environment.json
โโโ production.postman_environment.json
Command reference
| Command | Result |
|---|---|
postman:sync |
collection + environments + openapi (default) |
postman:sync --only=collection |
only collection.json |
postman:sync --only=environment |
only the environment file(s) |
postman:sync --only=openapi |
only openapi.json |
postman:sync --docs-files |
also write standalone Markdown to <output>/docs/ |
postman:sync --output=build/postman |
custom output directory |
postman:sync --push |
generate, then merge into the Postman collection |
postman:sync --push --fresh |
full replace of the remote collection |
Push to Postman
POSTMAN_API_KEY=PMAK-xxxx POSTMAN_COLLECTION_ID=xxxx # set to update an existing collection POSTMAN_WORKSPACE_ID=xxxx # optional, used when creating
php artisan postman:sync --push
# Pushed to Postman (merge): added 10, updated 2, unchanged 152, orphaned 0 [12345-abc]
Incremental merge appends new routes, regenerates changed ones, and leaves unchanged requests โ including manual edits to their docs/tests โ untouched. Use --fresh to overwrite the whole collection.
Getting your Postman credentials
You only need the API key to push. The collection ID and workspace ID are optional (see notes below).
1. API key โ POSTMAN_API_KEY (required)
- Sign in to Postman and open go.postman.co/settings/me/api-keys (or: click your avatar, top-right โ Settings โ API keys).
- Click Generate API Key, give it a name (e.g.
laravel-postman-sync), and Generate. - Copy the key โ it starts with
PMAK-โ and put it in.env:POSTMAN_API_KEY=PMAK-xxxxxxxxxxxxxxxxxxxxxxxx
Treat it like a password. You can only see it once; regenerate if you lose it.
2. Collection ID โ POSTMAN_COLLECTION_ID (optional)
Leave this empty the first time โ --push creates a new collection and prints its ID:
Pushed to Postman (create): added 484, ... [12345678-aaaa-bbbb-cccc-1234567890ab]
Copy that ID into .env so future pushes update the same collection instead of creating duplicates:
POSTMAN_COLLECTION_ID=12345678-aaaa-bbbb-cccc-1234567890ab
To target a collection that already exists, fetch its exact API uid (not the short id shown in the app) โ list them with your key:
curl -s -H "X-Api-Key: $POSTMAN_API_KEY" https://api.getpostman.com/collections | json_pp
Use the uid value from the response (looks like 12345678-...).
3. Workspace ID โ POSTMAN_WORKSPACE_ID (optional)
Only used when creating a new collection, to place it in a specific workspace. Omit it to use your default workspace.
- From the app: open the workspace, then look at the browser URL:
https://go.postman.co/workspace/My-Team~<workspace-id>/...โ the ID is the part after the~. - Via the API: list your workspaces and copy the
id:curl -s -H "X-Api-Key: $POSTMAN_API_KEY" https://api.getpostman.com/workspaces | json_pp
POSTMAN_WORKSPACE_ID=abcdef12-3456-7890-abcd-ef1234567890
After editing
.env, runphp artisan config:clearso Laravel picks up the new values, thenphp artisan postman:sync --push.
Configuration
Key options in config/postman-sync.php:
'api_prefix' => 'api', // routes to scan 'output_path' => storage_path('app/postman'), 'base_url' => env('APP_URL').'/api', // seeds {{base_url}} 'default_guard' => 'sanctum', // collection-level auth 'guard_tokens' => [], // guard => token var override 'environments' => ['local', 'staging', 'production'], 'generate_tests' => true, 'capture_login_token' => true, 'postman' => [ 'api_key' => env('POSTMAN_API_KEY'), 'collection_id' => env('POSTMAN_COLLECTION_ID'), 'sync_mode' => 'merge', // merge | replace 'prune_orphans' => false, ],
Full configuration reference and a multi-guard (CRM-style) example are in INSTALLATION.md.
How it works
RouteScanner โโบ RequestAssembler โโบ CollectionBuilder โโ
(ControllerScanner + Validation/Auth/Example/ โโโบ collection.json
Response extractors) โ environment.json
โโบ EnvironmentGenerator โโค openapi.json
โโบ MarkdownGenerator โโโโโค (+ docs in request descriptions)
โโบ OpenApiGenerator โโโโโโค
โโบ TestScriptBuilder โโโโโ
โโบ PostmanSyncService โโบ CollectionMerger โโบ PostmanApiClient (--push)
A one-directional pipeline of immutable DTOs; each stage is interface-backed and independently tested.
Testing
composer test # Pest composer stan # PHPStan level max composer lint # Pint --test
All Postman API calls go through Laravel's Http facade and are mocked with Http::fake() โ the test suite needs no real API key or network.
Contributing
Issues and PRs welcome. Please run composer test && composer stan && composer lint before submitting. New code uses declare(strict_types=1) and Sorbet-style full type hints; tests are written in Pest.
License
MIT.