Gateway HTTP API · v1.7.0

API Reference

Every endpoint the gateway exposes. Rendered at build time from api/openapi.yaml in the open-source repo. Download the spec to generate clients in any language.

Overview

Two surfaces, one binary:

- **Runtime path** (`/v1/mcp`, `/v1/tool-call`) — called by agent
runtimes on every tool invocation. Traverses the four-check
pipeline (capability, intent, policy, budget) and either
forwards to the upstream tool server or returns a typed
JSON-RPC error.
- **Admin path** (`/v1/admin/*`) — called by operators and the
console. Mint capability tokens, manage policies, query and
verify the audit chain, review approvals, switch tenants,
inspect SIEM integrations.

Authentication uses bearer tokens for both surfaces. Stable
across the v1 series; breaking changes ship as `/v2`.

Authentication

- **Runtime** endpoints accept a **capability token** signed by the gateway's master key. Issued by `POST /v1/admin/mint`. - **Admin** endpoints (`/v1/admin/*`) accept either the **superadmin token** (`INTENTGATE_ADMIN_TOKEN`) or a **per-tenant admin token** (`INTENTGATE_TENANT_ADMIN_TOKENS`). Tokens are compared in constant time.

Servers

  • https://gateway.example.com — Customer deployment (substitute your own host)
  • http://localhost:8080 — Local dev (default Docker / docker-compose)

Runtime

Agent-facing tool-call endpoints. Traverses the four-check pipeline.

POST /v1/mcp

Model Context Protocol passthrough

Accepts MCP messages over JSON-RPC 2.0 — `initialize`,
`tools/list`, `ping`, and tool invocations. Tool invocations
traverse the full four-check pipeline; the others are
forwarded to the upstream tool server with light validation.

Recommended endpoint for any agent that already speaks MCP.
Request body
{
  "jsonrpc": "2.0",
  "id": "string",
  "method": "tools/call",
  "params": {}
}
Responses
200
Allowed call forwarded; response from upstream tool server.
{
  "jsonrpc": "2.0",
  "id": "string",
  "result": null,
  "error": {
    "code": -32010,
    "message": "string",
    "data": {}
  }
}
POST /v1/tool-call

Direct JSON-RPC tool invocation

For agents that don't speak MCP. Same authorization pipeline
as `/v1/mcp`; the wire shape is plain JSON-RPC 2.0.
Request body
{
  "jsonrpc": "2.0",
  "id": "string",
  "method": "tools/call",
  "params": {}
}
Responses
200
Allowed call forwarded; upstream response.
{
  "jsonrpc": "2.0",
  "id": "string",
  "result": null,
  "error": {
    "code": -32010,
    "message": "string",
    "data": {}
  }
}

Capabilities

Mint, revoke, and inspect capability tokens.

POST /v1/admin/mint

Issue a fresh capability token

Requires `INTENTGATE_MASTER_KEY` to be set. `subject` is the
only required field. Optional `tools` restricts to a
whitelist, `max_calls` encodes a budget caveat, `step_up`
stamps a fresh-factor timestamp Rego reads via
`input.capability.step_up_at`.
Request body
{
  "subject": "agent-finance-bot-7",
  "issuer": "intentgate",
  "tenant": "acme-corp",
  "ttl_seconds": 3600,
  "tools": [
    "read_invoice",
    "list_vendors"
  ],
  "max_calls": 100,
  "step_up": false,
  "with_memory_signing_key": false
}
Responses
200
Minted token.
{
  "token": "string",
  "jti": "01HXYZ...",
  "expires_at": "2026-06-14T13:42:00Z"
}
400
Validation error.
{
  "error": "string"
}
401
Missing or invalid token.
{
  "error": "string"
}
503
A dependency (policy store, master key) is not configured.
{
  "error": "string"
}
POST /v1/admin/revoke

Revoke a capability token by JTI

Subsequent runtime calls presenting that JTI fail the
capability check with `-32010`. Per-tenant admins can only
revoke tokens issued under their tenant.
Request body
{
  "jti": "01HXYZ...",
  "reason": "rotation"
}
Responses
204
Revoked.
400
Validation error.
{
  "error": "string"
}
401
Missing or invalid token.
{
  "error": "string"
}
GET /v1/admin/revocations

