Skip to main content

REST API Reference

The NeoMind backend serves a REST API on Axum. This page is an integrator's overview: base URL, auth, unified response format, and endpoint groups by business domain. For the full interactive reference, see Swagger UI.

Entry Points​

ItemValue
Base URLhttp://<SERVER_IP>:9375/api
Swagger UI (interactive)http://<SERVER_IP>:9375/api/docs
Default port9375 (override with --port or the PORT env var)

Every endpoint path starts with /api. The endpoint lists below omit the /api prefix.

Authentication​

Two schemes:

1. JWT (User Session)​

Default for the Web UI:

POST /api/auth/login    { "username": "...", "password": "..." }
β†’ returns a JWT
Subsequent requests add the header:
Authorization: Bearer <jwt>

2. API Key (Programmatic)​

For scripts / 3rd-party integrations:

  • Generate a key under Settings β†’ API Keys
  • Send the header on every request:
X-API-Key: <key>

API Keys are independent of user sessions and can be scoped and set to expire.

Public Endpoints (No Auth)​

A handful of endpoints are open:

  • /api/health / /health/status / /health/live / /health/ready
  • /api/system/network-info
  • /api/auth/status / /auth/verify
  • /api/auth/login / /auth/register
  • /api/setup/* (first-run wizard)
  • /api/llm-backends/types
  • /api/messages/channels/types
  • /api/extensions
  • /api/capabilities / /capabilities/:name
  • /api/tools

Unified Response Format​

Success​

{
"success": true,
"data": { /* business payload */ },
"meta": { /* optional: pagination / count / timestamps */ }
}

Integration note: the CLI wraps an extra data layer β€” integrators extracting from data.data should be aware. The raw HTTP response is as shown above.

Failure​

{
"success": false,
"error": {
"code": "DEVICE_NOT_FOUND",
"message": "Device with id 'xxx' not found"
}
}

HTTP status codes follow convention: 4xx client errors, 5xx server errors. Pull the human-readable text from error.message.

Field Naming Convention​

Important gotcha: the backend returns snake_case (e.g. data_source), the frontend uses camelCase (e.g. dataSource). The frontend converts every API response via web/src/store/persistence/types.ts::fromDashboardDTO(). When you parse the JSON yourself as an integrator, trust the backend's snake_case.

Main Endpoint Groups​

Auth​

MethodPathDescription
POST/auth/loginLogin, get JWT
POST/auth/registerRegister (first user becomes admin)
GET/auth/statusCurrent auth status
GET/auth/verifyVerify JWT validity

Devices​

MethodPathDescription
GET/devicesList devices
POST/devicesCreate device (requires connection_config: {} even if empty)
GET/devices/:idDevice detail (metrics + commands)
PUT/devices/:idUpdate device
DELETE/devices/:idDelete device
GET/devices/:id/historyTelemetry history (?metric=&time_range=)
POST/devices/:id/controlSend command ({"command": "...", "params": {...}})
POST/devices/:id/webhookPush data via webhook (no auth)
GET/devices/typesList device types
POST/devices/typesCreate device type
GET/devices/draftsPending drafts (auto-discovered)
POST/devices/drafts/:id/approveApprove a draft

Dashboards​

MethodPathDescription
GET/dashboardsList dashboards
POST/dashboardsCreate dashboard
GET/dashboards/:idDashboard detail
PUT/dashboards/:idUpdate dashboard (including layout)
DELETE/dashboards/:idDelete dashboard
POST/dashboards/:id/shareGenerate a share link (with expiration)
GET/dashboards/shared/:tokenAccess a shared dashboard (no auth)

Rules​

MethodPathDescription
GET/rulesList rules
POST/rulesCreate rule β€” JSON body (name / trigger / condition / actions)
GET/rules/:idRule detail
PUT/rules/:idUpdate rule
DELETE/rules/:idDelete rule
POST/rules/:id/testDry-run the rule (no real action)

Rules use JSON format (not a DSL string). Example POST body:

