Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.markapidown.net/llms.txt

Use this file to discover all available pages before exploring further.

Real API workflows rarely involve a single request. You fetch a resource, capture its ID, pass that ID to a second call, validate the result, and so on. MarkApiDown flow pipelines let you describe these multi-step sequences as a single markdown file in api-docs/flows/. Each step references an existing endpoint spec, captures values from the response, and injects them into later steps — all without writing a line of scripting code.

File location

Place pipeline files under api-docs/flows/ (or api-docs/pipelines/ — both directories are recognized):
api-docs/
└── flows/
    ├── post-with-author.md
    ├── checkout.md
    └── user-onboarding.md
MarkApiDown automatically treats files in flows/ or pipelines/ directories as pipeline specs, not endpoint specs. The mad validate command checks both kinds.

Pipeline frontmatter fields

A pipeline file opens with a YAML frontmatter block, just like an endpoint spec. The key difference is type: pipeline.
type
string
required
Must be pipeline. Tells MarkApiDown to parse this file as a flow rather than a single endpoint spec.
name
string
required
A machine-friendly identifier for the pipeline, used in CLI output and the browser UI (e.g. post-with-author, checkout-flow).
description
string
A human-readable sentence describing what the pipeline does. Shown in the browser UI and in mad flow console output.
continue-on-error
boolean
When true, MarkApiDown runs all remaining steps even if an earlier step fails an assertion or returns an unexpected status. Defaults to false.
parallel
boolean
When true, MarkApiDown executes all steps concurrently instead of sequentially. Use this for independent steps where order does not matter. Defaults to false.

Annotated pipeline example

The following pipeline is taken directly from the JSONPlaceholder example project. It fetches a post, captures userId from the response body, and then fetches the author using that captured value:
---
type: pipeline
name: post-with-author
description: Fetch a post and then fetch its author using the captured userId.
continue-on-error: false
parallel: false
---
# Post with author

Demonstrates a two-step pipeline with variable capture. Fetches post 1,
captures the `userId` from the response body, then fetches that user's
full record.

## Steps

1. **Get post** -> `posts/get-post-by-id.md`
   - Capture: `response.body.userId` as `userId`
2. **Get author** -> `users/get-user-by-id.md`
   - Inject: `userId`
   - Assert: `response.status == 200`

Steps format

Define steps as a numbered list under ## Steps. Each step entry includes:
  • A label — a bold name for the step, displayed in CLI output and the flow canvas.
  • A spec path — the path to the endpoint spec file, relative to the flows/ directory’s parent (api-docs/). Written after ->.
  • Capture, Inject, and Assert sub-items — indented bullet points that describe how to wire values between steps.
## Steps

1. **Create user** -> `users/create-user.md`
   - Capture: `response.body.id` as `userId`
   - Capture: `response.headers.Location` as `userLocation`
2. **Get created user** -> `users/get-user-by-id.md`
   - Inject: `userId`
   - Assert: `response.status == 200`
3. **Delete user** -> `users/delete-user.md`
   - Inject: `userId`
   - Assert: `response.status == 204`

Capture syntax

The Capture directive extracts a value from a step’s response and stores it as a named variable for downstream steps. Use dot-notation and bracket-notation to navigate the response:
Capture expressionWhat it extracts
response.body.idThe id field of a JSON object body
response.body[0].idThe id field of the first item in a JSON array body
response.body.data.tokenA nested field at body.data.token
response.headers.LocationThe Location response header
Write captures as:
- Capture: `response.body.id` as `resourceId`
- Capture: `response.body[0].userId` as `firstUserId`
- Capture: `response.headers.Location` as `createdUrl`
The captured variable name (e.g. resourceId) becomes available to every subsequent step as if it were defined in env.md.

Running a pipeline

Use mad flow and pass the pipeline file path along with the target environment:
mad flow api-docs/flows/post-with-author.md --env=dev
Pass --var to inject additional variables for this run:
mad flow api-docs/flows/checkout.md --env=staging --var userId=42
Override the output format for CI:
mad flow api-docs/flows/checkout.md --env=staging --output=junit

Running steps in parallel

Override the parallel frontmatter setting at runtime with the --parallel flag:
mad flow api-docs/flows/health-checks.md --env=prod --parallel
Force sequential execution even when the file says parallel: true:
mad flow api-docs/flows/health-checks.md --env=prod --no-parallel
Parallel execution is best for independent steps such as health checks or data seeding. Do not run steps in parallel when a later step depends on a value captured from an earlier one — the capture will not be available yet.

Viewing pipelines in the browser

Run mad serve and open the Flows section in the left sidebar. Each pipeline appears as a visual flow canvas where nodes represent steps and edges represent captured values flowing between them.
Use the visual flow canvas in the mad serve browser UI to build pipelines graphically. Drag endpoint spec nodes onto the canvas, connect them with capture arrows, and click Save as markdown — MarkApiDown writes the api-docs/flows/<name>.md file for you, ready to commit to version control.