Hermes API Reference
Hermes-Relay communicates with the Hermes API Server using the following endpoints. If the server is configured with API_SERVER_KEY, requests must include a Bearer token in the Authorization header. Most local setups don't require a key.
Base URL
http(s)://<server>:8642Authentication
Authorization: Bearer <API_SERVER_KEY> (optional — only if server has a key configured)How endpoints get served
Installing the plugin via install.sh is enough to make all of the endpoints below work — including the management ones (/api/sessions/*, /api/memory, /api/skills, /api/config, /api/available-models). The plugin wires the gateway up at install time so these are served on the same :8642 host as the standard /v1/* endpoints, with the same Authorization: Bearer … auth.
Chat streaming uses standard /v1/runs by default — it emits structured tool.started/tool.completed SSE events for live tool progress cards in the Android app. The app's Settings → Chat → Streaming endpoint = "Auto" (default) probes per-endpoint capability and picks the best chat path automatically; you can manually force Sessions or Runs mode for debugging.
Endpoints
Health Check
GET /healthReturns server health status. Used by the app to verify connectivity (green/red dot indicator).
Response: 200 OK with server info.
List Sessions
GET /api/sessionsReturns all chat sessions.
Response:
{
"sessions": [
{
"id": "uuid",
"title": "Session title",
"created_at": "2026-04-05T12:00:00Z",
"updated_at": "2026-04-05T12:30:00Z",
"message_count": 12
}
]
}Create Session
POST /api/sessionsCreates a new chat session.
Request body:
{
"title": "Optional title"
}Response: 201 Created with the new session object.
Get Messages
GET /api/sessions/{id}/messagesReturns message history for a session.
Response:
{
"messages": [
{
"id": "uuid",
"role": "user | assistant",
"content": "Message text",
"created_at": "2026-04-05T12:00:00Z",
"usage": {
"input_tokens": 150,
"output_tokens": 847
}
}
]
}Stream Chat
POST /api/sessions/{id}/chat/streamSends a message and streams the response via Server-Sent Events.
Request body:
{
"message": "Your message here",
"personality": "default"
}Response: SSE stream with the following event types:
| Event | Data |
|---|---|
session.created | { "session_id": "...", "run_id": "...", "title": "..." } |
run.started | { "session_id": "...", "run_id": "...", "user_message": { "id": "...", "role": "user", "content": "..." } } |
message.started | { "session_id": "...", "run_id": "...", "message": { "id": "...", "role": "assistant" } } |
assistant.delta | { "session_id": "...", "run_id": "...", "message_id": "...", "delta": "text chunk" } |
tool.progress | { "session_id": "...", "run_id": "...", "message_id": "...", "delta": "reasoning chunk" } |
tool.pending | { "session_id": "...", "run_id": "...", "tool_name": "...", "call_id": "..." } |
tool.started | { "session_id": "...", "run_id": "...", "tool_name": "...", "call_id": "...", "preview": "...", "args": {...} } |
tool.completed | { "session_id": "...", "run_id": "...", "tool_call_id": "...", "tool_name": "...", "args": {...}, "result_preview": "..." } |
tool.failed | { "session_id": "...", "run_id": "...", "call_id": "...", "tool_name": "...", "error": "..." } |
assistant.completed | { "session_id": "...", "run_id": "...", "message_id": "...", "content": "...", "completed": true, "partial": false, "interrupted": false } |
run.completed | { "session_id": "...", "run_id": "...", "message_id": "...", "completed": true, "partial": false, "interrupted": false, "api_calls": 3 } |
error | { "message": "error description", "error": "..." } |
done | { "session_id": "...", "run_id": "...", "state": "final" } |
Rename Session
PATCH /api/sessions/{id}Updates a session's title.
Request body:
{
"title": "New title"
}Delete Session
DELETE /api/sessions/{id}Permanently deletes a session and all its messages.
Response: 204 No Content