{
"name": "High Temp Alert",
"trigger": { "trigger_type": "data_change" },
"condition": { "condition_type": "comparison", "source": "device:sensor-01:temperature", "operator": "greater_than", "threshold": 30 },
"actions": [ { "type": "notify", "message": "Too hot" } ]
}

Condition types: comparison / range / logical. Action types: notify / execute / trigger_agent. Trigger types: data_change / schedule / manual.

Agents​

MethodPathDescription
GET/agentsList agents
POST/agentsCreate agent
GET/agents/:idAgent detail
PUT/agents/:idUpdate agent
DELETE/agents/:idDelete agent
POST/agents/:id/statusControl execution (body {"status": "active"} / "paused")
GET/agents/:id/executionsExecution history

Required fields for create: user_prompt (required), schedule: {"schedule_type": "..."} (required). When no resources are bound, also set execution_mode: "free".

LLM Backends​

MethodPathDescription
GET/llm-backendsList backends
POST/llm-backendsAdd backend (Ollama / OpenAI / Anthropic / …)
GET/llm-backends/:idBackend detail (includes probed capabilities)
PUT/llm-backends/:idUpdate backend
DELETE/llm-backends/:idDelete backend
PATCH/llm-backends/:id/capabilitiesManually override capability (body {"multimodal": true} / false / null, null clears)

Messages​

MethodPathDescription
GET/messagesMessage list
GET/messages/channelsList notification channels
POST/messages/channelsAdd a channel (webhook/email/telegram/wecom/dingtalk/slack/feishu)
PUT/messages/channels/:idUpdate channel
DELETE/messages/channels/:idDelete channel
POST/messages/channels/:id/testTest channel delivery
POST/messages/sendSend a message manually

Extensions​

MethodPathDescription
GET/extensionsList installed extensions
GET/extensions/typesEnumerate extension types
POST/extensions/discoverScan the extensions directory
GET/extensions/:idExtension detail
GET/extensions/:id/healthHealth check
GET/extensions/:id/commandsList extension commands
POST/extensions/:id/commands/:cmdExecute an extension command
GET/extensions/:id/componentsDashboard components provided by the extension

Data Push​

MethodPathDescription
GET/data-pushList push targets
POST/data-pushCreate a push target (Webhook or MQTT)
GET/data-push/:idDetail
PUT/data-push/:idUpdate
DELETE/data-push/:idDelete
POST/data-push/:id/testPush once as a test
POST/data-push/:id/startStart
POST/data-push/:id/stopStop
GET/data-push/:id/logsDelivery logs

Storage & System​

MethodPathDescription
GET/settings/*System settings (retention policy, etc.)
GET/system/infoSystem info (MQTT / network / webhook)
GET/system/network-infoNetwork info

Realtime API​

In addition to REST, NeoMind exposes:

  • WebSocket: ws://<host>:9375/api/events β€” dashboard live data, device state changes
  • SSE: GET /api/events (Server-Sent Events) β€” same event stream over plain HTTP
  • MQTT: connect directly to mqtt://<host>:1883 and subscribe to device topics

The canonical reference for the realtime protocol (WebSocket / SSE) is the frontend implementation: web/src/lib/events.ts and web/src/lib/websocket.ts.

Error Handling Example​

import requests

resp = requests.post(
"http://host:9375/api/devices",
json={"name": "sensor", "device_type": "temp", "connection_config": {}},
headers={"X-API-Key": KEY},
)
data = resp.json()
if not data.get("success"):
err = data["error"]
print(f"[{err['code']}] {err['message']}")
else:
device = data["data"]

Next Steps​

  • Full interactive docs: /api/docs (Swagger) β€” every endpoint + parameter schema + live try-it
  • Adding a new endpoint β†’ add a handler under crates/neomind-api/src/, follow the existing per-module pattern
  • Realtime push β†’ WebSocket / SSE (see web/src/lib/websocket.ts)

Last updated: 2026-06-15