> ## 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.

# Markdown Endpoint Files

> Write every Reqbook endpoint as a markdown file with YAML frontmatter, an HTTP request block, and an expected response block.

## What is an endpoint file?

An endpoint file is a `.md` file that serves as both documentation and an executable HTTP request. The CLI, web preview, CI, and AI agents all read the same file there is no separate schema, generated client, or runtime artifact.

<CardGroup cols={3}>
  <Card title="Browser UI" icon="desktop">
    The web preview renders the file, lets you run it, and provides runtime-only params, headers, and body overrides.
  </Card>

  <Card title="Coding agents" icon="robot">
    Agent skills use this structure to create specs safely and validate them before reporting back.
  </Card>

  <Card title="Terminal and CI" icon="terminal">
    `rqb exec` and `rqb validate` read the same markdown file for automation.
  </Card>
</CardGroup>

***

## File location and naming

Endpoint files live under `api-docs/apis/<resource>/`. The recommended filename format is `<method-lower>-<slug>.md`.

| HTTP method + path                     | Filename                                     |
| -------------------------------------- | -------------------------------------------- |
| `GET /users/:id`                       | `get-user-by-id.md`                          |
| `POST /orders`                         | `post-orders.md`                             |
| `DELETE /subscriptions/:id`            | `delete-subscription-by-id.md`               |
| `PATCH /orders/:orderId/items/:itemId` | `patch-order-by-order-id-item-by-item-id.md` |

***

## Frontmatter reference

Every endpoint file must begin with YAML frontmatter delimited by `---`.

```yaml filename="api-docs/apis/users/get-user-by-id.md" theme={null}
---
resource: users
protocol: http
method: GET
path: /users/:id
tags: [users, read]
version: 1
env: [dev, staging, prod]
auth: bearer
timeout: 5000
retry:
 attempts: 0
 backoff: fixed
---
```

| Field             | Required | Type         | Description                                                         | Default         |
| ----------------- | -------- | ------------ | ------------------------------------------------------------------- | --------------- |
| `resource`        | yes      | string       | Resource group and folder name                                      |                 |
| `protocol`        | yes      | enum         | `http`, `ws`, or `sse`. Only `http` executes in the current release |                 |
| `method`          | yes      | enum         | `GET` `POST` `PUT` `PATCH` `DELETE` `HEAD` `OPTIONS`                |                 |
| `path`            | yes      | string       | Path with `:param` for path params                                  |                 |
| `tags`            | no       | string\[]    | Searchable labels shown in web preview and reports                  | `[]`            |
| `version`         | yes      | integer      | Spec version (must be `1`)                                          |                 |
| `env`             | no       | string\[]    | Environments where this endpoint is valid. Empty = all              | `[]`            |
| `auth`            | no       | enum         | `none` / `bearer` / `basic` / `custom`                              | project default |
| `timeout`         | no       | integer (ms) | Per-request timeout in milliseconds                                 | `5000`          |
| `retry.attempts`  | no       | integer      | Retry count after failure                                           | `0`             |
| `retry.backoff`   | no       | enum         | `fixed` or `exponential`                                            | `fixed`         |
| `response.match`  | no       | enum         | `shape`, `strict`, or `schema` comparison mode                      | `shape`         |
| `response.ignore` | no       | string\[]    | Strict-mode paths to ignore, such as `body.id`                      | `[]`            |

<Note>
  Unknown frontmatter keys produce a warning and are ignored. This forward-compatible behavior means future Reqbook versions can introduce new fields without breaking existing spec files.
</Note>

***

## The Request block

`## Request` must contain exactly one `http` fenced code block. The first line is the request line; subsequent lines are headers; a blank line separates headers from the optional body.

### Request line forms

```http theme={null}
GET {{baseUrl}}/users/:id
GET /users/:id
POST https://api.example.com/users
```

<Note>
  Relative URLs are resolved against the selected environment's `baseUrl` from `api-docs/_shared/env.md`. Absolute URLs are used as-is.
</Note>

### Full request with headers and body

```http theme={null}
POST {{baseUrl}}/users
Authorization: Bearer {{authToken}}
Content-Type: application/json
Accept: application/json

{
 "email": "{{email}}",
 "name": "{{name}}"
}
```

***

## The Expected response block

`## Expected response` must contain exactly one `http` fenced code block. Reqbook diffs the actual response against this block after every execution.

### Comparison behavior

| Part    | Comparison                                                                      |
| ------- | ------------------------------------------------------------------------------- |
| Status  | Strict equality                                                                 |
| Headers | Subset match listed headers must be present; extra response headers are allowed |
| Body    | JSON shape when both sides are valid JSON; exact string match otherwise         |

