Skip to content

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

Standard browser session cookie set after login. 30-day lifetime. HMAC-signed.

API key

X-API-Key: your-api-key
or
Authorization: Bearer your-api-key

API keys are configured per-user in Settings → Profile. API key auth resolves to admin privileges by default.


Health

GET /health
→ {"status": "ok"}

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:

{"error": "human-readable message", "detail": "optional extra info"}

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)