List revoked JTIs

Parameters
NameInTypeRequiredDescription
tenant query string no Superadmin-only — scope the operation to a tenant. Per-tenant admin tokens force scope and ignore this.
limit query integer no Maximum items to return (1-1000).
cursor query string no Opaque cursor returned in the prior response's `next_cursor`.
Responses
200
Revocations.
{
  "items": [
    {
      "jti": "string",
      "tenant": "string",
      "revoked_at": "2026-06-14T13:42:00Z",
      "reason": "string"
    }
  ],
  "next_cursor": "string"
}
401
Missing or invalid token.
{
  "error": "string"
}

Policies

Two-stage lifecycle — drafts, active, dry-run, rollback.

GET /v1/admin/policies/drafts

List draft policies

Parameters
NameInTypeRequiredDescription
tenant query string no Superadmin-only — scope the operation to a tenant. Per-tenant admin tokens force scope and ignore this.
Responses
200
Drafts.
[
  {
    "id": "string",
    "name": "string",
    "description": "string",
    "tenant": "string",
    "created_by": "string",
    "created_at": "2026-06-14T13:42:00Z",
    "rego_sha256": "string"
  }
]
401
Missing or invalid token.
{
  "error": "string"
}
POST /v1/admin/policies/drafts

Create a draft

Rego is compiled at save time. Bad Rego returns 400 with OPA's parser error verbatim.
Request body
{
  "name": "baseline-2026-06",
  "description": "Add value-threshold rule for transfer_funds",
  "rego_source": "package intentgate.policy\n...",
  "tenant": "acme-corp",
  "created_by": "joe@acme-corp.example"
}
Responses
201
Created.
{
  "id": "string",
  "name": "string",
  "description": "string",
  "tenant": "string",
  "created_by": "string",
  "created_at": "2026-06-14T13:42:00Z",
  "rego_sha256": "string",
  "rego_source": "string"
}
400
Validation error.
{
  "error": "string"
}
401
Missing or invalid token.
{
  "error": "string"
}
GET /v1/admin/policies/drafts/{id}

Fetch a draft (including Rego source)

Responses
200
Draft.
{
  "id": "string",
  "name": "string",
  "description": "string",
  "tenant": "string",
  "created_by": "string",
  "created_at": "2026-06-14T13:42:00Z",
  "rego_sha256": "string",
  "rego_source": "string"
}
401
Missing or invalid token.
{
  "error": "string"
}
404
Resource not found (or cross-tenant — gateway returns 404 to avoid leaking existence).
{
  "error": "string"
}
PUT /v1/admin/policies/drafts/{id}

Update a draft

Request body
{
  "name": "string",
  "description": "string",
  "rego_source": "string"
}
Responses
200
Updated.
{
  "id": "string",
  "name": "string",
  "description": "string",
  "tenant": "string",
  "created_by": "string",
  "created_at": "2026-06-14T13:42:00Z",
  "rego_sha256": "string",
  "rego_source": "string"
}
400
Validation error.
{
  "error": "string"
}
401
Missing or invalid token.
{
  "error": "string"
}
404
Resource not found (or cross-tenant — gateway returns 404 to avoid leaking existence).
{
  "error": "string"
}
DELETE /v1/admin/policies/drafts/{id}

Delete a draft

Responses
204
Deleted.
401
Missing or invalid token.
{
  "error": "string"
}
404
Resource not found (or cross-tenant — gateway returns 404 to avoid leaking existence).
{
  "error": "string"
}
GET /v1/admin/policies/active

Read the active-policy pointer

Parameters
NameInTypeRequiredDescription
tenant query string no Superadmin-only — scope the operation to a tenant. Per-tenant admin tokens force scope and ignore this.
Responses
200
Active policy metadata.
{
  "draft_id": "string",
  "name": "string",
  "promoted_by": "string",
  "promoted_at": "2026-06-14T13:42:00Z",
  "rego_sha256": "string",
  "tenant": "string"
}
401
Missing or invalid token.
{
  "error": "string"
}
POST /v1/admin/policies/active

Promote a draft to active

