routeman documentation
Everything you need to generate, configure and automate Postman collections from Django, Django REST framework, Flask and FastAPI projects. These docs are for routeman 0.1.0.
Quick start
Install routeman into the same virtualenv your project runs in, because routeman imports your application to read its routes. Then run it from the project folder:
$ pip install routeman
$ cd your-project
$ routeman generate
✓ django: 24 requests (11 GET, 9 POST, 2 PUT, 1 PATCH, 1 DELETE), 1 websocket(s)
✓ auth: bearer (login: POST /api/v1/auth/token/)
✓ wrote postman/your-project-api.postman_collection.json
✓ wrote postman/your-project-api.local.postman_environment.json
done in 0.26s - import the files in Postman (File → Import)
Open Postman, choose File → Import and drop both files. Select the local environment in the top-right corner, fill in username and password, and run the Login request. Every other request now sends the saved token.
Installation
routeman supports Python 3.9 and newer. It has no dependencies, except tomli on Python 3.9 and 3.10 for reading TOML.
pip install routeman # pip
uv pip install routeman # uv
poetry add --group dev routeman
pipenv install --dev routeman
Check the install with routeman --version. It is a development tool, so a dev dependency group is the natural place for it.
Why the same virtualenv? routeman imports your project the same way manage.py, gunicorn or uvicorn does, so Django, Flask, FastAPI and your own packages must be importable. Importing is read-only: routeman never connects to your database, runs migrations or sends HTTP requests.
Supported frameworks
| Framework | Versions | Guide |
|---|---|---|
| Django REST framework | 3.12+ | DRF to Postman |
| Django | 3.2 to 6 | Django to Postman |
| FastAPI | 0.95+, Pydantic v1 and v2 | FastAPI to Postman |
| Flask | 2.0 to 3.x (blueprints, MethodView, Flask-RESTful, flask-smorest) | Flask to Postman |
Commands
routeman generate # write postman/<name>.postman_collection.json + environments
routeman generate --stdout # print the collection instead
routeman routes # list what routeman found (method, path, auth, body fields)
routeman init # save the project details in routeman.toml (asks a few questions)
routeman --version
generate can be shortened to gen and routes to ls. Run routeman routes first if you want to see what will be generated. A lock icon marks endpoints that need authentication:
$ routeman routes
POST /auth/token
GET /products
POST /products 🔒 json: name, price, sku
GET /products/{product_id} 🔒
4 routes, auth: bearer
Options
Every option is optional. routeman detects everything it can, and you only override what it gets wrong or can't guess.
| Option | Meaning |
|---|---|
-C, --project DIR | Project folder (default: current folder) |
-f, --framework | django, flask or fastapi (default: detect) |
-a, --app | Django settings module (mysite.settings) or Flask/FastAPI app: main:app, myapp:create_app() |
-n, --name | Collection name |
-o, --output DIR | Output folder (default postman) |
-b, --base-url URL | Base URL of the local environment |
-e, --env NAME=URL | Add an environment, e.g. -e production=https://api.example.com (repeatable) |
-x, --exclude REGEX | Leave out matching paths, e.g. -x '^/internal/' (repeatable) |
--auth TYPE | Force auto, none, bearer, token, basic, apikey or session |
--login PATH | The POST route whose response contains the token |
--env-file FILE | KEY=VALUE file loaded before importing the project (default: .env if present) |
--stdout | Print the collection instead of writing files |
Examples:
# FastAPI app in app/main.py, collection named "Billing API"
routeman generate -a app.main:app -n "Billing API"
# Flask application factory
routeman generate -a "myapp:create_app()"
# Django project with a non-default settings module and two extra servers
routeman generate -a config.settings.local \
-e staging=https://staging.example.com \
-e production=https://api.example.com
# Leave out internal and health-check routes
routeman generate -x '^/internal/' -x '^/health'
Configuration file (routeman.toml)
routeman init asks a few questions and writes routeman.toml, so the whole team and CI get the same output from a bare routeman generate. You can also put the same table under [tool.routeman] in pyproject.toml.
[routeman]
name = "Shop API"
framework = "django"
app = "shop.settings" # Flask/FastAPI: "main:app" or "factory:create_app()"
output = "postman"
exclude = ["^/internal/"]
[routeman.environments]
local = "http://localhost:8000"
production = "https://api.example.com"
[routeman.auth]
type = "auto" # auto | none | bearer | token | basic | apikey | session
login = "/api/token/" # optional: detected automatically
# prefix = "JWT" # Authorization: JWT <token>
# header = "X-API-Key" # header for apikey auth
Command-line options override the file.
What the collection contains
- Folders: one per Django app, Flask blueprint or FastAPI tag, with sub-folders per resource.
- Requests: every URL and HTTP method the framework would serve, including nested
include()s, routers, blueprints and mounted routers. Admin and static routes are skipped. - Bodies: JSON,
x-www-form-urlencodedormultipart/form-data, with file uploads turned into Postman file pickers. Example values pass validation: they respect choices, min/max, lengths and regex patterns, and use field names (email→user@example.com). - Path variables:
{{product_id}},{{user_id}}… named after the resource, typed from the model (UUID or integer) and stored in the environment. - Query parameters: pagination, search, ordering, filters and anything your code reads from
request.GET,query_paramsorargs. Optional ones are present but disabled. - Auth: set once at collection level. Public endpoints are set to No Auth.
- Tests: every request checks
pm.response.code < 500, and the login request checks that a token came back. - Descriptions: the view docstring and a field table (type, required, allowed values). WebSocket routes (Django Channels, FastAPI) are listed in the collection description.
The format is Postman Collection v2.1, which Postman, Newman, Insomnia, Bruno, Hoppscotch and most other API clients can import.
Authentication and the login script
routeman finds the auth scheme in your code and configures the collection for it:
| Detected | Postman setup |
|---|---|
| JWT / Bearer (SimpleJWT, flask-jwt-extended, FastAPI OAuth2/HTTPBearer) | Bearer token {{access_token}} |
DRF TokenAuthentication, Knox | Authorization: Token {{access_token}} |
| Basic (incl. Flask-HTTPAuth) | Basic auth with {{username}} / {{password}} |
API key (FastAPI APIKeyHeader, custom header) | API key header |
| Session (Django login, Flask-Login) | Cookies, with csrftoken copied into X-CSRFToken |
The login (token) request gets a test script that finds the token in the response, even when it is nested, and stores it. Common key names are recognised: access_token, access, token, jwt, key, id_token, plus camelCase variants. Refresh endpoints send {{refresh_token}}.
If detection picks the wrong route, use --login /api/v1/auth/login/. To use a custom prefix such as Authorization: JWT <token>, set prefix = "JWT" under [routeman.auth].
Environments
routeman writes one Postman environment file per server. Each one holds base_url, the token variables (marked secret), username/password and one variable per path id. Add servers with -e NAME=URL or [routeman.environments], then switch between them in Postman's environment picker.
Running in CI with Newman
Because every request carries a "no server error" test, the generated collection is an instant smoke test. A typical GitHub Actions or GitLab CI job:
pip install -r requirements.txt routeman
routeman generate -b http://localhost:8000
python manage.py runserver 0.0.0.0:8000 & # or: uvicorn main:app / flask run
npx newman run postman/*.postman_collection.json \
-e postman/*.local.postman_environment.json
See Smoke-test a Python API in CI with Newman for a complete pipeline.
Tips
- Run Login first. The token is stored and sent with every other request.
- Set the
{{…_id}}variables in the environment from list responses, or edit them per request. - Django form views (session/CSRF): send any GET first so Postman receives the
csrftokencookie. The collection copies it into theX-CSRFTokenheader for you. - Regenerate whenever your API changes. Collection and request ids are stable, so importing again replaces the previous version.
- Commit
routeman.tomland, if you like, thepostman/folder, so collection changes show up in code review.
Troubleshooting
"Could not detect the framework / app"
Pass it explicitly: -f fastapi -a app.main:app, or -a mysite.settings for Django. Run routeman init once to save it.
ImportError or missing settings when loading the project
Activate the project's virtualenv first. If your settings read environment variables, keep them in .env (loaded automatically) or pass --env-file.
A request body is empty or incomplete
Run routeman routes to see the fields routeman found. Declaring a serializer, form, marshmallow schema or Pydantic model on the view gives the most complete result. Without one, routeman reads the view's source code and marks the fields as inferred.
The wrong login route was picked
Use --login /your/token/path/ or set login under [routeman.auth].
Still stuck? Email routeman@swastik.ai with your framework and version and the output of routeman routes.