REST API
41 endpoints under /api/v1/, plus 2 WebSocket endpoints. JSON in, JSON out. Full OpenAPI schema at /docs (Swagger UI) and /redoc on the running gateway.
When gateway.api_key is non-empty, include X-API-Key: <key> on all /api/* requests. The /health endpoint and all /ws/* WebSocket endpoints are always exempt.
Health
GET
/health
Gateway liveness check. Returns HTTP 200 when the gateway is running. No auth required.
json
{ "status": "ok", "version": "2.1.0", "agent": "NeuralCleave" }
Chat
POST
/api/v1/chat
Send a message to the agent and receive a complete response. For streaming, use the WebSocket endpoint instead.
json
// Request
{
"message": "What is the weather in Tokyo?",
"session_id": "optional-session-id",
"model": "claude-sonnet-4-6", // optional override
"channel": "api"
}
// Response
{
"response": "I don't have real-time weather access, but…",
"session_id": "abc123",
"model_used": "claude-sonnet-4-6",
"quality_score": 88,
"tokens": { "input": 142, "output": 96 }
}
WebSocket — /ws/chat
WS
/ws/chat
Bi-directional streaming chat. Connect, send a
hello frame, then send message frames and receive streamed message_chunk events followed by a terminal message_done event.json
// Client → Server: hello
{ "type": "hello", "session_id": "optional" }
// Client → Server: message
{ "type": "message", "content": "Hello!", "model": "optional-override" }
// Client → Server: ping (keepalive)
{ "type": "ping" }
// Server → Client: message_chunk (streaming token)
{ "type": "message_chunk", "delta": "Hello" }
// Server → Client: message_done (end of response)
{ "type": "message_done", "session_id": "abc123", "quality_score": 92 }
// Server → Client: pong
{ "type": "pong" }
Memory
| Method | Path | Description |
|---|---|---|
| GET | /api/v1/memory | List rows. Query: session_id, tag, type, limit (default 50) |
| GET | /api/v1/memory/search | FTS5 full-text search. Query: q, limit |
| POST | /api/v1/memory | Store a memory row manually |
| DELETE | /api/v1/memory/{id} | Delete a memory row by ID |
| DELETE | /api/v1/memory/session/{id} | Delete all rows for a session |
| POST | /api/v1/memory/compact | Trigger session compaction |
Channels
| Method | Path | Description |
|---|---|---|
| GET | /api/v1/channels | List adapters, connection status, and ping result |
| GET | /api/v1/channels/{name} | Adapter detail — status + config schema |
| POST | /api/v1/channels/{name}/send | Send via a channel. Body: {"target","text"} |
Plugins
| Method | Path | Description |
|---|---|---|
| GET | /api/v1/plugins | List loaded plugins and their tools |
| GET | /api/v1/plugins/{name} | Plugin detail — metadata, tools, load status |
| POST | /api/v1/plugins/reload | Hot-reload all plugins |
| POST | /api/v1/plugins/{name}/reload | Hot-reload a single plugin |
Hub
| Method | Path | Description |
|---|---|---|
| GET | /api/v1/hub/packages | List registry packages. Returns {"available":true,"packages":[...]} |
| GET | /api/v1/hub/search | Search by name/tag. Query: q |
| POST | /api/v1/hub/install | Install a package. Body: {"name","url"} |
| DELETE | /api/v1/hub/{name} | Uninstall a package |
| GET | /api/v1/hub/{name} | Package detail — version, tags, enabled status |
| PATCH | /api/v1/hub/{name} | Enable/disable a package. Body: {"enabled":bool} |
| POST | /api/v1/hub/scan | PackageScanner safety scan. Body: {"code":"..."} |
| GET | /api/v1/hub/status | Hub status — total packages, enabled count |
Orchestrator
| Method | Path | Description |
|---|---|---|
| GET | /api/v1/orchestrator/nodes | List all nodes with routing config |
| POST | /api/v1/orchestrator/nodes | Register a new node |
| DELETE | /api/v1/orchestrator/nodes/{name} | Remove a node |
| PATCH | /api/v1/orchestrator/nodes/{name} | Update node config (enable/disable, priority, etc.) |
| POST | /api/v1/orchestrator/route | Test routing. Body: {"task_type","channel"} |
| GET | /api/v1/orchestrator/status | Orchestrator health + per-node request counters |
| GET | /api/v1/orchestrator/nodes/{name}/memory | Node memory namespace stats |
| DELETE | /api/v1/orchestrator/nodes/{name}/memory | Clear a node's memory namespace |
| GET | /api/v1/orchestrator/namespaces | All namespaces + aggregate stats |
Canvas
| Method | Path | Description |
|---|---|---|
| GET | /api/v1/canvas/state | Current canvas blocks. Returns {"available":true,"blocks":[...],"count":N} |
| POST | /api/v1/canvas/render | Render a block. Body: {"type","content"}. Returns 201. |
| DELETE | /api/v1/canvas/clear | Clear all blocks. Returns 204. |
| GET | /api/v1/canvas/status | Block count + connected WebSocket viewers |
WS
/ws/canvas
Canvas real-time stream. On connect, receives full current state. Subsequently receives
add and clear broadcast events as blocks are rendered by the LLM.Settings
| Method | Path | Description |
|---|---|---|
| GET | /api/v1/settings | All current settings (non-secret fields) |
| POST | /api/v1/settings/model | Override model. Body: {"provider","model"} |
| POST | /api/v1/settings/privacy | Toggle privacy mode. Body: {"enabled":bool} |
Metrics
GET
/api/v1/metrics
Returns all 13 Prometheus metrics in the standard Prometheus text/plain format. Compatible with
prometheus.yml scrape config directly. See Observability.Push Notifications (PWA)
| Method | Path | Description |
|---|---|---|
| GET | /api/v1/push/vapid-public-key | VAPID public key for Web Push subscription |
| POST | /api/v1/push/subscribe | Register a push subscription |
| DELETE | /api/v1/push/subscribe | Unregister a push subscription |
| GET | /api/v1/push/subscriptions | List active push subscriptions |
| POST | /api/v1/push/notify | Send a push notification. Body: {"title","body"} |
Sessions
| Method | Path | Description |
|---|---|---|
| GET | /api/v1/sessions | List active WebSocket sessions |
| DELETE | /api/v1/sessions/{id} | Disconnect and remove a session |
The full interactive API reference is available at http://localhost:7432/docs (Swagger UI) and http://localhost:7432/redoc when the gateway is running.