Request flows
Named request-flow presets — runnable in the UI and via CLI.
DocTreen loads named request-flow presets into the docs UI and runs them through a shared engine — also available as a CLI.
Languages: flows are first-class in all three packages — the same flow
JSON runs in the docs UI and headlessly via doctreen-flow (npm),
doctreen-flow (pip), or vendor/bin/doctreen-flow (Composer). The Python
package additionally runs flows as pytest tests (see below). A flow
written against a service in one language runs unchanged against a service in
another.
Flows are first-class in the UI:
- A top-level Flows tab keeps flows separate from route docs
- The Flows tab includes a built-in guide for writing flow JSON
- The built-in flow creator lets you assemble draft steps from documented routes
- Runtime inputs and per-run
baseUrloverrides are supported {{input.*}},{{vars.*}}, and{{env.*}}placeholders are supported in all step fields- Prior response fields can be promoted into
extractentries and reused as{{vars.*}} - Results are shown as both a visual execution timeline and raw JSON
Directory-based loading
Place *.json files in a ./doctreen-flows directory and they will be loaded
automatically. Use flowsPath for a custom location:
app.use(expressAdapter(app, {
flowsPath: path.join(__dirname, 'doctreen-flows'),
meta: { title: 'My API', version: '1.0.0' },
}));On Laravel the same two keys live in config/doctreen.php — 'flows' for an
inline array of flow definitions, 'flowsPath' for a directory of *.json
files (default: ./doctreen-flows under the project root). The flow JSON
format itself is language-neutral: a flow written against a Node service runs
unchanged against a Laravel one.
Inline flows
app.use(expressAdapter(app, {
flows: [
{
version: 1,
name: 'Login smoke test',
baseUrl: 'http://localhost:3000',
steps: [
{
id: 'login',
request: {
method: 'POST',
path: '/auth/login',
body: { email: 'alice@example.com', password: 'secret' },
},
assert: { status: 200 },
extract: { token: { from: 'body', path: '$.token' } },
},
],
},
],
}));Flow format
{
"version": 1,
"name": "User onboarding",
"description": "Create a user, fetch it back, then delete it.",
"baseUrl": "http://localhost:3000",
"inputs": {
"email": { "type": "string", "required": true },
"name": { "type": "string", "required": true }
},
"steps": [
{
"id": "create-user",
"request": {
"method": "POST",
"path": "/users",
"body": { "email": "{{input.email}}", "name": "{{input.name}}" }
},
"extract": {
"userId": { "from": "body", "path": "$.id" }
},
"assert": {
"status": 201,
"body": { "$.email": "{{input.email}}" }
}
},
{
"id": "get-user",
"request": { "method": "GET", "path": "/users/{{vars.userId}}" },
"assert": {
"status": 200,
"exists": ["$.id", "$.createdAt"]
}
}
]
}Variable namespaces
| Namespace | Source |
|---|---|
{{input.*}} | Runtime values entered in the docs UI or CLI |
{{vars.*}} | Values extracted from previous step responses |
{{env.*}} | Values from the flow file or environment overrides |
CLI runner
# npm & pip: doctreen-flow · PHP: vendor/bin/doctreen-flow — same flags, same flow JSON
doctreen-flow run doctreen-flows/user-onboarding.json \
--input email=alice@example.com \
--input name='Alice Smith'
# Named environment
doctreen-flow run doctreen-flows/user-onboarding.json --env staging
# Explicit environment file + JSON report
doctreen-flow run doctreen-flows/user-onboarding.json \
--env ./doctreen-flows/environments/staging.json \
--report jsonCLI flags:
| Flag | Description |
|---|---|
--env <name|file> | Load an environment preset |
--base-url <url> | Override baseUrl for this run |
--input key=value | Supply runtime inputs |
--no-bail | Continue running after a failed step |
--report text|json | Output format (default: text) |
As pytest tests (Python)
This is the one place the Python package deliberately does more than Node.
Installing doctreen registers a pytest plugin (via entry point — no
conftest.py line to remember): name a flow document *.flow.json and it is
collected and run as a test.
pytest --doctreen-base-url http://localhost:5000 --doctreen-input email=a@b.cA failing flow reports the step that broke and what it expected, not a diff of
two large JSON blobs. In Python an integration test belongs in the test suite —
collected by pytest, reported alongside everything else, failing the build the
same way. The doctreen-flow CLI still exists for flows that are not part
of a test suite: a smoke check after a deploy, a step in a release script.
In CI
doctreen-flow exits non-zero on any step failure or assertion miss, so a
workflow that runs your flows is a single CLI call away. See the
GitHub Actions guide for
production-ready sequential, matrix, and post-deploy gate examples.