REST API Reference¶
All API endpoints are under /api/. Endpoints that require authentication use the session cookie or the X-API-Key / Authorization: Bearer <key> header.
Admin-only endpoints are marked with [admin].
Authentication¶
Session cookie¶
Standard browser session cookie set after login. 30-day lifetime. HMAC-signed.
API key¶
orAPI keys are configured per-user in Settings → Profile. API key auth resolves to admin privileges by default.
Health¶
Status & control¶
GET /api/status
→ {"paused": false, "agent_name": "Jarvis"}
POST /api/pause
→ {"ok": true}
POST /api/resume
→ {"ok": true}
GET /api/queue
→ {"running": 1, "queued": 0, "max_concurrent": 3}
Credentials [admin]¶
Encrypted key-value store for API keys and system settings.
GET /api/credentials
→ [{"key": "system:anthropic_api_key", "description": "...", "updated_at": "..."}, ...]
GET /api/credentials/{key}
→ {"key": "...", "value": "decrypted-value", "description": "..."}
POST /api/credentials
Body: {"key": "system:anthropic_api_key", "value": "sk-ant-...", "description": "Anthropic key"}
→ {"ok": true}
DELETE /api/credentials/{key}
→ {"ok": true}
Audit log¶
GET /api/audit
Query: start, end, tool_name, session_id, task_id, confirmed_only, page, per_page
→ {"entries": [...], "total": 1234, "page": 1, "per_page": 50}
DELETE /api/audit?older_than_days=90 [admin]
→ {"deleted": 456}
GET /api/settings/audit-retention [admin]
→ {"days": 90}
POST /api/settings/audit-retention [admin]
Body: {"days": 90}
→ {"ok": true}
Whitelists [admin]¶
Email whitelist¶
GET /api/email-whitelist
→ [{"email": "...", "daily_limit": 0, "created_at": "..."}, ...]
POST /api/email-whitelist
Body: {"email": "alice@example.com", "daily_limit": 10}
→ {"ok": true}
DELETE /api/email-whitelist/{email}
→ {"ok": true}
Web whitelist (Tier 1)¶
GET /api/web-whitelist
→ [{"domain": "wikipedia.org", "note": "...", "created_at": "..."}, ...]
POST /api/web-whitelist
Body: {"domain": "example.com", "note": "Our company site"}
→ {"ok": true}
DELETE /api/web-whitelist/{domain}
→ {"ok": true}
Filesystem whitelist¶
GET /api/filesystem-whitelist
→ [{"path": "/data/documents", "note": "...", "created_at": "..."}, ...]
POST /api/filesystem-whitelist
Body: {"path": "/data/documents", "note": "Documents folder"}
→ {"ok": true} (400 if path doesn't exist on server)
DELETE /api/filesystem-whitelist/{path}
→ {"ok": true}
GET /api/filesystem-browser?path=/data
→ {"path": "/data", "entries": [{"name": "docs", "type": "dir"}, ...]}
Browser trusted domains (per-user)¶
GET /api/my/browser-trusted
→ [{"domain": "example.com", "note": "...", "created_at": "..."}, ...]
POST /api/my/browser-trusted
Body: {"domain": "example.com", "note": "Our app"}
→ {"ok": true}
DELETE /api/my/browser-trusted/{domain}
→ {"ok": true}
Models¶
GET /api/models
→ {"models": ["anthropic:claude-sonnet-4-6", ...], "default": "anthropic:claude-sonnet-4-6"}
GET /api/models/info
→ [{"id": "...", "name": "...", "provider": "anthropic", "context_length": 200000,
"pricing": {"prompt": 3.0, "completion": 15.0},
"capabilities": {"vision": true, "tools": true, "online": false}}, ...]
Settings [admin]¶
GET /api/settings/limits
→ {"max_tool_calls": 20, "max_autonomous_runs_per_hour": 10, "max_concurrent_runs": 3}
POST /api/settings/limits
Body: {"max_tool_calls": 30, "max_autonomous_runs_per_hour": 20, "max_concurrent_runs": 5}
→ {"ok": true}
GET /api/settings/provider
→ {"default_provider": "anthropic", "available_providers": ["anthropic", "openrouter"]}
POST /api/settings/provider
Body: {"default_provider": "openrouter"}
→ {"ok": true}
GET /api/settings/security
→ {"sanitize_enhanced": false, "canary": false, "llm_screen": false, ...}
POST /api/settings/security
Body: {"sanitize_enhanced": true}
→ {"ok": true}
Agents¶
GET /api/agents
→ [{"id": "...", "name": "...", "prompt": "...", "model": "...", "schedule": "0 8 * * *",
"enabled": true, "created_at": "..."}, ...]
POST /api/agents
Body: {"name": "Daily Summary", "prompt": "...", "model": "anthropic:claude-haiku-4-5-20251001",
"schedule": "0 8 * * *", "allowed_tools": ["email", "caldav"], "enabled": true,
"prompt_mode": "combined", "max_tool_calls": null}
→ {"id": "...", "name": "Daily Summary", ...} (201)
GET /api/agents/{id}
→ {"agent": {...}, "runs": [...], "total_input_tokens": 12345, "total_output_tokens": 5678}
PUT /api/agents/{id}
Body: {fields to update}
→ {"ok": true}
DELETE /api/agents/{id}
→ {"ok": true}
POST /api/agents/{id}/run
Body: {"message": "Optional override message"}
→ {"run_id": "..."}
POST /api/agents/{id}/stop
→ {"ok": true}
Scheduled tasks¶
GET /api/tasks
→ [{"id": "...", "name": "...", "schedule": "0 */4 * * *", "enabled": true, ...}, ...]
POST /api/tasks
Body: {"name": "...", "schedule": "0 8 * * *", "prompt": "...",
"allowed_tools": ["caldav", "pushover"], "enabled": true}
→ {"id": "...", ...} (201)
GET /api/tasks/{id}
PUT /api/tasks/{id}
DELETE /api/tasks/{id}
POST /api/tasks/{id}/toggle
→ {"enabled": false}
POST /api/tasks/{id}/run
→ {"ok": true}
Email accounts¶
GET /api/email-accounts
POST /api/email-accounts
Body: {"label": "Work", "account_type": "trigger",
"imap_host": "mail.example.com", "imap_port": 993,
"imap_username": "user@example.com", "imap_password": "...",
"smtp_host": "mail.example.com", "smtp_port": 465,
"smtp_username": "user@example.com", "smtp_password": "..."}
GET /api/email-accounts/{id}
PUT /api/email-accounts/{id}
DELETE /api/email-accounts/{id}
Telegram¶
GET /api/telegram/config
→ {"bot_token_set": true, "status": "running"}
POST /api/telegram/config
Body: {"bot_token": "..."}
GET /api/telegram/whitelist
POST /api/telegram/whitelist
Body: {"chat_id": "123456789", "label": "My phone"}
DELETE /api/telegram/whitelist/{chat_id}
GET /api/telegram/triggers
POST /api/telegram/triggers
Body: {"trigger_word": "weather", "agent_id": "...", "enabled": true}
PUT /api/telegram/triggers/{id}
DELETE /api/telegram/triggers/{id}
User management [admin]¶
GET /api/admin/users
→ [{"id": "...", "username": "alice", "role": "user", "is_active": true, "mfa_enabled": false}, ...]
POST /api/admin/users
Body: {"username": "alice", "password": "...", "role": "user"}
→ {"id": "..."}
GET /api/admin/users/{id}
PUT /api/admin/users/{id}
Body: {"role": "admin", "is_active": true} (partial update)
DELETE /api/admin/users/{id}
POST /api/admin/users/{id}/mfa-setup
→ {"provisioning_uri": "otpauth://...", "qr_code": "data:image/png;base64,..."}
POST /api/admin/users/{id}/mfa-disable
→ {"ok": true}
Per-user files¶
GET /api/my/files?path=/subdir
→ {"path": "/...", "entries": [{"name": "file.txt", "type": "file", "size": 1234}, ...]}
GET /api/my/files/download?path=/subdir/file.txt
→ (binary file content)
GET /api/my/files/download-zip?path=/subdir
→ (zip archive)
DELETE /api/my/files?path=/subdir/file.txt
→ {"ok": true}
Conversations¶
GET /api/conversations
Query: page, per_page
→ {"conversations": [{"id": "...", "title": "...", "model": "...", "started_at": "...", "message_count": 5}], "total": 42}
GET /api/conversations/{id}
→ {"id": "...", "title": "...", "messages": [...]}
PATCH /api/conversations/{id}
Body: {"title": "New title"}
→ {"ok": true}
DELETE /api/conversations/{id}
→ {"ok": true}
WebSocket: /ws/{session_id}¶
See the WebSocket Protocol page for full documentation.
Error responses¶
All errors return JSON:
Common status codes:
- 400 — bad request (missing field, validation error)
- 401 — not authenticated
- 403 — authenticated but not authorised (e.g. non-admin accessing admin endpoint)
- 404 — resource not found
- 409 — conflict (e.g. duplicate email in whitelist)
- 500 — server error (check logs)