> ## Documentation Index
> Fetch the complete documentation index at: https://docs.trevosdk.com/llms.txt
> Use this file to discover all available pages before exploring further.

# API & CLI

> Drive Trevo from a script, CI, or an agent — the same routes the dashboard uses, with a workspace API key.

Everything the dashboard does to proposals and experiments goes through `https://api.trevosdk.com/v1`.
A **workspace API key** lets a script, a CI job, or an agent do the same: list what Trevo proposed,
approve or dismiss, send revision instructions, ask for a fresh batch, start and end experiments.

## Keys

Make one under **Settings → API access**. A key:

* opens **one workspace** — no workspace header needed, and one that disagrees is refused;
* **reads everything** in it, and writes only what its scopes allow — `proposals.review`,
  `experiments.manage`, `experiments.decide`, `funnels.manage`, each a permission the routes already
  check for people;
* **acts as the person who made it** in the audit log and in what Trevo says it did;
* is shown **once**, stored hashed, and revocable from the same page.

A key cannot manage keys, billing, members, or the organisation. SDK keys (`tsk_live_`,
`tsk_secret_`) are your site's, and are refused on these routes.

Every write a key makes is recorded in the audit trail as that key, beside the person it acts as —
the dashboard's trail and the CSV export both name it, and `GET /v1/audit?actorApiKeyId=…` filters
to one key.

```bash theme={null}
curl https://api.trevosdk.com/v1/experiments?status=proposed \
  -H "Authorization: Bearer tsk_api_…"
```

## The CLI

```bash theme={null}
npm install -g @trevosdk/cli
trevo login                    # paste a key once; or set TREVO_API_KEY
```

Every command takes `--json` and prints the API response verbatim. Exit codes: `0` ok, `1` the API
refused (the reason and its code are on stderr), `2` usage, `3` auth — so a script can tell a revoked
key from a proposal that was not approvable. Installation and CI setup: [CLI](/install/cli).

Reading is always allowed; the **Scope** column is the permission a key needs for the write.

### Keys and identity

| Command | What it does | Route | Scope |
| - | - | - | - |
| `trevo login` | Stores a key in `~/.config/trevo/config.json` (mode 0600) after checking it against the API. `TREVO_API_KEY` overrides the file, so CI never writes one. | `GET /experiments/counts` | — |
| `trevo whoami` | Which workspace the key opens, the key's own name, the person it acts as, and what it may write — the first thing to run when a script hits the wrong workspace. | `GET /me`, `GET /experiments/counts` | — |

### Proposals

| Command | What it does | Route | Scope |
| - | - | - | - |
| `trevo proposals list` | The proposals waiting for a decision — experiments at `status=proposed`, newest first. | `GET /experiments?status=proposed` | — |
| `trevo proposals show <id>` | One proposal in full: the hypothesis, the change plan file by file, and whether any of those files have since moved or gone. | `GET /experiments/{id}` | — |
| `trevo proposals approve <id>` | Accepts the proposal and starts the pull request. `--wait` blocks until it is open and exits non-zero the moment generation fails; `--acknowledge-overlap` confirms you want it running beside an experiment that shares a surface. | `POST /experiments/{id}/approve` | `proposals.review` |
| `trevo proposals dismiss <id> --reason <reason>` | Refuses a proposal, terminally. Comma-separate more than one reason. The reason is what teaches the next generation round. | `POST /experiments/{id}/dismiss` | `proposals.review` |
| `trevo proposals revise <id> "<instructions>"` | Asks for the proposal to be rewritten to your brief, in place. `--wait` blocks until the revision lands (ten minutes, then it gives up). | `POST /experiments/{id}/refine`, `GET …/refine` | `proposals.review` |

### Generation

| Command | What it does | Route | Scope |
| - | - | - | - |
| `trevo generate` | Asks for a fresh batch of proposals, grounded in your repository. Returns as soon as the run starts. `--replace` retires the pending drafts when the new batch lands, not before. `--wait` blocks until the run finishes and exits non-zero if it failed. | `POST /experiments/generate` | `proposals.review` |
| `trevo runs` | The generation runs, newest first: status, how many proposals survived filtering, and when. This is how you check on a `generate` you did not wait for. `--wait` blocks on the current one. | `GET /experiment-runs` | — |
| `trevo runs show <id>` | One run, including why it failed and at which step. | `GET /experiment-runs/{id}` | — |

### Experiments

| Command | What it does | Route | Scope |
| - | - | - | - |
| `trevo experiments list` | Every experiment, filterable with `--status`, `--search` and `--limit`. Statuses comma-separate. | `GET /experiments` | — |
| `trevo experiments show <id>` | One experiment with its results, readiness flags and pull requests. | `GET /experiments/{id}` | — |
| `trevo experiments status <id>` | Just the status word — what a CI job polls. `--wait --until <status>` blocks until it arrives, exits `1` if the experiment settles somewhere it will never leave (`pr_failed`, `rejected`), and is always bounded by `--timeout`. | `GET /experiments/{id}/status` | — |
| `trevo experiments create --file <file>` | Declares an experiment you wrote yourself, instead of accepting a proposal. The `Idempotency-Key` is derived from the file, so a re-run of the same CI step replays the first result rather than opening a second pull request. `--generate-pr` starts the code immediately. | `POST /experiments` | `experiments.manage` |
| `trevo experiments start\|pause\|resume\|end\|ship <id…>` | Moves experiments through the lifecycle. Takes several ids and applies them in order; if one is refused the earlier ones have already moved, and the CLI says which. `start` refuses when the primary event cannot be verified — measurement fails closed rather than starting blind. | `POST /experiments/{id}/{action}` | `experiments.manage` |
| `trevo experiments decide <id> --ship <variant>` | Calls the winner and opens the cleanup pull request. `--reject` reverts instead; `--reason` records why; `--force` skips the settling wait that holds a decision while conversions from the last exposures are still arriving. | `POST /experiments/{id}/decide` | `experiments.decide` |

### Funnels

| Command | What it does | Route | Scope |
| - | - | - | - |
| `trevo funnels list` | Every funnel with its steps in order. | `GET /funnel` | — |
| `trevo funnels pull` | Writes the definitions as a file to commit — name and ordered steps, nothing the workspace owns. Without `--file` it prints to stdout. | `GET /funnel` | — |
| `trevo funnels apply --file <file>` | Reconciles the workspace to that file: creates what is missing, updates what changed, no-ops on the second run. Funnels are matched **by name**, so a rename creates a new funnel. `--dry-run` prints the plan without calling a write; `--prune` is the only way it deletes. | `GET`/`POST`/`PATCH`/`DELETE /funnel` | `funnels.manage` |

## Reference

The OpenAPI description of these routes is at [`/reference/openapi.json`](/reference/openapi.json).
It is generated from the schemas the API parses, so it describes what the routes actually accept
and return.
Refusals carry a `code` worth branching on:

| Code | Meaning |
| - | - |
| `SURFACE_OVERLAP` | The proposal shares a surface with an experiment already in flight. Approve with `acknowledgeOverlap: true` to run both. |
| `PROPOSAL_FILES_MISSING` | A file the plan edits is no longer in the repository; the message names it. Revise or regenerate. |
| `PROPOSAL_SNAPSHOT_STALE` | Code the proposal relies on changed after it was written. Generate a fresh one. |
| `GENERATION_IN_FLIGHT` | A batch is already being generated for this workspace. |
| `MISSING_PERMISSION` | The key lacks the scope this write needs. |
| `API_KEY_NOT_ALLOWED_HERE` | Keys work on experiments, proposals, funnels, readiness and events — not settings. |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.