Markdown API testing that runs
How runnable Markdown API specs turn request examples into executable contracts, local UI screens, CI checks, and coding-agent context.
Markdown API testing sounds almost too simple: write the request in Markdown, write the expected response under it, and run the file.
The useful part is not that the file is Markdown. The useful part is that Markdown is the artifact developers already accept in docs, pull requests, and code review. If that same artifact can execute, API examples stop being passive documentation and start catching drift.

A README example is not an API test
Most API docs start with a request example like this:
curl http://localhost:8080/users/123
That example helps once. Then the implementation changes, the example goes stale, and nobody notices until a customer, teammate, or coding agent copies it into a task.
A runnable Markdown API spec keeps the example and the contract together:
# Get user by id
Fetches a single user record by stable user identifier.
## Request
```http
GET {{baseUrl}}/users/:userId
Accept: application/json
```
## Expected response
```http
HTTP/1.1 200 OK
Content-Type: application/json
{
"id": "{{userId}}",
"email": "ada@example.test"
}
```
## Assertions
- status: 200
- body.id: exists
- body.email: contains @
Now the file is still readable in a browser or pull request, but it can also run:
rqb exec api-docs/apis/users/get-user-by-id.md
The contract has five jobs
A good Markdown API test should do five jobs without becoming hard to read.
| Section | Job |
|---|---|
| Title and intro | Explain why the endpoint exists. |
## Request | Provide the exact method, URL, headers, and body. |
## Expected response | Define the status and stable response shape. |
## Assertions | Make the success criteria machine-readable. |
## Notes or ## Tests | Give humans and agents the edge cases worth checking. |
This makes the file useful across roles:
- Backend developers can run it while changing handlers.
- Reviewers can inspect it in a pull request.
- CI can execute it as a smoke test.
- Coding agents can read it before editing code.
- New contributors can learn the endpoint without opening a hosted workspace.
Use variables, not hardcoded environments
Markdown API testing becomes reliable when environment details are separated from the spec.
# api-docs/_shared/env.md
## dev
```yaml
baseUrl: http://localhost:8080
userId: usr_demo_123
```
The endpoint can now reference {{baseUrl}} and :userId without hardcoding local URLs into every file:
GET {{baseUrl}}/users/:userId
Secrets stay out of committed Markdown. Put tokens in .env.local, CI secrets, or RQB_* environment variables.
Keep assertions small and stable
The mistake with early API tests is asserting too much. If you assert every field in a large response, the test fails on unrelated metadata changes. If you assert only status == 200, the test catches almost nothing.
Start with stable assertions:
## Assertions
- status: 201
- body.id: exists
- body.status: in [pending_verification, active]
- headers.content-type: contains application/json
That says what must be true without pretending the whole response will never change.
If your team needs stricter contracts, the next product priority in Reqbook is explicit response match modes: shape, strict, and schema. That will let teams choose forgiving documentation checks for early specs and strict JSON/schema checks for critical endpoints.
Run the same Markdown in four places
Once the contract is in api-docs/, the same file supports multiple workflows:
# Catch malformed specs before commit
rqb validate api-docs/
# Execute one endpoint
rqb exec api-docs/apis/users/get-user-by-id.md
# Run a business flow
rqb flow api-docs/flows/signup-login-profile.md
# Open a local browser UI
rqb serve
For local demos and frontend work, recorded expected responses can become a mock API:
rqb mock api-docs --port 4001
That is especially useful for checkout, onboarding, billing, and other flows where frontend or agent work needs a predictable API shape.
How this fits beside Hurl
Hurl is excellent when you want a compact command-line HTTP test runner with plain-text files, captures, assertions, and reports. If your primary need is terse HTTP testing in CI, Hurl is a strong choice.
Reqbook aims at a different center: documentation-first API contracts. The file should be comfortable for a developer to read in a pull request and helpful for an agent to use as context before changing source code.
In practice:
- Use Hurl when the test is the product.
- Use Reqbook when the docs, test, PR review, and agent context should be one artifact.
A CI workflow that keeps docs honest
Use validation in every pull request:
- name: Validate Markdown API specs
run: rqb validate api-docs/
When the backend can run in CI, execute the important flows:
- name: Run onboarding API flow
run: rqb flow api-docs/flows/signup-login-profile.md --env ci
That makes stale examples visible. If a route changes from 201 to 200, or a response field disappears, the contract has to be updated in the same PR as the code.
Start with one useful journey
Do not convert every endpoint on day one. Pick one journey that matters:
- signup -> login -> current profile,
- create cart -> add item -> checkout session,
- create issue -> add comment -> close issue,
- create workspace -> invite member -> list members.
Create the endpoint specs, add one flow, run rqb validate, then open rqb serve beside your editor. Once the first journey works, expand from there.
Update contracts when behavior changes
A runnable Markdown API spec should change in the same pull request as the API behavior. If an endpoint intentionally returns a new status code, adds a required field, or removes a response property, update the ## Expected response block and assertions with the implementation.
That is the discipline that makes markdown API testing useful for SEO, docs, agents, and CI at the same time. The article people read is the same artifact the command runs. When the behavior changes, the documentation and test history change with it.
For agent-specific workflows, read API testing for coding agents. For positioning against GUI-first API workflows, read A local-first API workspace for agent workflows or jump to the comparison section.