Recompiles, swaps the per-tenant active engine, writes the
pointer, fans the change out to every replica via Postgres
`LISTEN`/`NOTIFY`. Compile errors return 400 and leave the
prior policy running.
Request body
{
  "draft_id": "01HXYZ...",
  "tenant": "string",
  "promoted_by": "joe@acme-corp.example"
}
Responses
200
Promoted.
{
  "draft_id": "string",
  "name": "string",
  "promoted_by": "string",
  "promoted_at": "2026-06-14T13:42:00Z",
  "rego_sha256": "string",
  "tenant": "string"
}
400
Validation error.
{
  "error": "string"
}
401
Missing or invalid token.
{
  "error": "string"
}
404
Resource not found (or cross-tenant — gateway returns 404 to avoid leaking existence).
{
  "error": "string"
}
DELETE /v1/admin/policies/active

Clear the active pointer

The tenant reverts to fail-closed until a new active is promoted.
Parameters
NameInTypeRequiredDescription
tenant query string no Superadmin-only — scope the operation to a tenant. Per-tenant admin tokens force scope and ignore this.
Responses
204
Cleared.
401
Missing or invalid token.
{
  "error": "string"
}
POST /v1/admin/policies/rollback

Roll back to the previous active policy

Parameters
NameInTypeRequiredDescription
tenant query string no Superadmin-only — scope the operation to a tenant. Per-tenant admin tokens force scope and ignore this.
Responses
200
Rolled back.
{
  "draft_id": "string",
  "name": "string",
  "promoted_by": "string",
  "promoted_at": "2026-06-14T13:42:00Z",
  "rego_sha256": "string",
  "tenant": "string"
}
401
Missing or invalid token.
{
  "error": "string"
}
POST /v1/admin/policies/dry-run

Evaluate a candidate Rego against synthetic or historical input

Either `input` or `sample` is required. Does not change the active pointer.
Request body
{
  "rego_source": "string",
  "tenant": "string",
  "input": {},
  "sample": "string"
}
Responses
200
Decisions.
{
  "decisions": [
    {
      "input": {},
      "candidate_decision": "allow",
      "actual_decision": "allow",
      "rule": "string"
    }
  ]
}
400
Validation error.
{
  "error": "string"
}
401
Missing or invalid token.
{
  "error": "string"
}

Audit

Tamper-evident audit chain — query, verify, export.

GET /v1/admin/audit

Query the per-tenant audit chain

Parameters
NameInTypeRequiredDescription
tenant query string no Superadmin-only — scope the operation to a tenant. Per-tenant admin tokens force scope and ignore this.
since query string no
until query string no
decision query string no
tool query string no
subject query string no
limit query integer no Maximum items to return (1-1000).
cursor query string no Opaque cursor returned in the prior response's `next_cursor`.
Responses
200
Audit events.
{
  "items": [
    {
      "ts": "2026-06-14T13:42:00Z",
      "event": "intentgate.tool_call",
      "schema_version": "v4",
      "decision": "allow",
      "check": "",
      "reason": "string",
      "tenant": "string",
      "agent_id": "string",
      "session_id": "string",
      "tool": "string",
      "arg_keys": [
        "string"
      ],
      "arg_values": {},
      "capability_token_id": "string",
      "root_capability_token_id": "string",
      "caveat_count": 0,
      "pending_id": "string",
      "decided_by": "string",
      "intent_summary": "string",
      "latency_ms": 0,
      "remote_ip": "string",
      "upstream_status": 0,
      "requires_step_up": false,
      "elevation_id": "string"
    }
  ],
  "next_cursor": "string"
}
401
Missing or invalid token.
{
  "error": "string"
}
GET /v1/admin/audit/verify

Verify the tamper-evident chain

Walks every event for the tenant and reports whether each
hash link reconciles. The daily compliance attestation for
BIO, ISO 27001, and EU AI Act auditors. Read replica safe.
Parameters
NameInTypeRequiredDescription
tenant query string no Superadmin-only — scope the operation to a tenant. Per-tenant admin tokens force scope and ignore this.
Responses
200
Verification result.
{
  "tenant": "string",
  "verified": false,
  "events_checked": 184523,
  "chain_head_id": "string",
  "chain_head_at": "2026-06-14T13:42:00Z",
  "duration_ms": 412,
  "first_broken_event_id": "string"
}
401
Missing or invalid token.
{
  "error": "string"
}
GET /v1/admin/audit/export

