# REST API Testing Guide (Project Template)

Copy this file into your project and edit it to match your project-specific commands and requests.

Suggested destination:

- `docs/backend/rest-api-guide.md`

Copy command:

```bash
cp "$AGENT_HOME/skills/tools/testing/api-test-runner/references/REST_API_TESTING_GUIDE.md" \
  "docs/backend/rest-api-guide.md"
```

## Purpose

This guide documents how to run manual API tests for a REST server and how to record results as a markdown report.

## Recommended tools

- CLI (repeatable calls): `api-rest` (install via `brew install nils-cli`), plus `jq` for formatting and assertions.
- GUI clients (optional): Insomnia / Postman / Bruno (good for saved environments + collections).

## Project setup (per repo)

Store project-specific, non-secret templates under `setup/rest/`:

- `setup/rest/endpoints.env` (commit this)
- `setup/rest/tokens.env` (commit this; placeholders only)
- `setup/rest/prompt.md` (commit this; optional project context for LLMs)
- `setup/rest/requests/*.request.json` (commit these, but keep secrets out)

Optional local-only overrides:

- `setup/rest/endpoints.local.env` (do not commit; recommended to gitignore)
- `setup/rest/tokens.local.env` (do not commit; real tokens)
- `setup/rest/requests/*.local.json` (do not commit; recommended to gitignore)
- `setup/rest/.rest_history` (do not commit; command history)

### Bootstrap (copy template)

To initialize `setup/rest/` in a repo for the first time, copy the bundled template from Codex:

```bash
mkdir -p setup
cp -R "$AGENT_HOME/skills/tools/testing/api-test-runner/assets/scaffold/setup/rest" setup/
```

The template includes a helper to turn a copied `api-rest`/`rest.sh` history command into a report:

- `api-rest report-from-cmd '<paste an api-rest/rest.sh command snippet>'`

## Request file schema (JSON only)

Each request lives at:

- `setup/rest/requests/<name>.request.json`

Schema:

- `method` (required; HTTP method, e.g. `GET`, `POST`)
- `path` (required; relative path only, starts with `/`, does not include scheme/host)
- `query` (optional; JSON object; strict encoding rules):
  - Keys are sorted (stable output)
  - `null` drops the key
  - Scalar values encode as `k=v`
  - Arrays encode as repeated `k=v1&k=v2` pairs (null elements are dropped)
  - Objects are rejected (put them in `body` instead)
- `headers` (optional; JSON object; Authorization is managed by CLI/token profiles)
- `body` (optional; JSON value; sent as request body)
- `expect` (optional; CI/E2E assertions):
  - `status` (required when `expect` is present; integer; typically `200`)
  - `jq` (optional; jq expression evaluated with `jq -e` against the JSON response)

## Steps

1. Start the API server (project-specific)

```bash
# Example
# yarn serve:api
```

1. Configure endpoint presets (local/staging/dev)

Edit `setup/rest/endpoints.env` to match your environments. Example:

```bash
REST_ENV_DEFAULT=local

REST_URL_LOCAL=http://localhost:<port>
# REST_URL_DEV=https://<dev-host>
# REST_URL_STAGING=https://<staging-host>
```

1. (Optional) Configure token profiles

Put placeholders in `setup/rest/tokens.env` and real tokens in `setup/rest/tokens.local.env` (gitignored). Example:

```bash
REST_TOKEN_DEFAULT="<your token>"
REST_TOKEN_ADMIN="<admin token>"
```

1. Call REST requests (recommended: Codex skill script)

Tip: if you are not running from the repo root, add `--config-dir setup/rest` to the commands below.

```bash
api-rest call \
  --env local \
  setup/rest/requests/<request>.request.json \
| jq .
```

If the endpoint requires auth:

- Use a token profile (requires `REST_TOKEN_<NAME>` to be non-empty in `setup/rest/tokens.local.env`): add `--token <name>`
- Or use a one-off token via env (useful for CI): export `ACCESS_TOKEN`

1. (Optional) Use built-in assertions for CI/E2E

Add `expect` to the request file:

```json
{
  "method": "GET",
  "path": "/health",
  "expect": { "status": 200, "jq": ".ok == true" }
}
```

Then run the request; the script should exit non-zero on assertion failure.

1. Generate a test report under `docs/`

Reports should include real data. If the response is empty and that’s not clearly intended/correct, adjust the request (path/query/body) and
re-run before writing the report.

Notes:

- Reports redact common secret-like fields by default (e.g. `Authorization`, `Cookie`, `accessToken`); use `--no-redact` only when
  necessary.
- If the request includes `expect`, the report will include an `### Assertions` section.

```bash
export REST_REPORT_DIR="docs" # optional (default: <project root>/docs; relative to <project root>)

api-rest report \
  --case "<test case name>" \
  --request setup/rest/requests/<request>.request.json \
  --env <local|staging|dev> \
  --run
```

Report output contract (recommended):

- `$AGENT_HOME/skills/tools/testing/api-test-runner/references/REST_API_TEST_REPORT_CONTRACT.md`

If you already have an `api-rest`/`rest.sh` command snippet (e.g. from `setup/rest/.rest_history`), you can generate the report without
manually rewriting it:

```bash
api-rest report-from-cmd '<paste an api-rest/rest.sh command snippet>'
```

1. CI / E2E usage (recommended pattern)

If a request file includes `expect`, `api-rest call` should exit non-zero on assertion failure. This makes it suitable for CI.

Minimal pattern:

- Start the API server (job/service).
- Export `REST_URL` and (if needed) `ACCESS_TOKEN` from CI secrets.
- Run one or more `setup/rest/requests/*.request.json` that include `expect`.

Example (single request):

```bash
REST_URL="https://<host>" \
ACCESS_TOKEN="${ACCESS_TOKEN:-}" \
api-rest call \
  --url "$REST_URL" \
  --config-dir setup/rest \
  setup/rest/requests/health.request.json
```

## Notes for stability

- Prefer “files + CLI” over ad-hoc one-liners: it reduces drift and quoting mistakes.
- Keep secrets out of request files; use `*.local.*` for local-only overrides.
