API Reference β
Complete list of Rounds authentication and authorization endpoints.
Conventions β
- Base path:
/api/ - Auth: cookie-based (
openobs_session) OR bearer token (Authorization: Bearer openobs_sa_.../Authorization: Bearer openobs_pat_...) ORX-Api-Key: TOKENheader. - Org context:
X-Openobs-Org-Id: ORG_UIDheader (optional; defaults to the user's default org). - Errors:
{ "message": "string" }with appropriate HTTP status. - List pagination:
?perpage=N&page=1. Responses include{ totalCount, ...items }or equivalent.
Legend β
| Symbol | Meaning |
|---|---|
| π | Public (no auth required) |
| πͺ | Cookie session required |
| π | API key or cookie |
| β | Server admin only |
| π’ | Org admin only |
| π | requirePermission(...) gate |
Public / auth flow β
π POST /api/login β
Local password login.
Body: { "user": "email or login", "password": "string" }200: { "message": "Logged in", "redirectUrl": "/..." } + Set-Cookie: openobs_session=...401: { "message": "invalid username or password" }429: { "message": "too many login attempts" }
π GET /api/login/providers β
Lists enabled authentication methods.
200: [{ "id": "local" | "github" | "google" | "generic" | "saml" | "ldap", "name": "...", "enabled": boolean, "url": "/api/login/ID" }]
π GET /api/login/:provider β
Initiates OAuth flow. Redirects to the provider's authorize URL.
π GET /api/login/:provider/callback β
OAuth callback. Exchanges code, creates/links user, issues session cookie, redirects to root.
π GET /api/saml/metadata β
SP metadata XML for SAML IdP configuration.
π POST /api/saml/acs β
SAML assertion consumer. Validates signed response, creates/links user, issues session, redirects.
π GET /api/saml/slo / POST /api/saml/slo/callback β
Single logout initiation + callback.
πͺ POST /api/logout / GET /api/logout β
Revokes current session; clears cookie.
Current user β
πͺ GET /api/user β
Returns the authenticated user profile + org list.
200:
{
"id": "u_abc",
"email": "...",
"login": "...",
"name": "...",
"theme": "dark" | "light",
"orgId": "org_main",
"isGrafanaAdmin": false,
"orgs": [{ "orgId": "...", "name": "...", "role": "Admin" }],
"authLabels": ["OAuth GitHub"],
"isDisabled": false,
"avatarUrl": "..."
}πͺ PUT /api/user β
Update own profile.
Body: { "name"?: string, "email"?: string, "login"?: string }
πͺ PUT /api/user/password β
Change password. Revokes all other sessions on success.
Body: { "oldPassword": string, "newPassword": string }
πͺ GET /api/user/preferences / PUT /api/user/preferences β
Get or update preferences.
Body (PUT): { "homeDashboardUid"?: string, "timezone"?: string, "theme"?: "light" | "dark" | "" }
πͺ GET /api/user/permissions β
Returns the user's effective permissions in the current org.
200: { "dashboards:read": ["dashboards:*"], "folders:write": ["folders:uid:f1"], ... }
πͺ POST /api/user/using/:orgId β
Switch the user's default org.
200: { "message": "active organization changed" }
πͺ GET /api/user/auth-tokens / DELETE /api/user/auth-tokens/:id β
List / unlink external login links (OAuth, SAML, LDAP).
πͺ GET /api/user/tokens β
List active sessions for the current user.
πͺ POST /api/user/revoke-auth-token β
Revoke a specific session.
Body: { "authTokenId": string }
πͺ GET /api/user/access-tokens / POST /api/user/access-tokens / DELETE /api/user/access-tokens/:id β
Personal access token lifecycle.
Body (POST): { "name": string, "secondsToLive"?: number }201: { "id": string, "name": string, "key": "openobs_pat_..." } β plaintext returned ONCE.
Organizations β
β GET /api/orgs β
List all orgs.
200: { "totalCount": N, "orgs": [{ "id", "name", "...": ... }] }
β POST /api/orgs β
Create org. Seeds RBAC, adds creator as Admin.
Body: { "name": string }201: { "id": string, "name": string, ... }
π’ GET /api/orgs/:id / GET /api/orgs/name/:name β
Get org by id or name.
π’ PUT /api/orgs/:id β
Update org name / address / billing email.
β DELETE /api/orgs/:id β
Delete org. Cascades to all org-scoped resources.
π’ GET /api/orgs/:id/users β
List org members.
π’ POST /api/orgs/:id/users β
Add a user to an org.
Body: { "loginOrEmail": string, "role": "Admin" | "Editor" | "Viewer" | "None" }
π’ PATCH /api/orgs/:id/users/:userId β
Change a user's role in an org.
Body: { "role": "Admin" | "Editor" | "Viewer" | "None" }
π’ DELETE /api/orgs/:id/users/:userId β
Remove user from org.
Current org (scoped by X-Openobs-Org-Id or user default) β
πͺ GET /api/org / PUT /api/org β
Get / update the active org.
πͺ GET /api/org/users β
List users in current org.
πͺ POST /api/org/users β
Invite user to current org. Body same as /api/orgs/:id/users.
πͺ PATCH /api/org/users/:userId / DELETE /api/org/users/:userId β
Update role / remove user in current org.
πͺ GET /api/org/preferences / PUT /api/org/preferences β
Org preferences.
Admin (server admin) β
β GET /api/admin/users β
List all users across all orgs.
β POST /api/admin/users β
Create a local user (any org).
Body: { "name": string, "login": string, "email": string, "password": string }
β PATCH /api/admin/users/:userId β
Update user name / email / login.
β DELETE /api/admin/users/:userId β
Delete user.
β POST /api/admin/users/:userId/password β
Force password reset.
Body: { "password": string }
β POST /api/admin/users/:userId/permissions β
Toggle server-admin flag.
Body: { "isGrafanaAdmin": boolean }
β POST /api/admin/users/:userId/disable / /enable β
Enable/disable a user. Disabling revokes all active sessions.
β POST /api/admin/users/:userId/logout β
Revoke all of the user's sessions.
β GET /api/admin/users/:userId/auth-tokens / POST /api/admin/users/:userId/revoke-auth-token β
Inspect / revoke specific user sessions.
β GET /api/admin/audit-log β
Query the audit log.
200: { totalCount, items: [AuditLogEntry] }
β GET /api/admin/stats / GET /api/admin/settings β
Server stats and runtime settings.
Teams β
π GET /api/teams/search β
List teams in current org. Permission: teams:read.
π POST /api/teams β
Create team. Permission: teams:create.
Body: { "name": string, "email"?: string }
π GET /api/teams/:id / PUT /api/teams/:id / DELETE /api/teams/:id β
Get / update / delete. Permissions: teams:read / :write / :delete with scope teams:id:ID.
π GET /api/teams/:id/members / POST /api/teams/:id/members β
List / add members. POST body: { "userId": string }.
π PUT /api/teams/:id/members/:userId / DELETE /api/teams/:id/members/:userId β
Update (permission: 0=Member, 4=Admin) / remove.
π GET /api/teams/:id/preferences / PUT /api/teams/:id/preferences β
Team preferences (home dashboard, timezone, theme).
Service accounts β
π GET /api/serviceaccounts/search β
List SAs in current org.
π POST /api/serviceaccounts β
Create SA. Permission: serviceaccounts:create.
Body: { "name": string, "role": "Admin" | "Editor" | "Viewer", "isDisabled"?: boolean }201: { "id": string, "name": string, "login": "sa-...", "role": "..." }
π GET /api/serviceaccounts/:id / PATCH /api/serviceaccounts/:id / DELETE /api/serviceaccounts/:id β
Get / update / delete.
π GET /api/serviceaccounts/:id/tokens β
List SA's tokens (metadata only; never plaintext).
π POST /api/serviceaccounts/:id/tokens β
Issue a new token.
Body: { "name": string, "secondsToLive"?: number }201: { "id": string, "name": string, "key": "openobs_sa_..." } β plaintext returned ONCE.
π DELETE /api/serviceaccounts/:id/tokens/:tokenId β
Revoke token.
β POST /api/serviceaccounts/migrate β
Bulk-migrate legacy API_KEYS env-var tokens to SAs. Idempotent.
Legacy API keys (compat) β
π GET /api/auth/keys / POST /api/auth/keys / DELETE /api/auth/keys/:id β
Pre-SA-era API keys. New code should use service accounts instead. Thin shim: POST auto-provisions a hidden legacy-NAME SA.
Access control (RBAC) β
π GET /api/access-control/roles β
List roles in current org + global.
π POST /api/access-control/roles β
Create custom role. Permission: roles:write. Name MUST start with custom:.
Body:
{
"uid": "custom:prod_monitor",
"name": "custom:prod_monitor",
"displayName": "Prod Monitor",
"description": "...",
"groupName": "monitoring",
"permissions": [{ "action": "dashboards:read", "scope": "folders:uid:prod" }]
}π GET /api/access-control/roles/:roleUid β
Get role details including permission list.
π PUT /api/access-control/roles/:roleUid β
Update custom role. Requires version match; 409 on optimistic-lock fail.
π DELETE /api/access-control/roles/:roleUid β
Delete custom role. Built-in / fixed / managed roles refuse delete.
π GET /api/access-control/users/:userId/roles / POST /api/access-control/users/:userId/roles / DELETE /api/access-control/users/:userId/roles/:roleUid / PUT /api/access-control/users/:userId/roles β
Inspect / assign / unassign / bulk-replace roles for a user.
POST body: { "roleUid": string, "global"?: boolean } PUT body: { "roleUids": string[] }
π GET /api/access-control/teams/:teamId/roles / same CRUD pattern β
Role assignments for a team.
π GET /api/access-control/users/:userId/permissions β
Inspect a specific user's resolved permissions (server admin).
π GET /api/access-control/status β
200: { "enabled": true, "rbacEnabled": true }
β POST /api/access-control/seed β
Re-run built-in + fixed role seeding for the current org. Idempotent.
Folders β
π GET /api/folders β
List root folders or children of a parent.
π POST /api/folders β
Body: { "uid"?: string, "title": string, "parentUid"?: string }
π GET /api/folders/:uid / GET /api/folders/:uid/counts β
Folder details; counts returns dashboard + subfolder counts.
π PUT /api/folders/:uid β
Body: { "title"?: string, "description"?: string, "parentUid"?: string }
Moving folders validated against cycle + max-depth=8.
π DELETE /api/folders/:uid?forceDeleteRules= β
Delete folder. If it contains alert rules and forceDeleteRules=false, returns 400.
π GET /api/folders/:uid/permissions / POST /api/folders/:uid/permissions β
List / set (bulk replace) folder permissions.
Body (POST):
{
"items": [
{ "userId": "...", "permission": 1 | 2 | 4 },
{ "teamId": "...", "permission": 2 },
{ "role": "Viewer", "permission": 1 }
]
}Dashboard permissions β
π GET /api/dashboards/uid/:uid/permissions / POST /api/dashboards/uid/:uid/permissions β
Same body shape as folder permissions. Response lists direct AND inherited-from-folder grants.
Datasource permissions β
π GET /api/datasources/:uid/permissions / POST /api/datasources/:uid/permissions β
No folder cascade β datasources are flat.
Actions mapped: Viewβdatasources:query, Editβdatasources:write, Adminβdatasources.permissions:write.
Alert rule permissions β
π GET /api/access-control/alert.rules/:folderUid/permissions / POST ... β
Alert rules inherit from folder, so permissions are folder-scoped.
Setup / bootstrap β
π GET /api/setup/config β
Current setup state.
π POST /api/setup/admin β
One-shot endpoint to create the first administrator. Returns 409 if any user already exists.
Body: { "name": string, "login"?: string, "email": string, "password": string }201: { "userId": string, "orgId": "org_main" } + session cookie.
π POST /api/setup/config β
Save platform settings (LLM, datasources, notifications).
π POST /api/setup/complete β
Mark setup as complete.
Quotas β
π GET /api/orgs/:orgId/quotas / PUT /api/orgs/:orgId/quotas/:target β
Org-level quota management. limit=-1 means unlimited.
Quota targets: users, dashboards, datasources, api_keys, service_accounts, alert_rules, folders.
π GET /api/user/quotas / POST /api/admin/users/:userId/quotas β
User-level quotas.
Audit log entry shape β
interface AuditLogEntry {
id: string
timestamp: string // ISO-8601
action: string // e.g. "user.login", "team.member_added"
actorType: "user" | "service_account" | "system"
actorId: string | null
actorName: string | null
orgId: string | null
targetType: string | null
targetId: string | null
targetName: string | null
outcome: "success" | "failure"
metadata: Record<string, unknown> | null
ip: string | null
userAgent: string | null
}Status codes β
| Code | Meaning |
|---|---|
| 200 / 201 / 204 | Success |
| 400 | Validation error |
| 401 | Unauthenticated |
| 403 | Authorization failure (permission / quota / disabled) |
| 404 | Resource not found |
| 409 | Conflict (uniqueness, optimistic-lock, SA already exists) |
| 429 | Rate limit |
| 500 | Internal error (redacted message) |
| 501 | Not implemented (reserved β all endpoints above are implemented) |
Token format cheatsheet β
| Token | Format | Where to use |
|---|---|---|
| Session (cookie) | opaque, HttpOnly, 30d max | Browser-driven calls |
| SA token | openobs_sa_BASE64URL | Bot / script calls |
| PAT | openobs_pat_BASE64URL | CLI / personal scripts |
All three authenticate via Authorization: Bearer TOKEN OR X-Api-Key: TOKEN; session cookie is also accepted automatically when present.
Related docs β
- Authentication β operator guide for users, roles, OAuth, sessions, and troubleshooting.