Rate-limit the optional agent bearer path after user auth resolution so mixed user/agent routes no longer leave an unthrottled PBKDF2 path. Stop logging token prefixes on agent auth failures and require a locally supplied token for backend/.env.test instead of committing one. Update tests and docs to cover agent bearer fallback, configurable webhook signature headers, and the operator-facing security settings added by the hardening work. Co-Authored-By: Claude <noreply@anthropic.com>
5.7 KiB
API reference (notes + conventions)
Mission Control exposes a JSON HTTP API (FastAPI) under /api/v1/*.
- Default backend base URL (local):
http://localhost:8000 - Health endpoints:
GET /health(liveness)GET /healthz(liveness alias)GET /readyz(readiness)
OpenAPI / Swagger
- OpenAPI schema:
GET /openapi.json - Swagger UI (FastAPI default):
GET /docs
If you are building clients, prefer generating from
openapi.json.
API versioning
- Current prefix:
/api/v1 - Backwards compatibility is best-effort while the project is under active development.
Authentication
All protected endpoints expect a bearer token:
Authorization: Bearer <token>
Auth mode is controlled by AUTH_MODE:
local: shared bearer token auth (token isLOCAL_AUTH_TOKEN)clerk: Clerk JWT auth
Notes:
- The frontend uses the same bearer token scheme in local mode (users paste the token into the UI).
- Many “agent” endpoints use an agent token header instead (see below).
Agent auth (Mission Control agents)
Some endpoints are designed for autonomous agents and use an agent token header:
X-Agent-Token: <agent-token>
On shared user/agent routes, the backend also accepts Authorization: Bearer <agent-token> after user auth does not resolve. When in doubt, consult the route’s dependencies (e.g., require_user_or_agent).
Agent authentication is rate-limited to 20 requests per 60 seconds per IP. Exceeding this limit returns 429 Too Many Requests.
Authorization / permissions model (high level)
The backend distinguishes between:
- users (humans) authenticated via
AUTH_MODE - agents authenticated via agent tokens
Common patterns:
- User-only endpoints: require an authenticated human user (not an agent). Organization-level admin checks are enforced separately where needed (
require_org_admin). - User or agent endpoints: allow either an authenticated human user or an authenticated agent.
- Board-scoped access: user/agent access may be restricted to a specific board.
SOC2 note: the API produces an audit-friendly request id (see below), but role/permission policy should be documented per endpoint as we stabilize.
Security headers
All API responses include the following security headers by default:
| Header | Default |
|---|---|
X-Content-Type-Options |
nosniff |
X-Frame-Options |
DENY |
Referrer-Policy |
strict-origin-when-cross-origin |
Permissions-Policy |
(disabled) |
Each header is configurable via SECURITY_HEADER_* environment variables. Set a variable to blank to disable the corresponding header (see configuration reference).
Rate limits
The following per-IP rate limits are enforced on sensitive endpoints:
| Endpoint | Limit | Window |
|---|---|---|
Agent authentication (X-Agent-Token or agent bearer fallback on shared routes) |
20 requests | 60 seconds |
Webhook ingest (POST .../webhooks/{id}) |
60 requests | 60 seconds |
When a rate limit is exceeded, the API returns 429 Too Many Requests.
Set RATE_LIMIT_BACKEND to choose the storage backend:
| Backend | Value | Behavior |
|---|---|---|
| In-memory (default) | memory |
Per-process limits; no external dependencies. |
| Redis | redis |
Shared across all workers. Set RATE_LIMIT_REDIS_URL or it falls back to RQ_REDIS_URL. Connectivity is validated at startup; transient failures fail open. |
Note: When using the in-memory backend, limits are per-process. Multi-process deployments should either switch to the Redis backend or apply rate limiting at the reverse proxy layer (nginx
limit_req, Caddy, etc.).
Request IDs
Every response includes an X-Request-Id header.
- Clients may supply their own
X-Request-Id; otherwise the server generates one. - Use this id to correlate client reports with server logs.
Errors
Errors are returned as JSON with a stable top-level shape:
{
"detail": "...",
"request_id": "..."
}
Common status codes:
401 Unauthorized: missing/invalid credentials403 Forbidden: authenticated but not allowed404 Not Found: resource missing (or not visible)413 Content Too Large: request payload exceeds size limit (e.g. webhook ingest 1 MB cap)422 Unprocessable Entity: request validation error429 Too Many Requests: per-IP rate limit exceeded500 Internal Server Error: unhandled server errors
Validation errors (422) typically return detail as a list of structured field errors (FastAPI/Pydantic style).
Pagination
List endpoints commonly return an items array with paging fields (varies by endpoint). If you’re implementing new list endpoints, prefer consistent parameters:
limitoffset
…and return:
items: []totallimitoffset
Examples (curl)
Health
curl -f http://localhost:8000/healthz
Agent heartbeat check-in
curl -s -X POST http://localhost:8000/api/v1/agent/heartbeat \
-H "X-Agent-Token: $AUTH_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"Tessa","board_id":"<board-id>","status":"online"}'
List tasks for a board
curl -s "http://localhost:8000/api/v1/agent/boards/<board-id>/tasks?status=inbox&limit=10" \
-H "X-Agent-Token: $AUTH_TOKEN"
Gaps / follow-ups
- Per-endpoint documentation of:
- required auth header (
AuthorizationvsX-Agent-Token) - required role (admin vs member vs agent)
- common error responses per endpoint
- required auth header (
- Rate limits are documented above; consider exposing them via OpenAPI
x-ratelimit-*extensions. - Add canonical examples for:
- creating/updating tasks + comments
- board memory streaming
- approvals workflow