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

FrameworkVersionsGuide
Django REST framework3.12+DRF to Postman
Django3.2 to 6Django to Postman
FastAPI0.95+, Pydantic v1 and v2FastAPI to Postman
Flask2.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.

OptionMeaning
-C, --project DIRProject folder (default: current folder)
-f, --frameworkdjango, flask or fastapi (default: detect)
-a, --appDjango settings module (mysite.settings) or Flask/FastAPI app: main:app, myapp:create_app()
-n, --nameCollection name
-o, --output DIROutput folder (default postman)
-b, --base-url URLBase URL of the local environment
-e, --env NAME=URLAdd an environment, e.g. -e production=https://api.example.com (repeatable)
-x, --exclude REGEXLeave out matching paths, e.g. -x '^/internal/' (repeatable)
--auth TYPEForce auto, none, bearer, token, basic, apikey or session
--login PATHThe POST route whose response contains the token
--env-file FILEKEY=VALUE file loaded before importing the project (default: .env if present)
--stdoutPrint 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-urlencoded or multipart/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_params or args. 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:

DetectedPostman setup
JWT / Bearer (SimpleJWT, flask-jwt-extended, FastAPI OAuth2/HTTPBearer)Bearer token {{access_token}}
DRF TokenAuthentication, KnoxAuthorization: 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 csrftoken cookie. The collection copies it into the X-CSRFToken header for you.
  • Regenerate whenever your API changes. Collection and request ids are stable, so importing again replaces the previous version.
  • Commit routeman.toml and, if you like, the postman/ 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.