Stream audit events for offline review

Parameters
NameInTypeRequiredDescription
format query string yes
tenant query string no Superadmin-only — scope the operation to a tenant. Per-tenant admin tokens force scope and ignore this.
since query string no
until query string no
Responses
200
Stream.
"string"
401
Missing or invalid token.
{
  "error": "string"
}

Approvals

Human-review queue for policy-escalated calls.

GET /v1/admin/approvals

List pending approvals

Parameters
NameInTypeRequiredDescription
tenant query string no Superadmin-only — scope the operation to a tenant. Per-tenant admin tokens force scope and ignore this.
limit query integer no Maximum items to return (1-1000).
cursor query string no Opaque cursor returned in the prior response's `next_cursor`.
Responses
200
Pending approvals.
{
  "items": [
    {
      "id": "string",
      "tenant": "string",
      "agent_id": "string",
      "capability_token_id": "string",
      "tool": "string",
      "arguments": {},
      "escalating_rule": "string",
      "created_at": "2026-06-14T13:42:00Z"
    }
  ],
  "next_cursor": "string"
}
401
Missing or invalid token.
{
  "error": "string"
}
POST /v1/admin/approvals/{id}/decide

Approve or reject a parked call

On `approve`, the gateway re-evaluates the call (modulo the
escalate rule) and forwards if it passes. On `reject`, the
call is denied. Cross-tenant IDs return 404.
Parameters
NameInTypeRequiredDescription
id path string yes
Request body
{
  "decision": "approve",
  "reason": "string",
  "decided_by": "joe@acme-corp.example"
}
Responses
204
Decided.
400
Validation error.
{
  "error": "string"
}
401
Missing or invalid token.
{
  "error": "string"
}
404
Resource not found (or cross-tenant — gateway returns 404 to avoid leaking existence).
{
  "error": "string"
}

Tenants

Tenant inventory for the console switcher.

GET /v1/admin/tenants

List configured tenants

Responses
200
Tenants.
[
  {
    "name": "acme-corp",
    "active_policy_sha": "string",
    "pending_approvals": 0,
    "recent_event_count": 0
  }
]
401
Missing or invalid token.
{
  "error": "string"
}

Integrations

SIEM and webhook destination health.

GET /v1/admin/integrations

Status of every configured SIEM and webhook destination

Sensitive fields (HEC tokens, API keys, shared keys) are
never returned — only labels and counters.
Responses
200
Integration statuses.
[
  {
    "name": "splunk",
    "configured": false,
    "endpoint": "string",
    "last_flush_ts": "2026-06-14T13:42:00Z",
    "events_flushed": 0,
    "events_dropped": 0,
    "last_error": "string"
  }
]
401
Missing or invalid token.
{
  "error": "string"
}

Discovery & inventory Pro · console

Console endpoints that feed the agent inventory. Bearer-token authenticated, server-to-server — not part of the open-core gateway spec above.

POST /api/discovery/ingest

Push discovered agents from a source.

A source (CASB, proxy, DNS, SIEM, or script) forwards its native log / export rows here. Authenticate with the per-source bearer token minted when the source was created; the source's vendor type selects the parser (Zscaler, Netskope, Microsoft Defender for Cloud Apps, Infoblox, or generic). Body is { "records": [ … ] } or a bare array. Returns { ok, discovered, imported, source }.
POST /api/discovery/sync

Run the automatic-pull scheduler.

Polls every enabled pull source whose interval has elapsed, fetches its endpoint, normalises, and imports. Authenticate with INTENTGATE_DISCOVERY_SYNC_TOKEN and call from a cron / CronJob every few minutes — it only touches sources actually due. Returns { ok, polled, imported, results }.

Governance reports Pro · console

Read-only reporting over the agent inventory, ownership, attestation, and the gateway audit log.

GET /api/reports/{type}

Fetch a governance report as JSON or CSV.

type is one of posture, access, attestation, or activity. Authenticate with INTENTGATE_REPORTS_API_TOKEN. Add ?format=csv for a flat-file download (default JSON) and ?tenant= to scope. Posture is coverage roll-ups; access is the agent register (agent → touches → policy → owner); attestation is campaign completion + evidence; activity aggregates the gateway audit log — allow / deny counts and top-blocked agents and tools.