Set `response.match: strict` when the JSON/string body must match exactly:

```yaml theme={null}
response:
  match: strict
  ignore: [body.id, headers.x-request-id]
```

Set `response.match: schema` when the actual JSON body should validate against a schema:

````markdown theme={null}
## Schema

```json
{
  "type": "object",
  "required": ["id", "email"],
  "properties": {
    "id": { "type": "string" },
    "email": { "type": "string" }
  }
}
```
````

### Example

```http theme={null}
HTTP/1.1 201 Created
Content-Type: application/json

{
 "id": "usr_123",
 "email": "user@example.com"
}
```

***

## Error responses (optional)

Use `## Error responses` to document representative error contracts such as validation failures, missing auth, not found, or conflict cases.

````markdown theme={null}
## Error responses

```http
HTTP/1.1 404 Not Found
Content-Type: application/json

{
 "error": "not_found",
 "message": "User not found"
}
```
````

<Note>
  the current Reqbook release executes only the single `## Expected response` block. Error responses are reference examples for humans, the web preview source view, and AI agents.
</Note>

***

## The Assertions block (optional)

`## Assertions` contains structured rules that Reqbook evaluates after each execution. Results appear in `rqb_exec` output as `assertion_results`.

```markdown theme={null}
## Assertions
- status: 201
- body.id: exists
- body.email: equals "ada@example.com"
- body.role: in [admin, user]
- headers.content-type: contains application/json
- body.slug: matches ^[a-z-]+$
```

Supported operators:

| Operator   | Example                                    | Description                   |
| ---------- | ------------------------------------------ | ----------------------------- |
| `exists`   | `body.id: exists`                          | Field is present and non-null |
| `equals`   | `status: 201` or `body.name: equals "Ada"` | Exact match                   |
| `contains` | `headers.content-type: contains json`      | Substring match               |
| `in`       | `body.role: in [admin, user]`              | Value is one of a list        |
| `matches`  | `body.slug: matches ^[a-z-]+$`             | Regex match                   |

Paths follow the format `status`, `body.<field>.<nested>`, or `headers.<name>`.

***

## The Tests block (optional)

`## Tests` contains an `agent-task` fenced code block with freeform validation instructions for AI agents. Use this for edge cases that can't be expressed as structured assertions.

````markdown theme={null}
## Tests

```agent-task
- Verify duplicate email returns 409.
- Verify the response time is under 200ms under normal load.
```
````

<Note>
  Reqbook does not execute `agent-task` code. The block is read by AI agents as instructions.
</Note>

***

## Notes section (optional)

`## Notes` is free-form markdown for team context: rate limits, edge cases, links to related endpoints, and migration notes. The Reqbook parser ignores this section entirely.

***

## Complete example

````markdown filename="api-docs/apis/users/get-user-by-id.md" theme={null}
---
resource: users
protocol: http
method: GET
path: /users/:id
tags: [users, read]
version: 1
env: [dev, staging]
auth: bearer
timeout: 5000
retry:
 attempts: 0
 backoff: fixed
---

# Get user by id

Fetch a single user record by stable user identifier.

## Request

```http
GET {{baseUrl}}/users/:id
Authorization: Bearer {{authToken}}
Accept: application/json
```

## Expected response

```http
HTTP/1.1 200 OK
Content-Type: application/json

{
 "id": "usr_123",
 "name": "Ada Lovelace",
 "email": "ada@example.com"
}
```

## Tests

```agent-task
- Verify the response status is 200.
- Verify response.body.id equals the requested id.
- Verify response.body.email is a valid email address.
- Verify Authorization header is masked in all output.
```

## Notes

Use this endpoint after login to fetch the current user's profile.
````

***

## Running an endpoint

Use the UI while developing and the CLI when you need automation.

<Tabs>
  <Tab title="Web UI">
    ```bash theme={null}
    rqb serve
    ```

    Open the endpoint, fill runtime-only params or headers, click Run, and inspect the response panel. The markdown file changes only when you enter edit mode and save.
  </Tab>

  <Tab title="CLI">
    ```bash theme={null}
    # Basic execution
    rqb exec api-docs/apis/users/get-user-by-id.md

    # With environment and variable override
    rqb exec api-docs/apis/users/get-user-by-id.md --env=staging --var id=usr_456

    # Dry run print the resolved request without sending
    rqb exec api-docs/apis/users/get-user-by-id.md --dry-run
    ```
  </Tab>
</Tabs>
