# API Surface

Reference for every `app/api/**/route.js` route. Read this when you need to find or wire an HTTP endpoint. Routes live at `app/api/**/route.js`.

## Core runtime

| Route | Description |
|-------|-------------|
| `GET /api/state` | Full runtime snapshot from SQLite |
| `POST /api/orchestrator/command` | Main agent NLP router — dispatches to agent creation, reports, etc. |
| `POST /api/agents/create` | Create a named agent with local files |
| `POST /api/runs/competitor-report` | Generate competitor report artifact |
| `POST /api/runs/marketing-plan` | Generate marketing plan artifact |
| `POST /api/runs/claude-code-dry-run` | Approval-gated command preview — **never auto-executes** |
| `POST /api/heartbeat/tick` | Update heartbeat for all generated agents |
| `POST /api/schedules/upsert` | Create or update a schedule for an agent |
| `GET/POST /api/approvals` | List or create durable approval requests |
| `GET/PATCH /api/approvals/[id]` | Read, approve, or deny one approval request |
| `GET /api/events/stream` | SSE channel for live activity events. Capped at 32 simultaneous subscribers. |
| `GET/PATCH /api/settings/trust-mode` | Read or update main agent trust mode. `PATCH { mode: 'auto' \| 'approval_required', confirm: true }`. Writes audit row. |

## Marketplace & tools

| Route | Description |
|-------|-------------|
| `GET /api/tools` | List tool marketplace metadata and connector readiness |
| `PUT /api/tools/[name]` | Enable or disable a marketplace tool |
| `GET /api/marketplace` | Unified marketplace. `?kind=tool\|skill\|bundle`, `?category=`, `?q=`. `kind=agent` returns 400 (Phase 1 boundary). |
| `GET /api/marketplace/open-design` | Read-only catalog over vendored `workspace/skills/open-design/`. `?kind=`, `?scenario=`, `?q=`, `?include_body=1`. |
| `PUT /api/marketplace/[id]` | Install / uninstall. Body: `{ installed: boolean }`. Tool → `setToolEnabled`; skill → `marketplace_installations`; bundle → `{ status: 'deferred' }`. |
| `DELETE /api/marketplace/[id]` | Phase 1: tool-kind only. 405 for skill/bundle. |

## Secrets, allowlists, egress

| Route | Description |
|-------|-------------|
| `GET /api/secrets` | List active secrets — names and metadata only. Values never returned. |
| `POST /api/secrets` | Store a new secret. Body: `{ name, value, scope?, source?, metadata? }`. Audit row written; value never logged. |
| `PATCH /api/secrets/[name]` | Rotate a secret. Creates new active row, marks old row `rotated`. |
| `DELETE /api/secrets/[name]` | Revoke a secret. `?scope=` query param. |
| `GET /api/tool-allowlists` | List entries grouped by tool. |
| `POST /api/tool-allowlists` | Add entry. Body: `{ tool_name, scope_key, scope_value, label? }`. 409 if duplicate. |
| `DELETE /api/tool-allowlists/[id]` | Remove entry by ID. |
| `GET /api/tool-egress` | Paginated external API call log. `?limit=`, `?tool_name=`, `?agent_id=` (`main` for main-agent rows), `?host=`, `?since=ISO`. |

## WhatsApp

| Route | Description |
|-------|-------------|
| `GET /api/whatsapp/status` | Bridge health + inbound allowlist. |
| `GET /api/whatsapp/qr` | Current QR pairing string, or `{ paired: true }`. |
| `POST /api/whatsapp/send` | Send manually. `{ chat_id, text }`. Logs + audit row. |
| `GET /api/whatsapp/messages` | Recent messages. `?limit=` up to 200. |
| `GET/POST/DELETE /api/whatsapp/allowlist` | Manage senders. `POST { chat_id, label?, kind? }`; `DELETE ?chat_id=`. |

## Voice (Jarvis)

