Skip to content
v0.3.8GitHub

REST API

Source: src/content/docs/docs/reference/rest-api.md · verified against cerbix f5240f5Edit on GitHub ↗

The cerbix UI is built on the same REST API you can call from scripts and pipelines. This page covers the conventions every endpoint shares and maps the main resource groups. The OpenAPI file is the reference for individual routes, request bodies and responses.

The API is served by the api and all roles on the same origin as the UI, under /api/v1. Requests and responses are JSON, except the event stream and the status-page feeds.

The binary mounts several route trees side by side:

Prefix Authentication Purpose
/api/v1/ Session cookie or bearer credential The main API.
/api/v1/public/ None Status pages, subscriptions, push heartbeats, branding.
/api/v1/agent/ Agent token HTTP-pull agents.
/auth/ None Sign-in, callback, sign-out.
/healthz, /readyz, /metrics None Operational endpoints. See Metrics and alerts.

The main API accepts three kinds of credential, checked in this order:

Credential How it is sent Notes
Session cookie Cookie cerbix_session (configurable with session.cookie_name) Issued by POST /auth/local/login or by the OIDC flow GET /auth/login → GET /auth/callback. HttpOnly, SameSite=Lax; Secure when session.secure is set.
API token Authorization: Bearer cbx_… A service-account token issued per organization.
OIDC client-credentials JWT Authorization: Bearer <jwt> Accepted when OIDC is active. cerbix verifies issuer and signature; it does not check the audience. The token subject is provisioned as a user on first use and gets only the access its memberships grant.

A request without a valid credential gets 401 with {"error":"unauthorized"}. GET /auth/config reports which sign-in methods are enabled. See OIDC.

An org admin issues tokens with POST /api/v1/organizations/{orgID}/tokens. The body sets name, role, an optional project_id (omit it for an org-scoped token) and an optional actions allow-list. The secret appears once, in the token field of the 201 response.

The allow-list only narrows what the role grants. It cannot be changed after creation; issue a new token instead. A token for CI that asks the gate and records changes, and can do nothing else:

{
"name": "ci-checkout-api",
"role": "editor",
"project_id": "<project-id>",
"actions": ["gate:evaluate", "change:record"]
}

Roles are org_admin, project_admin, editor and viewer. Some routes need a global admin. A caller who is not a member of the organization or project gets 404, so existence is not revealed. A member with too low a role gets 403.

Every error body has one field:

{"error": "<message>"}

Many 400 responses carry a stable code in error, such as limit_invalid, cursor_invalid or range_required. Each route’s codes are listed in the OpenAPI file.

Ledger-style lists use keyset pagination:

Parameter Meaning
limit Page size, 1–200, default 50. Anything else is 400 limit_invalid.
cursor Opaque. Pass the next_cursor of the previous page.
next_cursor In the response; null on the last page.

This applies to GET /api/v1/projects/{projectID}/gate/decisions, GET /api/v1/projects/{projectID}/services/{serviceID}/changes (where limit counts change groups) and GET /api/v1/projects/{projectID}/monitors/{monitorID}/expected-runs. The traversal is live: rows committed during it may or may not appear. A few other lists accept limit only: heartbeats, the audit logs and the dead-letter outbox.

POST /api/v1/projects/{projectID}/services/{serviceID}/gate is bounded per process. Each api or all replica keeps its own counters, so the cluster allowance grows with the replica count.

Config key Default Refusal code
gate.evaluate_inflight_process 8 process_inflight
gate.evaluate_inflight_principal 2 principal_inflight
gate.evaluate_rate_principal_per_minute 10 principal_rate
gate.evaluate_rate_process_per_minute 60 process_rate

A refused request gets 429 with the code in error and a Retry-After header. Retry-After is 1 for an in-flight refusal and the whole seconds until the next token for a rate refusal. A refused request runs no evaluation and writes no ledger row. Do not retry into a 429. Gate ledger reads take the in-flight permits but no rate token.

POST /api/v1/projects/{projectID}/services/{serviceID}/changes has its own bounds: change.record_inflight_process (default 32), change.record_rate_principal_per_minute (default 30) and change.record_rate_process_per_minute (default 300). Change timeline, comparison and incident-change reads share change.read_inflight_process (default 64). Local sign-in and password-reset requests share a per-client-IP limit, local.login_rate_limit_per_minute (default 10 per minute).

