Skip to content

REST API reference

The manager exposes a single REST API rooted at /api. The SPA in web/ calls it; you can call it directly with any HTTP client. There is no GraphQL, no gRPC for application traffic (gRPC is only used for the geminio tunnel, internal to the manager).

This page is a route catalogue, not a hand-written swagger spec. Source of truth: cmd/ongrid/main.go (the chi.Router mounts) and internal/manager/server/*/http.go (the per-BC handlers). Click through to the handler for exact request/response struct fields.

Conventions

  • Base path: every route is prefixed /api. So GET /v1/edges is reached at https://<manager>/api/v1/edges.
  • Versioning: all routes are under /v1/. There is no /v2/. Backwards-incompatible changes ship behind feature flags or new routes.
  • Auth: bearer JWT in Authorization: Bearer .... Public routes (login, refresh, register, IM webhooks, Prometheus's auth_request probe) skip the middleware. Listed in the "Public" table below.
  • Roles: admin, user, viewer. Write routes require admin (or the relevant casbin action like edge:* / write); read routes accept any authed role. viewer can chat but the agent's toolbag is filtered to ClassSafe. See ADR-022 three-role RBAC.
  • Errors: JSON {"error":"code","message":"human text"}. Codes are stable enums (not_found, invalid_argument, unauthorized, forbidden, conflict).
  • Content type: every request and response is application/json unless explicitly noted (streamed chat is SSE, log/trace ingest is OTLP-protobuf or Loki-JSON).

Public routes (no auth)

MethodPathPurpose
GET/healthzliveness probe
GET/readyzreadiness probe
GET/internal/auth/dataplane-verifynginx auth_request probe for log/trace ingest
POST/api/v1/auth/loginexchange email+password for JWT
POST/api/v1/auth/refreshexchange refresh token for a fresh access token
POST/api/v1/auth/registerself-registration (gated by config)
GET/api/v1/prometheus/authnginx auth_request probe for the Grafana embed
POST/api/v1/im/feishu/eventsinbound Feishu/Lark callback; webhook signature is the auth

Authenticated routes

iam (users, orgs, sessions)

MethodPathRoleSource
GET/v1/versionanycmd/ongrid/main.go (inline)
GET/v1/meanyinternal/iam/server/http.go
GET/v1/selfanyinternal/iam/server/http.go
GET/v1/usersanylist users
POST/v1/usersadmincreate user
PATCH/v1/users/{id}adminupdate user (name, email)
PATCH/v1/users/{id}/passwordself or adminrotate password
PATCH/v1/users/{id}/roleadminchange role (admin/user/viewer)
DELETE/v1/users/{id}adminremove user
GET/v1/orgsanylist orgs
POST/v1/orgsadmincreate org
PATCH/v1/orgs/{id}adminupdate org
DELETE/v1/orgs/{id}adminremove org
GET/v1/orgs/{id}/membersanylist members
POST/v1/orgs/{id}/membersadminadd member
PATCH/v1/orgs/{id}/members/{user_id}adminchange member role
DELETE/v1/orgs/{id}/members/{user_id}adminremove member

edge (the tunnel-connected agent)

MethodPathRoleDescription
POST/v1/edgesedge:*create edge, issues access+secret keys
GET/v1/edgesanylist edges
GET/v1/edges/{id}anyget edge detail
DELETE/v1/edges/{id}edge:*delete edge
POST/v1/edges/{id}/rotate-secretedge:*rotate the secret key
POST/v1/edges/{id}/upgradeedge:*trigger remote agent upgrade with explicit URL+sha256
POST/v1/edges/{id}/upgrade-packageedge:*one-click bundle upgrade (ADR-024)
GET/v1/edges/{id}/processesanyread-only process list (on-demand RPC)
GET/v1/edges/{id}/pluginsanylist edge's configured + live plugins (with health)
PUT/v1/edges/{id}/plugins/{name}edge:pluginenable/disable + tune a plugin
GET/v1/integrations/plugin-countsanyglobal plugin enable/disable counts (for the homepage tile)

device (host entity, decoupled from tunnel state)

MethodPathRoleDescription
GET/v1/devicesanylist host devices
GET/v1/devices/{id}anyget device detail
PATCH/v1/devices/{id}device:*update display name, tags
DELETE/v1/devices/{id}device:*remove device
PATCH/v1/devices/{id}/rolesdevice:*assign roles (db, web, cache...)
GET/v1/devices/{id}/edgesanyedges currently representing this device
GET/v1/devices/{device_id}/shellwebshellopen a WebSSH stream (websocket upgrade)

topology (typed CMDB)

MethodPathRoleDescription
GET/v1/topology/node-typesanylist node-type schemas
POST/v1/topology/node-typestopology:*create node type
GET/v1/topology/node-types/{name}anyget one node type
DELETE/v1/topology/node-types/{name}topology:*remove node type
GET/v1/topology/nodesanylist nodes (filter by type, tag)
POST/v1/topology/nodestopology:*create node
GET/v1/topology/nodes/{id}anyget node
PATCH/v1/topology/nodes/{id}topology:*update node
DELETE/v1/topology/nodes/{id}topology:*remove node
GET/v1/topology/relation-typesanylist relation-type schemas
POST/v1/topology/relation-typestopology:*create relation type
GET/v1/topology/relation-types/{name}anyget one relation type
DELETE/v1/topology/relation-types/{name}topology:*remove relation type
GET/v1/topology/relationsanylist edges (relations)
POST/v1/topology/relationstopology:*create relation
GET/v1/topology/relations/{id}anyget relation
PATCH/v1/topology/relations/{id}topology:*update relation
DELETE/v1/topology/relations/{id}topology:*remove relation

alert (rules, incidents, channels)

MethodPathRoleDescription
GET/v1/alert-rulesanylist rules
POST/v1/alert-rulesalert:*create rule
GET/v1/alert-rules/{id}anyget rule
PUT/v1/alert-rules/{id}alert:*replace rule
DELETE/v1/alert-rules/{id}alert:*remove rule
POST/v1/alert-rules/{id}/enabledalert:*flip enabled flag
POST/v1/alert-rules/previewalert:*dry-run a rule definition against current data
GET/v1/alerts/incidentsanylist incidents (filters: status, severity, scope)
GET/v1/alerts/incidents/{id}anyget incident
GET/v1/alerts/incidents/{id}/eventsanyevent timeline
POST/v1/alerts/incidents/{id}/ackanyacknowledge
POST/v1/alerts/incidents/{id}/resolveanymark resolved
POST/v1/alerts/incidents/{id}/silenceanysilence for N hours
GET/v1/alerts/incidents/{id}/investigationanyget the AI-generated investigation report
POST/v1/alerts/incidents/{id}/investigationanytrigger or re-run the investigation
GET/v1/alerts/runtime-infoanyevaluator pace + last cycle stats
GET/v1/notification-channelsanylist channels
POST/v1/notification-channelschannel:*create channel
GET/v1/notification-channels/{id}anyget channel
PUT/v1/notification-channels/{id}channel:*replace channel
DELETE/v1/notification-channels/{id}channel:*remove channel
POST/v1/notification-channels/{id}/testchannel:*send a synthetic notification

See Alert rule schema for the JSON shape of a rule.

aiops (chat, agents, models)

MethodPathRoleDescription
GET/v1/agentsanylist agent personas
GET/v1/agents/{name}anyget persona detail
DELETE/v1/agents/{name}agent:*delete a built-in / disk persona (rare; usually only custom deletable)
POST/v1/agents/customagent:*create a user-defined persona
PATCH/v1/agents/custom/{name}agent:*update user persona
DELETE/v1/agents/custom/{name}agent:*delete user persona
GET/v1/chat/sessionsanylist sessions
POST/v1/chat/sessionsanycreate session
PATCH/v1/chat/sessions/{id}anyrename / tag a session
DELETE/v1/chat/sessions/{id}anydelete session
GET/v1/chat/sessions/{id}/messagesanymessage history
POST/v1/chat/sessions/{id}/messagesanysend a message (non-streaming, returns final reply)
POST/v1/chat/sessions/{id}/messages/streamanysend a message (SSE stream of token + tool-call events)
GET/v1/aiops/modelsanyavailable providers + models (gated by configured API keys)
POST/v1/aiops/query-translateanyLLM-assisted PromQL / LogQL / TraceQL composition
GET/v1/aiops/mentions/searchanyautocomplete for @edge, @device, @dashboard mentions
GET/v1/usage/todayanytoken usage for the current UTC day

See Agent persona format for the markdown frontmatter shape.

knowledge (RAG, vault, repos, uploads)

MethodPathRoleDescription
GET/v1/knowledge/docsanylist documents (tree)
POST/v1/knowledge/docsknowledge:*create document
GET/v1/knowledge/docs/{id}anyget document
PATCH/v1/knowledge/docs/{id}knowledge:*edit document body
PATCH/v1/knowledge/docs/{id}/moveknowledge:*move to another path
DELETE/v1/knowledge/docs/{id}knowledge:*remove document
GET/v1/knowledge/pathsanylist path nodes (for the tree)
GET/v1/knowledge/reposanylist Git repos
POST/v1/knowledge/reposknowledge:*register a repo
DELETE/v1/knowledge/repos/{id}knowledge:*remove repo
POST/v1/knowledge/repos/{id}/syncknowledge:*trigger a re-sync
POST/v1/knowledge/uploadknowledge:*upload .md / .txt / .pdf / .docx (parsed via docextract)
GET/v1/knowledge/searchanyRAG query (returns chunks + scores)
POST/v1/knowledge/vault/syncknowledge:*re-pull built-in vault from GitHub
GET/v1/knowledge/ssh-identitiesknowledge:*list SSH keys for Git auth
POST/v1/knowledge/ssh-identitiesknowledge:*register an existing SSH key
POST/v1/knowledge/ssh-identities/generateknowledge:*generate a new keypair (private key never leaves server)
PATCH/v1/knowledge/ssh-identities/{id}knowledge:*edit identity (name, comment)
DELETE/v1/knowledge/ssh-identities/{id}knowledge:*remove identity

skill (toolbag introspection)

MethodPathRoleDescription
GET/v1/skillsanylist skills (manager-scope + edge-scope)
GET/v1/skills/{key}anyget skill detail (schema, description, scope, class)
POST/v1/skills/{key}/executeskill:*direct skill execution (testing / debugging)

See Skill manifest for the on-disk skill.json shape.

logs / traces (read-only proxies)

MethodPathRoleDescription
GET/v1/logs/query_rangeanyproxied LogQL query_range
GET/v1/logs/labelsanyproxied label-names
GET/v1/logs/labels/{name}/valuesanyproxied label-values
GET/v1/traces/searchanyproxied TraceQL /api/search
GET/v1/traces/{trace_id}anyone trace by ID
GET/v1/traces/tags/{tag}/valuesanyproxied /api/search/tag/.../values

monitor (dashboards / panels)

MethodPathRoleDescription
GET/v1/monitor/panelsanylist panels
POST/v1/monitor/panelsmonitor:*create panel
PATCH/v1/monitor/panels/{id}monitor:*edit panel
DELETE/v1/monitor/panels/{id}monitor:*remove panel
GET/v1/observability/dashboards/{uid}anyrender-ready Grafana dashboard JSON

metric (per-edge metric snapshot)

MethodPathRoleDescription
GET/v1/edges/{id}/metricsanylatest closed-set host metric snapshot

prometheus (admin)

MethodPathRoleDescription
POST/v1/prometheus/launchadmin(re-)launch the embedded Prometheus
POST/v1/prometheus/query_rangeanyLLM-tool-facing query_range (returns normalised matrix)

imbridge (chat surfaces — Slack / Telegram / Lark / DingTalk / WeCom)

MethodPathRoleDescription
GET/v1/im/appsanylist connected IM apps
POST/v1/im/appsim:*register IM app
GET/v1/im/apps/{id}anyget app
PUT/v1/im/apps/{id}im:*update app
DELETE/v1/im/apps/{id}im:*remove app
POST/v1/im/apps/{id}/revealadminreveal masked secrets

marketplace (skill packs)

MethodPathRoleDescription
GET/v1/marketplace/registriesanylist configured registries
GET/v1/marketplace/installedanylist installed packs
POST/v1/marketplace/installmarketplace:*install pack from a registry
DELETE/v1/marketplace/installed/{pack_id}marketplace:*uninstall pack

setting (system settings: integrations, defaults, secrets)

MethodPathRoleDescription
GET/v1/system-settingsanylist visible settings
PUT/v1/system-settings/{category}/{key}adminupsert setting
DELETE/v1/system-settings/{category}/{key}adminremove setting
GET/v1/system-settings/{category}/{key}/revealadminreveal masked secret

integration (connectivity tests)

MethodPathRoleDescription
POST/v1/integrations/grafana/syncadminsync dashboards + datasources
POST/v1/integrations/grafana/testadmintest Grafana connection
POST/v1/integrations/llm/invalidateadmininvalidate cached LLM client (forces re-read of API keys)
POST/v1/integrations/loki/testadmintest Loki connection
POST/v1/integrations/prom/testadmintest Prometheus connection
POST/v1/integrations/tempo/testadmintest Tempo connection
POST/v1/integrations/websearch/testadmintest SearXNG / web-search backend

webshell (interactive shell over the tunnel)

MethodPathRoleDescription
GET/v1/devices/{device_id}/shellwebshellopen WebSocket-upgraded SSH stream
GET/v1/webshell/sessionsanylist active sessions
DELETE/v1/webshell/sessions/{id}webshellkill a session

audit (admin log)

MethodPathRoleDescription
GET/v1/admin/audit-logsadmintenant-wide audit trail (HLD-010)

Pagination

List endpoints use opaque cursors:

text
GET /v1/edges?limit=50&cursor=eyJpZCI6MTAwMH0

The response carries {"items":[...], "next_cursor":"...", "total":...}. next_cursor is empty on the last page.

Rate limits

There are no global rate limits in the open-source build. The LLM budget gate (ONGRID_LLM_DAILY_TOKEN_LIMIT) bounds chat traffic — every other endpoint depends on whatever you put in front of the manager (nginx, your own gateway).

Versioning

GET /v1/version returns {"manager_version":"vX.Y.Z"}. The SPA reads this and flags edges whose agent version drifts from the manager. Use it for upgrade tooling.

See also