API guide
Everything Yagra does is driven through one REST API. This page covers how to authenticate against it and the conventions every endpoint follows; the per-endpoint details live in the generated API reference, and AI assistants get their own surface — the MCP server.
The northbound API
Section titled “The northbound API”The API is served by core on the API port (8080 in the bundled compose files), with every path
under the /api/v1 prefix — about 206 endpoints, plus the two unversioned health probes
GET /healthz (liveness) and GET /readyz (readiness; in a high-availability pair only the
leader answers 200, so a load balancer can route to it).
Everything the WebUI does goes through this same API. There is no private backchannel: every
inventory screen, dashboard, alert action, and settings page is a sequence of /api/v1 calls, so
anything you can see or do in the browser you can automate. When in doubt about how to do something
programmatically, doing it once in the WebUI with the browser’s network tab open shows the exact
requests.
Authentication
Section titled “Authentication”Two credentials authenticate this API, both sent as Authorization: Bearer <token>:
- a session token, exchanged for a username and password — short-lived, and what the WebUI uses;
- an API token (
yat_…, minted under Settings ▸ API tokens) — long-lived, for unattended clients. Use this one for scripts, CI jobs and integrations.
Session tokens
Section titled “Session tokens”Exchange a username and password for a bearer session token at POST /api/v1/auth/login:
curl -s http://<yagra-host>:8080/api/v1/auth/login \ -H "Content-Type: application/json" \ -d '{"username": "admin", "password": "your-password"}'{ "token": "<session-token>", "role": "admin" }Send that token on every subsequent request:
curl -s http://<yagra-host>:8080/api/v1/nodes \ -H "Authorization: Bearer <session-token>"The response also carries the account’s role, so a client knows up front what it will be allowed
to do. Login is rate-limited per account and globally — too many attempts answer 429 with a
Retry-After header — and POST /api/v1/auth/logout revokes the token.
API tokens
Section titled “API tokens”For anything unattended, mint an API token instead of scripting a login. An admin creates one under Settings ▸ API tokens; the raw value is shown once and never again. Send it exactly like a session token:
curl -s http://<yagra-host>:8080/api/v1/nodes \ -H "Authorization: Bearer yat_…"Four things about a token are worth knowing before you issue one:
- It names the surfaces it may be used at. A token reaches this REST API only if it was created
with the
restsurface. Tokens created before that field existed carrymcpalone and answer401here — an upgrade never widens what an existing credential can do. - It acts as an account. Every token has an owner. Its effective role is the lower of the token’s role and the owner’s current role, so demoting the account narrows the token immediately, and disabling or deleting the account revokes it. Prefer a service account as the owner (see Users & SSO) so an integration does not depend on the person who set it up.
- It cannot administer users.
POST /api/v1/users, the API-token endpoints themselves, and anything else behind the user-management permission answer403 token_not_permittedto a token, whatever its role — a credential that could mint its own successor would survive revoking the original. - It has no interactive identity. Endpoints that mean “the signed-in account” —
GET /api/v1/auth/meand the personal dashboard — answer403 session_required.
An optional expiry (expires_at) is offered when creating one, and omitting it still means no
expiry. Revoke a token from the same page at any time; revocation takes effect immediately.
A few endpoints are deliberately unauthenticated, because a client needs them before it can log in and none of them reveal inventory, configuration, or state:
| Endpoint | Returns |
|---|---|
GET /api/v1/version |
The running core version |
GET /api/v1/config |
Client bootstrap flags (whether auth, SSO, and AI analysis are available) — no secrets |
GET /api/v1/openapi.json |
The generated OpenAPI document (below) |
GET /healthz, GET /readyz |
Liveness and readiness probes |
If the deployment runs with the public-dashboard option, read endpoints open up without a token; every write stays authenticated.
Conventions
Section titled “Conventions”The whole surface follows one set of rules, so what you learn on one endpoint carries to the rest:
-
JSON everywhere. Request bodies and responses are JSON; set
Content-Type: application/jsonwhen sending a body. -
Creation returns
201with the new resource’s id:{"id": "<uuid>"}. -
Deletion returns
204 No Content— no body, and deletes are idempotent where that is safe. -
Errors are typed. Every failure renders the same envelope:
{ "error": { "code": "invalid_filter", "message": "…" } }The
codeis stable and machine-readable — branch on it, not on the message. Themessageis operator-safe prose and never carries internal error text. Status codes follow the usual meanings:400malformed input,401unauthenticated,403authenticated but not permitted,404no such resource,409conflict,429throttled (with aRetry-Afterheader),502an upstream store or provider failed (distinct from500, a fault in Yagra itself), and503an optional subsystem this deployment has not configured. -
Authentication is checked before availability. An endpoint whose subsystem is unconfigured answers
503only to a caller who is already authenticated and permitted; an anonymous request gets401regardless. This is deliberate — the deployment does not disclose which subsystems it runs to a caller holding no credential. (Before v0.1.19 the two checks ran in the other order on most endpoints.) -
Large lists are enveloped and capped. A listing that could grow unbounded returns
{"items": [...], "total": <n>, "truncated": <bool>}rather than a bare array — for exampleGET /api/v1/thresholdsreturns at most 500 rules per request, withtotalcarrying the unfiltered count. A?limit=parameter can narrow a cap, never widen it. -
Timestamps are RFC 3339 strings (
2026-08-01T09:30:00Z) in responses and in query parameters that take a time.
Roles and permissions
Section titled “Roles and permissions”Every request is authorized per endpoint by the role the token carries:
- Viewer — read-only: inventory, metrics, alerts, events, flows.
- Operator — Viewer plus incident response: acknowledge and mute alerts, open and close maintenance windows, run Troubleshoot analyses and AI root-cause explanations.
- Admin — full control: nodes, profiles, thresholds, credentials, users, and the audit log.
A request with a valid token but an insufficient role answers 403 — distinguishable from the
401 an unauthenticated request gets. State-changing requests are recorded in the audit log
automatically. The full role and permission model, including single sign-on, is described in
Users & SSO.
The OpenAPI document
Section titled “The OpenAPI document”The API publishes its own contract at GET /api/v1/openapi.json — an OpenAPI 3.1 document
covering every path, query parameter, request body, response shape, and error code. It is
generated from the handlers themselves, so it describes what the server actually does and
cannot drift from the code; the WebUI’s own types and API client are generated from this same
document. It contains no inventory, configuration, or state, so it is served unauthenticated and
is identical on every deployment.
Point any OpenAPI client generator at it to get a typed client in your language:
curl -s http://<yagra-host>:8080/api/v1/openapi.json -o yagra-openapi.jsonThe same document is served on this site at /openapi.json, so you can generate
a client without a running deployment.
Browse the reference
Section titled “Browse the reference”The per-endpoint reference — every route with its parameters, bodies, and responses, grouped by domain — is generated from that same document and lives at /docs/api/reference/, right below this page in the sidebar. Because it is generated, it is always in step with the release it documents.
Compatibility and changes
Section titled “Compatibility and changes”Behavior changes an API client could notice — response shapes, status codes, defaults, the meaning
of a query parameter, removed endpoints — are always listed in the release notes, each under
the version that shipped it. Recent examples of the kind of thing to look for: a bare-array
response gaining an envelope and a cap, delete and create endpoints aligning on 204/201,
endpoints nothing called being removed outright, and a list field being replaced by a more precise
one rather than deprecated in place — nodes.source became nodes.kind in v0.2.1, and the old
two-valued field is gone in the same release. Skim the notes for the versions you are crossing
before upgrading a deployment your automation talks to; see the changelog for
where they live. Regenerating your client from the new deployment’s /api/v1/openapi.json picks
up the shape changes mechanically.
The MCP tool surface
Section titled “The MCP tool surface”For AI assistants there is a second, purpose-built surface: an opt-in MCP server at /mcp
that exposes monitoring state as tools — mostly read-only queries plus a few audited actions — so
a client like Claude Code or Claude Desktop can answer “which nodes are down?” directly. It takes
the same yat_… API tokens, and a token can name both surfaces or just one; keeping an assistant’s
credential to mcp alone is the reason that field exists. It has its own page:
MCP server.