FastAPI to Postman: better than importing openapi.json
Importing /openapi.json gives you URLs. Here's how to generate a FastAPI Postman collection with a working OAuth2 login, saved tokens, valid Pydantic examples and environments.
FastAPI gives you an OpenAPI document for free, and Postman can import it. So why use anything else? Because the imported collection is where the work starts: you still have to wire up login, copy tokens, create environments and fix example bodies that fail validation.
This post compares the two approaches on the same app and shows how routeman produces a collection you can use straight away.
The example app
from fastapi import FastAPI, Depends, Query
from fastapi.security import OAuth2PasswordBearer
from pydantic import BaseModel, Field
app = FastAPI(title="Shop API")
oauth = OAuth2PasswordBearer(tokenUrl="/auth/token")
class ProductIn(BaseModel):
name: str = Field(min_length=2, max_length=80)
price: float = Field(gt=0)
sku: str
@app.post("/auth/token", tags=["auth"])
def token(): ...
@app.get("/products", tags=["products"])
def list_products(page: int = 1, search: str | None = Query(None)): ...
@app.post("/products", tags=["products"])
def create_product(p: ProductIn, user=Depends(oauth)): ...
@app.get("/products/{product_id}", tags=["products"])
def get_product(product_id: int, user=Depends(oauth)): ...
Option 1: import openapi.json
Start the server, then in Postman choose Import and paste http://localhost:8000/openapi.json. You get requests grouped by tag, which is a good start. But:
- Login isn't automated. You send the token request, copy
access_tokenfrom the response and paste it into the auth settings by hand, and again every time it expires. - No environments. Switching between local and staging means editing URLs or building environments yourself.
- Hidden routes are missing. Anything with
include_in_schema=False, often internal or admin endpoints, is left out. - No tests. The Collection Runner has nothing to assert.
Option 2: generate with routeman
$ pip install routeman
$ routeman generate -a main:app
✓ fastapi: 4 requests (2 POST, 2 GET)
✓ auth: bearer (login: POST /auth/token)
✓ wrote postman/demo-api.postman_collection.json
✓ wrote postman/demo-api.local.postman_environment.json
done in 0.31s - import the files in Postman (File → Import)
No server needs to run. routeman builds the OpenAPI document in memory and also reads the route table. Here's what it adds:
A login request that saves the token
routeman saw OAuth2PasswordBearer(tokenUrl="/auth/token"), so Auth › Token gets a test script. After you send it, the script searches the response for the token (including nested keys) and runs:
pm.environment.set('access_token', access);
pm.environment.set('refresh_token', refresh);
pm.test('login returned a token', ...)
The collection's auth is Bearer {{access_token}}, and the login request itself is No Auth. Send login once and everything else works.
Bodies that pass Pydantic validation
The generated Create Product body:
{
"name": "John Doe",
"price": 1.5,
"sku": "string"
}
price is 1.5 because of gt=0, so a zero would be rejected with a 422. name fits min_length/max_length and reads like a name. routeman also respects Literal/Enum values, regex patterns and well-known field names such as email.
Query and path parameters
List Products has page=1 and search, added but disabled, so the default request matches the default behaviour. {{product_id}} is an environment variable (default 1) that you set once from a list response.
Environments and smoke tests
The environment holds base_url, secret access_token/refresh_token/password and the path ids. Add more servers with -e staging=https://staging.example.com. Every request carries a "no server error" test, so the Collection Runner flags any 5xx.
Forms, files and headers
Endpoints using Form(...) become x-www-form-urlencoded requests, File()/UploadFile become multipart with a file picker, and Header() parameters are added as request headers. APIKeyHeader security becomes Postman API-key auth on the right header.
Where's my app?
routeman looks for the FastAPI() instance in common locations. Otherwise, point to it:
routeman generate -a app.main:app
routeman generate -a "app.factory:create_app()"
routeman init # remember it in routeman.toml
Summary
| openapi.json import | routeman | |
|---|---|---|
| Needs a running server | Yes (or an exported file) | No |
| Login saves token | No | Yes |
| Hidden routes | No | Yes |
| Environments | No | One per server |
| Smoke tests | No | On every request |
Keep /docs for interactive documentation and use routeman for the Postman collection your team works in every day. More on the FastAPI page.
Try routeman on your project
$ pip install routeman
$ routeman generate