DocTreen
Features

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.

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 baseUrl overrides are supported
  • {{input.*}}, {{vars.*}}, and {{env.*}} placeholders are supported in all step fields
  • Prior response fields can be promoted into extract entries 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' },
}));

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

NamespaceSource
{{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

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 json

CLI flags:

FlagDescription
--env <name|file>Load an environment preset
--base-url <url>Override baseUrl for this run
--input key=valueSupply runtime inputs
--no-bailContinue running after a failed step
--report text|jsonOutput format (default: text)

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.

On this page