Management API — stability & versioning
What we promise about the API surface, in writing. Last updated: July 2026.
The Management API lives under /api/v1 and its contract is an OpenAPI document you can fetch without a key: /api/v1/openapi.yaml. That document is not generated marketing — it is the file our CI diffs against the implemented routes in both directions, including each endpoint's required scope and rate-limit bucket, so it cannot drift from what the server actually enforces.
Within v1, changes are additive-only: new endpoints, new response fields, new optional parameters. The error envelope, the authentication header, the scope names, and the truncated flag's meaning are stable. Anything breaking means a new /api/v2 namespace — v1 does not change under you.
Authentication & scopes
Every endpoint takes Authorization: Bearer vmk_…— a management key minted show-once in the dashboard by an administrator under a fresh two-factor challenge. Scopes are chosen at mint and are immutable for the key's lifetime; rotation issues a successor key with the same scopes and never extends the predecessor's life. Keys may carry an IP allowlist; an empty or absent allowlist means behavior identical to an unrestricted key.
These scope names are the contract. The list below renders from the same module the server validates against; renaming one is a breaking change with ceremony, not a refactor.
compliance:readFetch signed receipts, incident timelines and seal exportsexports:readPoll export-job status and download completed exportsbreakglass:readList break-glass grantsbreakglass:revokeRevoke break-glass grantsrules:readList governance rulesagents:readList agentsbudgets:readList agent budgetschannels:readList notification channelspermissions:readList the permission catalogevents:readList and count governance eventsevents:exportExport the governance-event record — sync download or async job (one egress grant)rules:writeCreate, edit, delete, enforce/demote, install packs and backtest governance rulesbudgets:writeCreate, edit and delete agent budgetsagents:writeRegister, edit, pause/resume and soft-delete individual agentsagents:killFlip the org-wide kill switch — pause-all and resume-allchannels:writeCreate, edit and delete notification channelspermissions:writeCreate, edit and delete catalog permissions
Rate limits
Limits are per key, per minute, in three buckets. An exhausted bucket answers 429 { "error", "code": "rate_limited" } with a Retry-After header in seconds. Limiting runs after authentication — an invalid key gets its 401, never a 429.
v1:read600 requests/min — list and read endpoints.v1:write120 requests/min — mutations and history-replaying analysis.v1:export10 requests/min — bulk egress (sync export, async-export create, download).
The error envelope
- Failures
{ "error": string }, with a machinecodewhere one exists. Validation failures on write endpoints are{ "errors": string[] }— every reason at once. insufficient_scope403 when the key lacks the endpoint's scope; the body names therequired_scope.rate_limited429 withRetry-After, as above.ip_not_allowed401 when a key's IP allowlist refuses the caller's network. This is an authentication failure: it is never a governance event and leaves no decision record.plan_required403 when a plan tier gates the operation; the body names thefeature,required_tierandcurrent_tier. Gates cover creating or widening configuration — existing configuration keeps evaluating on every tier.
Versioned surfaces
Three platform surfaces carry explicit version constants, pinned by tests in this repository; documents that embed them name their version so a reader always knows which grammar they hold.
- Rule grammarVersion 2 — the condition/effect language of governance rules.
- Approval configurationVersion 2 — quorums, restrictions, chains and autonomy bands on escalations.
- Row metadataVersion 1 — a rule row's enablement, priority, scope and canary fields.
The signed artifacts are versioned the same way, inside their own signed bytes:
- Oversight receipts
veragent-oversight-receipt-v1, canonical algorithmreceipt-v2. - Incident timelines
veragent-incident-timeline-v1, canonical algorithmtimeline-v3. - Seal exports
veragent-seal-export-v1— verifiable offline with our public auditor script and the keys at/.well-known/veragent-audit-signing-keys.
Frozen semantics
Shapes are not enough; these behaviors are part of the contract and are pinned by tests:
- IP refusals are authentication
401 ip_not_allowednever enters the governance-event record and never creates a decision row. - Empty allowlist = unrestrictedA key with no IP allowlist behaves byte-identically to one that never had the feature.
- Rotation never extends lifeA rotated key's predecessor expires at the earlier of its existing expiry and the overlap window — rotation can only shorten.
- Export jobs are complete-or-refusedStatus is exactly
queued / running / complete / refused / failed; a refused job carries its reason, and only a complete job downloads — there is no silently partial artifact. The sync export marks a capped walk withtruncatedinstead of pretending completeness. - The plan diff is the §7b shapeThe plan-before-apply endpoint returns
PlanDiffResultexactly as specified in the contract — either the full diff or the honest{ available: false, reason }, never a blocker.
Deliberately human-only
Some operations are absent from the API on purpose — they are features of the design, not gaps in it. Each stays in the dashboard, behind a human administrator:
- Resolving approvalsApproving, denying, delegating, or approving-for-hours is the product's human-judgment moment — a key that could resolve an escalation would remove the human the escalation exists to insert.
- API-key managementA key that could mint keys could widen its own reach — a looser IP allowlist, broader scopes — and defeat revocation; credentials are issued only by people.
- Issuing break-glass grantsIssuing mints new capability at runtime, and the dashboard ceremony for that is an administrator with a fresh two-factor challenge — no key ceremony substitutes for it. Listing and revoking grants are on the API, and revoking — the safety direction — is never gated.
Questions
Endpoint-by-endpoint detail lives in the browsable reference, which renders the contract itself — or read the raw document at /api/v1/openapi.yaml. For anything neither answers, email support@veragent.io.