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 exports
  • exports:readPoll export-job status and download completed exports
  • breakglass:readList break-glass grants
  • breakglass:revokeRevoke break-glass grants
  • rules:readList governance rules
  • agents:readList agents
  • budgets:readList agent budgets
  • channels:readList notification channels
  • permissions:readList the permission catalog
  • events:readList and count governance events
  • events:exportExport the governance-event record — sync download or async job (one egress grant)
  • rules:writeCreate, edit, delete, enforce/demote, install packs and backtest governance rules
  • budgets:writeCreate, edit and delete agent budgets
  • agents:writeRegister, edit, pause/resume and soft-delete individual agents
  • agents:killFlip the org-wide kill switch — pause-all and resume-all
  • channels:writeCreate, edit and delete notification channels
  • permissions: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 machine code where 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 the required_scope.
  • rate_limited429 with Retry-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 the feature, required_tier and current_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 receiptsveragent-oversight-receipt-v1, canonical algorithm receipt-v2.
  • Incident timelinesveragent-incident-timeline-v1, canonical algorithm timeline-v3.
  • Seal exportsveragent-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 authentication401 ip_not_allowed never 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 with truncated instead of pretending completeness.
  • The plan diff is the §7b shapeThe plan-before-apply endpoint returns PlanDiffResult exactly 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.