API Reference
Everything is HTTPS + JSON under /api/v1. The full machine-readable contract lives in our OpenAPI 3.1 spec.
Download the OpenAPI 3.1 spec → Import it into Postman, Insomnia, or your codegen.
Authentication
Send your gateway API key as a bearer token. Keys are created in the dashboard or via POST /api/v1/keys, shown once, stored hashed, and revocable. Every request is scoped to the key's tenant. There is no way to read another tenant's data with a valid key.
header
Authorization: Bearer apk_...Endpoints
| Endpoint | Purpose |
|---|---|
POST /api/v1/actions/preflight | The core decision: should this action proceed? |
POST /api/v1/actions/execute | Preflight + forward to the upstream with the bound credential injected. |
POST /api/v1/passports/issue · verify · revoke | Manage Action Passports. GET /api/v1/passports/jwks serves public keys. |
GET /api/v1/approvals · POST /api/v1/approvals/:id/decide | List the queue; apply approve/deny/modify/escalate (FSM-gated, RBAC). |
GET/POST/PUT/DELETE /api/v1/policies · POST /api/v1/policies/replay | Policy CRUD, validated, versioned, hashed. Replay tests a draft policy against historical decisions before you ship it. |
POST /api/v1/tools/ingest · /api/v1/tools/diff | Register tool manifests; classify drift between versions. |
GET /api/v1/evidence/events · verify · export · stats · stream | Read the ledger, verify the hash chain, export signed bundles; stats aggregates decisions server-side (by day, agent, or tool) and stream tails the ledger live over SSE with cursor/Last-Event-ID resume. GET /api/v1/evidence/jwks serves this team's verification keys (tenant-scoped, active + retired). |
POST/GET /api/v1/credentials | Vault credentials (AES-256-GCM). Secrets are write-only. |
POST/GET/DELETE /api/v1/keys · POST /api/v1/keys/signing/rotate | API-key lifecycle. Keys are returned once, stored hashed. signing/rotate rotates this team's report/evidence signing key; the retired key stays in the JWKS so old signatures keep verifying. |
GET /api/v1/compliance · /api/v1/integrations/siem | Live control evaluation; SIEM-formatted event streams. |
GET /api/v1/integrations/servicenow/status · /api/v1/integrations/slack/status · /api/v1/integrations/teams/status · /api/v1/integrations/compliance-export/status | Self-serve integration bridge health (ServiceNow, Slack, Teams, Vanta/Drata compliance export): typed pass/fail checklist with per-check remediation steps. |
POST /api/v1/agents/register · issue-passport · validate · renew · refresh-passport | Agent lifecycle: register an AI agent (its declared capabilities cap all future passports), then issue, validate, and renew passports for it. |
POST /api/v1/actions/decision | Alias for /api/v1/actions/preflight: same deterministic engine, same request and response shape. Use whichever verb fits your SDK flow. |
POST /api/v1/certified | Free manifest scan → signed certification badge. A critical finding (or score below the bronze threshold) returns 400 and no badge is minted. |
POST /api/v1/install/initiate · /api/v1/install/poll | Device-code onboarding (RFC 8628) for CLIs, SDKs, and MCP servers: declare identity + tools, send the human to consent, poll for the key. |
POST /api/v1/simulate | Dry-run one or a batch of actions against your policies in monitor mode: decision, matched rules, and rule trace, with nothing executed, blocked, or persisted. |
GET /api/v1/audit · GET /api/v1/audit/export | SOC2-grade audit trail: every allow/deny with its matched reason and per-chain integrity; export as signed JSON, CSV, or Markdown for board/auditor review. |
GET/POST /api/v1/policies/lint | Surface rule conflicts (contradictions & shadowed rules) across your policy set: GET lints stored policies, POST lints a candidate set before you publish. |
POST /api/v1/policies/backtest | Apply a candidate policy against historical decisions and report what would have changed. No live environment is touched. |
POST /api/v1/policies/:id/versions | Version-bump an immutable published (or archived) policy: clones it into a new draft with the version incremented — the paved path past policy.lifecycle_invalid. |
POST /api/v1/observations/ingest · mine | Observation pipeline: batch-ingest privacy-reduced observed events (raw args are digested server-side and dropped), then run deterministic mining sweeps to surface recurring workflow patterns. |
GET /api/v1/observations/candidates · POST /api/v1/observations/candidates/:id/promote · dismiss | Review mined workflow candidates; promote one to a DRAFT-only governable policy (never auto-published) or dismiss it — each decision sealed onto the evidence chain. |
POST /api/v1/integrations/github/import | Import a repo, infer its agent tool surface, auto-generate the required MCP policies (monitor mode), and return a push-back plan. |
POST /api/v1/agents/service-accounts | Mint a service-account identity for an agent, distinct from any human account, for non-interactive enforcement. |
GET /api/v1/integrations/servicenow/update-set | Download the checksummed ServiceNow bridge Update Set package for import into your instance. |
POST /api/v1/policies/install-pack | Install a curated starter policy pack (idempotent, opt-in): day-one secret-blocking and prod-deploy-approval rules without hand-authoring. |
GET/POST /api/v1/runtime/kill-switches · DELETE /api/v1/runtime/kill-switches/:id | Runtime control plane: list and arm kill switches that force a stricter mode (or block a tool) at enforcement time; delete to disarm. |
GET/POST /api/v1/integrations/sinks · PATCH/DELETE /api/v1/integrations/sinks/:id · POST /api/v1/integrations/sinks/drain | Manage SIEM forwarding sinks (Splunk HEC / Datadog / webhook / CEF); drain flushes queued evidence to every active sink. |
GET /api/v1/integrations/deliveries · POST /api/v1/integrations/deliveries/drain | Outbound notification queue: inspect pending / delivered / dead-lettered rows; drain retries due deliveries with backoff (cron-callable) and can replay a dead-lettered row. |
The preflight request
POST /api/v1/actions/preflight
{
"tool": "stripe.refund.create", // required - namespaced tool id
"resource": "stripe:charge:ch_123", // what it acts on
"args": { "amount": 4900, "currency": "usd" },
"agent_id": "support_agent", // required
"user_id": "user_456", // the delegating human
"goal": "resolve_refund_request",
"mode": "enforce", // monitor | warn | enforce | strict
"passport": "eyJhbGciOiJFZERTQSJ9...", // optional JWS
"idempotency_key": "req_8841" // safe retries
}response - 200
{
"decision": "require_approval",
"reason_code": "refund.medium_needs_approval",
"risk_tier": "high",
"approval_request_id": "apr_312",
"tool_manifest_hash": "sha256:9f2c...",
"policy_hash": "sha256:77ab...",
"evidence_event_id": "ev_5520",
"explain": {
"summary": "Policy refund_policy v3: require_approval.",
"matched_rules": ["medium_refund_needs_human"],
"next_steps": ["A reviewer must decide approval apr_312."]
}
}Note:Preflight never executes anything. Denies in
enforce/strict return HTTP 403 for hard security failures (replay, revocation, tenant mismatch) and 200 with decision: denyfor policy outcomes, so your client can distinguish "attack" from "not allowed".Reason codes
Every decision carries a stable, typed reason_code. The families:
| Family | Examples |
|---|---|
passport.* | missing, expired, revoked, replay_detected, tool_not_allowed, audience_mismatch |
tool.* | manifest_changed, reapproval_required, read_to_write_conversion, oauth_scope_broadened |
args.* | schema_invalid, amount_exceeds_limit, resource_out_of_scope, external_recipient |
approval.* | pending, denied, expired, invalid (forged hash), satisfied (verified approval) |
policy.* / domain packs | update_required; refund.small_in_scope, refund.out_of_policy, … |
Errors & rate limits
error shape
{ "decision": "deny", "reason_code": "args.schema_invalid", "error": "tool is required" }| Status | Meaning |
|---|---|
| 400 | Invalid request body (e.g. reason_code args.schema_invalid when tool is missing) |
| 401 | Missing/invalid API key, or a passport that fails verification |
| 402 | Plan gate: the feature needs a higher tier (body includes feature and min_tier) |
| 403 | Authenticated but forbidden: RBAC, tenant scope, or a hard security deny |
| 409 | Approval state transition not allowed by the FSM |
| 429 | Per-tenant request budget exceeded (reason_code rate_limited; retry-after header set) |
Use idempotency_key on preflight/execute: retrying the same key with the same payload is safe and returns the original decision instead of burning a passport use.