# API Reference Base URL: `http://:` (default `http://127.0.0.1:4173`). When `auth.enabled: true`, every endpoint below except `/api/healthz`, `/api/auth/login`, and `/api/auth/session` requires either a valid session cookie or an `Authorization: Bearer ` header using a token from `triggershell users add-token`. `triggershell run ` is a first-party client of this exact REST + WS contract (see [Running scripts from the CLI](../README.md#running-scripts-from-the-cli)) - nothing below is CLI-specific. ## Auth ### `POST /api/auth/login` ```bash curl -c cookies.txt -X POST http://127.0.0.1:4173/api/auth/login \ -H "Content-Type: application/json" \ -d '{"username":"admin","password":"..."}' ``` `200 {"user": {"username": "admin"}}` on success (sets the session cookie), `401` on bad credentials, `429` if rate-limited. ### `POST /api/auth/logout` `204` — clears the session. ### `GET /api/auth/session` `200 {"authRequired": bool, "authenticated": bool, "user": {"username": string} | null}` ## Scripts ### `GET /api/scripts` `200 {"scripts": [{"id", "name", "description"}]}` ### `GET /api/scripts/:scriptId` Full schema for one script, including resolved UI `control` per variable and secret defaults stripped: ```bash curl -b cookies.txt http://127.0.0.1:4173/api/scripts/deploy-service ``` `404` if not found. ### `POST /api/scripts/:scriptId/runs` Starts a run. ```bash curl -b cookies.txt -X POST http://127.0.0.1:4173/api/scripts/deploy-service/runs \ -H "Content-Type: application/json" \ -d '{"variables": {"environment": "staging", "replicas": 2, "dryRun": true}}' ``` `201 {"runId": string, "status": "queued"}` on success. `400 {"error", "fieldErrors"}` if the variables fail validation (the same Zod schema the UI form uses). `404` if the script doesn't exist. ## Runs ### `GET /api/runs` Query params: `scriptId`, `status` (one of `queued|running|succeeded|failed|cancelled|timed_out|interrupted`), `limit` (default 50, max 200), `cursor` (offset, from the previous page's `nextCursor`). `200 {"runs": [...], "nextCursor": string | null}` ### `GET /api/runs/:runId` The full run record (status, variables with secrets redacted, resolved command, timestamps, exit code). `404` if not found. ### `POST /api/runs/:runId/cancel` `202 {"status": "cancelling"}`. `409` if the run already finished, or if it isn't tracked by _this_ server process (e.g. after a restart — see "orphaned runs" in `docs/ARCHITECTURE.md`). ### `GET /api/runs/:runId/logs` Plain-text log output. Query params: `tail=` (last N lines only), `download=1` (sets `Content-Disposition: attachment`). ## WebSocket: `/ws/runs` Auth: session cookie, or `?token=` for non-browser clients (the upgrade request has no `Authorization` header support, since it's a plain HTTP upgrade). Client → server messages: ```jsonc { "type": "subscribe", "runId": "..." } { "type": "unsubscribe", "runId": "..." } { "type": "cancel", "runId": "..." } ``` Server → client messages: ```jsonc { "type": "output", "runId": "...", "stream": "stdout" | "stderr", "chunk": "...", "seq": 0, "ts": 0 } { "type": "status", "runId": "...", "status": "running", "exitCode": null, "ts": 0 } { "type": "error", "runId": "...", "message": "..." } ``` A client only receives messages for runs it has subscribed to.