Skip to content
Browse documentation

REST API

The control-plane API: 110 routes for policy, decisions, runs, approvals, secrets, audit, SSO, and provisioning.

The SDKs cover the tool-executor boundary from inside your process. The REST API is for everything else — CI checks, internal tooling, and anything that needs to reach the control plane without running an agent.

Note
There is no hosted API. Every deployment is your own — the base URL below is whatever you deployed at. See Self-hosted / VPC.

Base URL and authentication

TerminalShell
$ export CIRVIX_API=https://cirvix.internal.example.com $ curl -s $CIRVIX_API/health{"status":"ok","version":"0.3.0","uptime":12.4} $ curl -s $CIRVIX_API/v1/agents \    -H "authorization: Bearer cvx_..."
CredentialPrefixLifetimeUsed by
API keycvx_Until revokedThe endpoint daemon, CI, the SDKs
Session access tokenJWT15 minutesThe console
Refresh tokencvr_30 days, rotatingThe console
SCIM tokenscim_Until revokedYour identity provider

A SCIM token can only reach /scim/v2/*, and a console credential can only reach /v1/*. That separation is structural, not a check that could be forgotten: a SCIM principal carries no role, so the permission test could never be satisfied by one.

Two invariants

  • orgId is never read from a body, query, or path. It comes only from the authenticated principal, so a client cannot address another tenant's data even by guessing ids — the parameter that would allow it does not exist in the routing layer.
  • Every route declares the permission it needs, or null for an explicitly public one. The router throws at startup otherwise, so an endpoint cannot be added unauthenticated by omission.

Selected endpoints

MethodPathPermission
GET/healthpublic
GET/metricspublic, or CIRVIX_METRICS_TOKEN
POST/v1/leadspublic
GET/v1/leadsCIRVIX_LEAD_TOKEN
POST/v1/auth/loginpublic
GET/v1/policypolicy:read
POST/v1/policypolicy:write
POST/v1/policy/validatepolicy:read
POST/v1/policy/simulatepolicy:read
GET/v1/decisions/:decisionIddecision:read
POST/v1/runs/:runId/replaypolicy:read
GET/v1/approvalsdecision:read
POST/v1/approvals/:approvalId/decideapproval:decide
POST/v1/secrets/handlessecret:use
GET/v1/audit/verifyaudit:read
GET/v1/compliance/reportaudit:read
GET/v1/exportaudit:read
GET/v1/streamdecision:read

Publishing a rule set

TerminalShell
$ curl -X POST $CIRVIX_API/v1/policy \    -H "authorization: Bearer cvx_..." \    -H "content-type: application/json" \    -d @cirvix.policy.json

Rules are structurally validated before anything is written — publishing a malformed set fans it out to the entire fleet. POST /v1/policy/validate returns every problem at once rather than throwing on the first, because an operator fixing one error per round trip is an operator who gives up.

Fetching a decision

TerminalShell
$ curl -s $CIRVIX_API/v1/decisions/dec_01JQ8F2K7M \    -H "authorization: Bearer cvx_..."
ResponseJSON
{  "id": "dec_01JQ8F2K7M",  "runId": "run_01JQ8F2K7M",  "agent": "pr-triage",  "action": "fs.read",  "resource": "/repo/.env.production",  "verdict": "deny",  "rule": "deny-dotenv-read",  "reason": "Reading .env files is denied outside an approved secrets flow.",  "ts": "2026-08-06T09:14:02.418Z"}

Rate limits

BucketDefaultKeyed by
General600/min (CIRVIX_RATE_LIMIT)API key id or session id
Login, SSO, invitations10/minIP
SCIM600/minSCIM token id

A sliding window, not a fixed one — a fixed window lets a caller spend the full budget at the end of one window and again at the start of the next. A refused request still counts against the budget, so a hot retry loop does not recover. /v1/stream is exempt.

Edit this page on GitHub
Was this page helpful?