Base URL: http://localhost:10272 (or your domain if behind a reverse-proxy)
All endpoints marked Auth required require a valid session cookie (hermes...auth).
Login first via POST /api/auth/login to receive the cookie.
Internal endpoints (marked Internal) require the x-hermes-control-secret header matching HERMES_CONTROL_SECRET instead of a cookie.
Auth required: No
Returns a basic health check.
{
"ok": true,
"title": "Hermes Control Interface",
"auth": true,
"ws": "/ws"
}Auth required: No
Returns the current authentication state.
{
"authenticated": false,
"passwordRequired": true,
"identity": "root@hermes"
}Auth required: No
Rate limited: 5 attempts per 15 minutes per IP.
Request body:
{ "password": "***" }Success response (200):
{ "ok": true }Sets the hermes...auth cookie.
Failure response (401):
{ "ok": false, "error": "bad password" }Rate limited response (429):
{
"ok": false,
"error": "too many failed attempts, try again in 15 minutes"
}Auth required: No (but does nothing if not authenticated)
Clears the session cookie.
{ "ok": true }Auth required: Yes
Returns all configured Hermes profiles with their status.
Response:
{
"ok": true,
"profiles": [
{ "name": "default", "model": "xiaomi/mimo-v2-pro", "gateway": "stopped", "alias": null, "active": false },
{ "name": "david", "model": "xiaomi/mimo-v2-pro", "gateway": "running", "alias": "david", "active": true },
{ "name": "soci", "model": "gpt-5.4-mini", "gateway": "stopped", "alias": "soci", "active": false }
]
}Auth required: Yes (CSRF required)
Sets the active (default) Hermes profile.
Request body:
{ "profile": "david" }Response:
{ "ok": true, "profile": "david", "output": "..." }Auth required: Yes
Returns the systemd service status for a profile's gateway.
Response:
{
"ok": true,
"profile": "david",
"service": "hermes-gateway-david",
"active": true,
"enabled": true,
"status": "● hermes-gateway-david.service - Hermes Gateway - david..."
}Auth required: Yes (CSRF required)
Controls a gateway systemd service.
Actions: start, stop, restart, enable, disable
Response:
{
"ok": true,
"profile": "david",
"action": "start",
"active": true,
"output": ""
}Auth required: Yes
Returns journal logs for a gateway service.
Query parameters:
lines(optional) — number of log lines to return (default: 50, max: 500)
Response:
{
"ok": true,
"profile": "david",
"service": "hermes-gateway-david",
"logs": "Apr 10 23:00:00 vm1 systemd[1]: Started Hermes Gateway - david..."
}Auth required: Yes
Returns directory trees for configured explorer roots.
Query parameters:
root(optional) — key of a specific root to query. If omitted, returns all roots.
Response:
[
{
"key": "projects",
"label": "/root/projects",
"root": "/root/projects",
"children": [
{
"name": "my-project",
"path": "/root/projects/my-project",
"rel": "my-project",
"type": "dir",
"depth": 0,
"children": [...]
}
]
}
]Auth required: Yes
Reads a file.
Query parameters:
path— absolute path to the file (must be within an explorer root)
Response (200):
{
"path": "/root/projects/my-project/file.js",
"content": "console.log('hello')"
}Error responses:
400— path missing or outside allowed roots404— file not found400— path is a directory
Auth required: Yes
Writes a file.
Request body:
{
"path": "/root/projects/my-project/file.js",
"content": "console.log('updated')"
}Response (200):
{
"ok": true,
"path": "/root/projects/my-project/file.js",
"bytes": 24
}Auth required: Yes
Queues a command in the PTY terminal session.
Request body:
{ "command": "ls -la" }Response:
{
"ok": true,
"queued": true,
"command": "ls -la",
"cwd": "/root/projects/hermes-control-interface",
"identity": "root@hermes",
"ready": true,
"buffer": "...terminal output...",
"timestamp": "2026-04-09T00:00:00.000Z"
}Special commands starting with /cron are handled internally and marked "special": true.
Auth required: Yes
Actions: add, list, remove, pause, resume
add request body:
{
"schedule": "30m",
"note": "daily report",
"deliver": "origin"
}remove request body:
{ "id": "abc123" }pause / resume request body:
{ "id": "abc123" }list takes no body.
Auth required: Internal (header-based)
Same as /api/cron/:action but uses x-hermes-control-secret header for authentication. Used by Hermes itself to trigger cron actions internally.
Auth required: Yes
Returns system resource usage.
{
"memUsed": "842 MB",
"memTotal": "1.96 GB",
"diskUsed": "38 GB",
"diskTotal": "49 GB",
"cpuCores": 2,
"loadAvg": [0.12, 0.08, 0.05],
"uptime": 3600,
"hostname": "vm1"
}Auth required: Yes
Returns the saved dashboard layout.
{
"ok": true,
"layout": {
"updatedAt": "2026-04-09T00:00:00.000Z",
"panels": [
{ "id": "terminal", "x": 0, "y": 0, "w": 800, "h": 400 }
]
}
}Auth required: Yes
Saves dashboard layout.
Request body:
{
"panels": [
{ "id": "terminal", "x": 0, "y": 0, "w": 800, "h": 400 }
]
}Auth required: Yes
Returns avatar metadata (URL reference, not the full image data).
{
"ok": true,
"url": "/api/avatar/image",
"custom": true
}Auth required: Yes
Returns the avatar image as raw binary with proper Content-Type and Cache-Control headers. Use this endpoint in <img> tags instead of embedding base64 data.
Response: Raw image bytes (image/jpeg, image/png, or image/webp).
Headers:
Cache-Control: private, max-age=3600(1 hour browser cache)Content-Type: image/*(matches the uploaded format)
Auth required: Yes
Uploads a custom avatar image.
Request body:
{ "dataUrl": "data:image/png;base64,iVBORw0KGgo..." }Accepted formats: PNG, JPEG, WebP.
Response:
{
"ok": true,
"url": "/api/avatar/image",
"custom": true
}Triggers a WebSocket snapshot broadcast so connected clients refresh the avatar.
Auth required: Yes
Resets avatar to the default photo. Triggers a WebSocket broadcast.
Auth required: Yes (via cookie)
Ping:
{ "type": "ping" }Terminal input:
{ "type": "terminal-input", "data": "ls -la\n" }Terminal resize:
{ "type": "terminal-resize", "cols": 120, "rows": 32 }Dashboard snapshot (sent on connect):
{
"type": "snapshot",
"payload": { /* dashboard-state object */ }
}Live updates:
{
"type": "snapshot",
"payload": { /* updated dashboard-state */ }
}Terminal output (from PTY to client):
{
"type": "terminal-output",
"chunk": "root@hermes:~$ ",
"buffer": "...",
"ready": true,
"cwd": "/root/projects/hermes-control-interface",
"prompt": "root@hermes:/root/projects/hermes-control-interface# "
}Terminal transcript (sent on reconnect if session was active):
{
"type": "terminal-transcript",
"buffer": "...",
"ready": true,
"cwd": "...",
"prompt": "...",
"cols": 120,
"rows": 32
}Pong:
{ "type": "pong", "ts": 1712600000000 }Auth required: Yes
Returns the full kanban board for a given board name.
{
"ok": true,
"tasks": [{ "id": "t_...", "title": "...", "status": "done", "assignee": "david", ... }],
"links": [{ "parent_id": "t_...", "child_id": "t_..." }]
}Auth required: Yes
Returns a single task with full detail — runs, events, comments, attachments, links.
{
"ok": true,
"task": { "id": "t_...", "title": "...", "status": "done", ... },
"runs": [{ "id": 1, "status": "done", "outcome": "completed", "summary": "...", "metadata": {...} }],
"events": [{ "id": 1, "kind": "created", "payload": {...}, "created_at": ... }],
"comments": [{ "id": 1, "author": "david", "body": "Fixed the issue", "created_at": ... }],
"attachments": [{ "id": 1, "filename": "report.md", "size": 2048 }],
"links": [{ "parent_id": "t_...", "child_id": "t_..." }]
}Auth required: Yes
Reads a file from the task's workspace directory. Path traversal protected.
Directory listing (path ends with . or is a directory):
{
"ok": true,
"files": [{ "name": "script.py", "size": 15733, "isDir": false, "mtime": ... }],
"isDir": true
}File content (max 500KB, auto-detects language):
{
"ok": true,
"filename": "script.py",
"size": 15733,
"language": "py",
"content": "#!/usr/bin/env python3\n..."
}Auth required: Yes (CSRF required)
Quick actions on tasks. Body: { "action": "...", "assignee": "..." }
Valid actions: unblock, done, reopen, start, reassign
{ "ok": true, "action": "done", "taskId": "t_...", "board": "main" }Auth required: Yes
Returns agent health grid — model, provider, active/blocked tasks, gateway alive.
{
"ok": true,
"agents": [{ "name": "david", "model": "deepseek-v4-pro", "state": "idle", "activeTasks": 0, "blockedTasks": 0 }],
"timestamp": 1712600000000
}Auth required: Admin only
Returns live feed events from gateway logs (max 50).
{
"ok": true,
"events": [{ "timestamp": "2026-06-03 14:22:10", "agent": "david", "action": "web_search", "emoji": "🔍" }]
}Auth required: Yes
Board-level statistics with agent breakdown and recommendations.
{
"ok": true,
"overview": { "total": 19, "running": 1, "blocked": 1, "done": 13 },
"agents": [{ "name": "david", "active": 1, "done": 5 }],
"alerts": ["⚠️ 1 task blocked"],
"recommendations": ["Review blocked task t_..."]
}