GET /api/v1/events is a Server-Sent Events stream of monitor status changes, filtered to the projects the caller can see.

: connected
event: status
data: {"type":"status","monitor_id":"<id>","project_id":"<id>","status":"down","latency_ms":0,"ts":"<timestamp>"}
event: ping
data: {}

status is up, down or pending. A ping event arrives every 25 s so clients can detect a dead connection. The event bus is in-process: a stream carries the status changes ingested by the replica it is connected to.

These routes need no credential. Request bodies are capped at 64 KiB.

Route Purpose
GET /api/v1/public/status-pages/{slug} Render a status page. Unlisted pages need ?token=; internal pages return 404.
GET /api/v1/public/status-pages/{slug}/feed Incident feed: RSS by default, ?format=atom or ?format=json.
POST /api/v1/public/status-pages/{slug}/subscribers Subscribe to updates.
POST /api/v1/public/subscriptions/{token}/confirm Confirm a subscription.
DELETE /api/v1/public/subscriptions/{token} Unsubscribe.
POST /api/v1/public/push/{token} Push heartbeat for a push monitor; ?status=down reports a failure.
GET /api/v1/public/branding Instance branding for the sign-in page.

See Status pages.

HTTP-pull agents (cerbix serve --role agent) use /api/v1/agent/* to claim jobs, report results and heartbeat. These routes are mounted only when pull.token, pull.agents or pull.regions is configured, and are not part of the OpenAPI file.

An agent authenticates with Authorization: Bearer <token> and names its region with ?region=. Three token sources are accepted: the catch-all pull.token, a per-region pull.agents[].token, and database-managed tokens issued by a global admin through /api/v1/agent-tokens. A wrong token gets 401. See Geo probers.

Representative routes. All paths start with /api/v1.

Group Representative routes
Identity GET /me, GET /version, POST /me/password, POST /me/totp/enroll
Organizations and members GET /organizations, GET /organizations/{orgID}/projects, GET /organizations/{orgID}/members, GET /organizations/{orgID}/audit
Projects GET /projects/{projectID}, GET /regions
Monitors GET /projects/{projectID}/monitors, POST /projects/{projectID}/monitors/test, PATCH /monitors/{monitorID}, GET /monitors/{monitorID}/heartbeats
Services and reliability GET /projects/{projectID}/services, PUT …/services/{serviceID}/declaration, GET …/services/{serviceID}/reliability, GET …/services/{serviceID}/reliability/series
SLA and availability GET /projects/{projectID}/sla, PUT /projects/{projectID}/sla-target, GET /monitors/{monitorID}/availability
Release gate POST …/services/{serviceID}/gate, PUT …/services/{serviceID}/gate/policy, POST …/services/{serviceID}/gate/override, GET /projects/{projectID}/gate/decisions
Changes POST …/services/{serviceID}/changes, GET …/services/{serviceID}/changes/compare, GET /projects/{projectID}/incidents/{incidentID}/changes
Incidents GET /projects/{projectID}/incidents, POST /incidents/{incidentID}/updates, PUT /incidents/{incidentID}/postmortem, POST /projects/{projectID}/alerts/alertmanager
Maintenance GET /projects/{projectID}/maintenance, POST /projects/{projectID}/maintenance/preview
On-call GET /projects/{projectID}/escalation-policies, GET /projects/{projectID}/oncall-schedules, GET /oncall-schedules/{scheduleID}/current
Notifications GET /projects/{projectID}/notification-channels, GET /organizations/{orgID}/webhooks, POST /monitors/{monitorID}/notifications
Status pages GET /organizations/{orgID}/status-pages, GET /status-pages/{pageID}/render, POST /status-pages/{pageID}/components
Secrets GET /projects/{projectID}/secrets, POST /projects/{projectID}/secrets
Tokens GET /organizations/{orgID}/tokens, DELETE /tokens/{tokenID}, GET /agent-tokens
Search and events GET /search, GET /events
Instance settings GET /settings/oidc, PUT /settings/branding, GET /settings/auth-policy, PUT /settings/monitor-defaults
Administration GET /admin/users, GET /admin/audit, GET /admin/file-providers, GET /admin/outbox/dead

… stands for /projects/{projectID}. Related pages: Services, Release gate, Change intelligence, Incidents, On-call.