| Route | Description |
|-------|-------------|
| `GET/POST /api/voice/tts` | TTS provider status + audio synthesis for OpenAI / ElevenLabs / local HTTP TTS (`MADARX_LOCAL_TTS_URL`, including the optional MisoTTS bridge). Audio streams; credentials stay in vault. |
| `GET/POST /api/voice/realtime/session` | OpenAI Realtime availability + ephemeral browser session. Client secret returned but never stored. Body accepts `project_id`/`agent_id`. |
| `POST /api/voice/realtime/tool-result` | Relays model-requested tools through `executeVoiceTool` / `executeRegistryTool`. All gates preserved. |
| `GET /api/voice/providers` | Provider capabilities snapshot (realtime/tts/stt/llm) + default mode + local slot URLs. |
| `GET /api/voice/realtime/context` | Madarx context block (instructions, tools, capabilities, date, project, providers_configured). Per-IP rate-limited 60/min. |
| `GET /api/voice/realtime/tools` | Curated voice tool catalog (UI + OpenAI function-call schema). |

## Auth + Privacy (see [auth-privacy.md](auth-privacy.md))

| Route | Description |
|-------|-------------|
| `GET/DELETE /api/auth/session` | Current session; `DELETE` signs out. |
| `GET /api/auth/callback` | Supabase OAuth / magic-link code exchange. |
| `GET/POST /api/orgs` | List orgs for session user; create org. |
| `GET/PATCH/DELETE /api/orgs/[id]` | Read, update, delete org. |
| `GET/POST/DELETE /api/orgs/[id]/members` | List, invite, remove members. |
| `PATCH /api/orgs/[id]/members/[userId]/role` | Change a member's role. |
| `DELETE /api/orgs/[id]/members/[userId]` | Remove specific member. |
| `GET/PUT /api/artifacts/[id]/acl` | Read or update artifact ACL (owner/admin only). |
| `POST/DELETE /api/artifacts/[id]/protect` | Set or clear passphrase protection. |
| `POST/DELETE /api/artifacts/[id]/share-link` | Create or revoke signed share link. |
| `GET/DELETE /api/artifacts/[id]/share-link/[linkId]` | Read or revoke specific link. |
| `GET /api/share/[token]` | Public share link resolution. Path-traversal guard before streaming. |
| `POST /api/share/[token]/verify` | Consume signed short-lived token for download. |
| `POST /api/share/[token]/otp` | Request / verify email OTP for share-link access (per-org toggle). OTP in body, never URL. |
| `GET /api/admin/audit-export` | Stream filtered audit log as CSV/NDJSON (owner/admin only). |
| `DELETE /api/admin/share-links` | Bulk revoke by `link_ids[]` or `artifact_id`. |
| `GET/POST/DELETE /api/privacy/config` | Read passphrase config (no key material), set passphrase, reset protections. No public read path. |
| `POST /api/privacy/verify` | Verify PBKDF2-derived HMAC. Never returns the key. |
| `GET /api/audit/search` | Audit log search. `?user_id=`, `?org_id=` filters supported; rows include `user_id`, `org_id`, `ip`. |

## Process / Workflow engine (see [process-engine.md](process-engine.md))

| Route | Description |
|-------|-------------|
| `GET /api/processes/definitions` | List published process definitions. `?status=all\|published\|draft\|archived`. |
| `GET /api/processes/definitions/[slug]` | Definition detail incl. stages + intake form schema. |
| `GET /api/processes` | List cases. Filters: `project_id`, `status`, `definition_slug`, `limit`. |
| `POST /api/processes` | Start a case. Body: `{ definition_slug, project_id, title?, intake_payload? }`. When `intake_payload` is supplied, the case advances past intake immediately. |
| `GET /api/processes/[id]` | Case detail: case row, definition, stages, executions, approvals, artifacts. |
| `PATCH /api/processes/[id]` | Currently supports `{ status: 'cancelled' }` only. |
| `POST /api/processes/[id]/stages/[stageId]/submit` | Submit an intake form payload for an `intake_form` stage. Body: `{ payload }`. |
| `POST /api/processes/[id]/stages/[stageId]/retry` | Re-enqueue a stage execution (creates a new `attempt`). |
| `POST /api/processes/[id]/stages/[stageId]/override` | Admin force-transition. Body: `{ outcome: 'pass'\|'fail', reason? }`. Records an explicit execution row + advances. |
