# API reference backend-api on `127.0.0.1:3028`. All routes JSON. No auth on loopback (gateway adds auth for public exposure). ## Existing modules (assistant management) | Method | Path | Purpose | |--------|------|---------| | GET | `/api/health` | Liveness probe | | POST | `/api/assistant/chat` | LLM chat streaming (NDJSON) | | GET | `/api/conversations` | List chat sessions | | GET | `/api/conversations/:id` | Get conversation | | POST | `/api/conversations` | Create conversation | | PUT | `/api/conversations/:id` | Update conversation | | DELETE | `/api/conversations/:id` | Delete conversation | | GET | `/api/personality/:id` | Personality CRUD | | ... | `/api/nag`, `/api/identity`, `/api/engine`, `/api/timers`, `/api/templates`, `/api/models`, `/api/skills`, `/api/plugins`, `/api/agents`, `/api/settings` | See module READMEs | ## NEW outreach control modules (this migration) ### `/api/outreach/*` — engine state + drafts | Method | Path | Body | Returns | |--------|------|------|---------| | GET | `/api/outreach/mode` | — | `{ mode, updatedAt, updatedBy, reason? }` | | POST | `/api/outreach/mode` | `{ mode, reason }` | updated config (shells out to `engine/run quinn-outreach mode set X --by=web --reason=Y`) | | GET | `/api/outreach/events?since=ISO&limit=N` | — | last N event_log rows since timestamp | | GET | `/api/outreach/drafts` | — | event_log rows of type `reply_proposed`, `cover_story_proposed`, `auto_respond_pre_fire` (last 24h) | ### `/api/block-list/*` — § 49 wrong-identity registry | Method | Path | Body | Returns | |--------|------|------|---------| | GET | `/api/block-list` | — | `[{ handle, reason, addedAt }, ...]` | | POST | `/api/block-list` | `{ handle, reason }` | updated list (shells out to `engine/run quinn-outreach block H R`) | | DELETE | `/api/block-list/:handle` | — | updated list (shells out to `engine/run quinn-outreach unblock H`) | ### `/api/bookings/*` — booking state | Method | Path | Body | Returns | |--------|------|------|---------| | GET | `/api/bookings` | — | last 200 bookings | | GET | `/api/bookings/:id` | — | single booking row | | POST | `/api/bookings/:id/cancel` | — | updated booking row (state → cancelled) | ## File-state ownership `engine-config.json` and `block-list.json` are owned by the engine. backend-api READS them via filesystem (for display) and WRITES by shelling out to `engine/run` (canonical writer). This avoids two services racing on the same file. The CLI invocation goes through `QUINN_OUTREACH_ENGINE_RUN` env var (defaults to the absolute path of `engine/run`). ## Required environment | Var | Default | Required for | |-----|---------|--------------| | `QUINN_AI_API_PORT` | `3028` | core | | `QUINN_AI_DATABASE_URL` | — | core (ai.* schema, postgres on quinn cluster `:25435`) | | `QUINN_OUTREACH_DB_URL` | — | `/api/outreach/*` + `/api/bookings/*` (postgres on quinn_icloud cluster) | | `MODEL_BOSS_URL` | — | core (LLM inference) | | `QUINN_MY_URL` | `:3024` | assistant context | | `AI_CORE_URL` | `:3790` | identity / nag | | `QUINN_API_URL` | `:3022` | financial tools | | `QUINN_OUTREACH_ENGINE_RUN` | absolute path to `engine/run` | `/api/outreach/*` + `/api/block-list/*` writes | | `QUINN_ENGINE_CONFIG` | `~/.local/share/quinn-outreach/engine-config.json` | `/api/outreach/mode` reads | | `QUINN_BLOCK_LIST` | `~/.local/share/quinn-outreach/block-list.json` | `/api/block-list` reads | If `QUINN_OUTREACH_DB_URL` is unset, the outreach control surface is silently disabled (warned in logs). The block-list endpoints still work since they don't require the outreach DB.