API reference
Base URL: https://api.inpolicy.ai/api/v1/agent
Authentication: Authorization: Bearer inp_live_… on every request.
Rate limit: 120 req/min per key by default; configurable per key.
All Agent Governance endpoints are mounted under /api/v1/agent. The tenant is resolved from the API key. You never pass a tenant id in a request body.
Errors
Section titled “Errors”| Status | Meaning |
|---|---|
400 | Bad request (validation error). Response body has details. |
401 | Missing / invalid / revoked API key. |
403 | Key lacks required scope OR feature gate disabled on the key. |
404 | Resource not found (e.g. unknown sessionId on GET /conversation). |
429 | Rate limit exceeded. Retry after window_seconds. |
5xx | Upstream error. Retryable with exponential backoff. |
POST /api/v1/agent/governance/conversation/turn
Section titled “POST /api/v1/agent/governance/conversation/turn”The primary surface. Record one turn in a conversation and get the updated policy state.
Request
{ "sessionId": "sess_abc", "turn": { "role": "user", "content": "I'm 16 — can I buy this?" }, "recentContext": ["prior turn content"], "priorHistory": null, "endUserContext": { "attributes": { "customer_tier": "basic", "region": "EU" } }, "policyAreaIds": ["data-handling"], "tokenBudget": 600, "idempotencyKey": "turn-7a9c-...", "checkOutput": false, "ttlSeconds": null}| Field | Required | Description |
|---|---|---|
sessionId | ✅ | Stable caller-chosen conversation id. |
turn.role | ✅ | user | assistant | tool. system is rejected. |
turn.content | ✅ | The turn’s text content. |
recentContext | — | Last 2–3 prior turns for disambiguation. Not stored. |
priorHistory | — | Bootstrap history; only used on the first call per session. |
endUserContext.attributes | — | Opaque attributes for policy matching. Not stored. |
policyAreaIds | — | Scope retrieval to specific policy areas. |
tokenBudget | — | Approx tokens for injectionBlock. Default 600. Range [50, 4000]. |
idempotencyKey | — | Replays within 5 min return the cached response. |
checkOutput | — | Only valid when turn.role === "assistant". Requires post_inference_checking: "allowed" on the key. |
ttlSeconds | — | Override conversation TTL. Range [300, 604800]. |
Response (200)
{ "sessionId": "sess_abc", "turnIndex": 3, "diff": { "newlyApplicable": [ /* ApplicablePolicy[] */ ], "newlyReleased": [], "stillActive": [ /* ApplicablePolicy[] */ ], "bindingEvents": [ { "turnIndex": 3, "policyId": "pol_123", "event": "binding_started", "ts": "2026-04-24T12:00:00Z" } ] }, "activePolicies": [ /* ApplicablePolicy[] */ ], "injectionBlock": "## Applicable Company Policies\n- [Policy 4.2]...", "tokenEstimate": 184, "postInferenceCheck": null, "traceId": null}ApplicablePolicy:
{ "id": "pol_123", "title": "No customer PII in external AI tools", "summary": "Mask customer emails, names, account IDs...", "severity": 4, "enforcement": "fix" | "warning" | "audit", "citationRef": "Policy 4.2", "tags": ["pii"]}Latency: p50 ~100 ms, p95 ~500 ms regardless of input size (pre-inference is bounded by top-K retrieval, not prompt length). See Latency expectations.
GET /api/v1/agent/governance/conversation/:sessionId
Section titled “GET /api/v1/agent/governance/conversation/:sessionId”Read-only snapshot of conversation state. No mutation, no TTL reset.
Response (200)
{ "sessionId": "sess_abc", "turnCount": 7, "activePolicies": [ /* ApplicablePolicy[] */ ], "injectionBlock": "...", "bindingLog": [ /* BindingEvent[] */ ], "updatedAt": "2026-04-24T12:00:00Z"}Returns 404 if the session has been evicted (past TTL) or never existed.
DELETE /api/v1/agent/governance/conversation/:sessionId
Section titled “DELETE /api/v1/agent/governance/conversation/:sessionId”End a conversation and purge its Redis state. Idempotent. Returns 204.
POST /api/v1/agent/governance/check-tool-call
Section titled “POST /api/v1/agent/governance/check-tool-call”Gate a proposed agent tool call against the session’s active policies. Requires tool_call_governance: "allowed" on the API key; returns 403 otherwise.
Request
{ "sessionId": "sess_abc", "toolName": "send_email", "arguments": { "to": "competitor@acme.com", "subject": "Q3 roadmap" }, "intent": "proposed"}Response (200)
{ "allow": false, "riskScore": 0.91, "violations": [ { "policyId": "pol_conf_01", "matchedText": "competitor@acme.com", "explanation": "Recipient domain matches listed competitor.", "severity": 4, "confidence": 0.95, "enforcementType": "fix" } ], "suggestedArguments": null, "traceId": null}allow: false happens when at least one violation has enforcementType: "fix" AND confidence ≥ 0.7. Any other violation (warning, audit, or low-confidence) returns allow: true with the violations surfaced for audit.
POST /api/v1/agent/governance/pre-inference
Section titled “POST /api/v1/agent/governance/pre-inference”Legacy single-shot surface. Returns applicable policies + injection block for one prompt.
Prefer POST /conversation/turn for multi-turn agents. Same shape plus incremental diff.
Request
{ "sessionId": "sess_abc", "prompt": "Draft a reply to our Acme account exec", "recentMessages": [], "context": { "surface": "email" }, "endUserContext": null, "policyAreaIds": null, "tokenBudget": 600, "isUpdate": false}Response — same shape as conversation/turn minus the diff field.
POST /api/v1/agent/governance/post-inference
Section titled “POST /api/v1/agent/governance/post-inference”Check a model output for policy violations. Requires post_inference_checking: "allowed" on the API key.
Request
{ "output": "Sure, here's the refund for John Smith (john@acme.com)...", "sessionId": "sess_abc", "prompt": "Draft a refund email", "surface": "email", "policyAreaIds": null, "traceId": "trc_from_pre_inference"}Response (200)
{ "safe": false, "riskScore": 0.72, "violations": [ { "policyId": "pol_pii_01", "matchedText": "john@acme.com", "explanation": "Contains unredacted customer email address.", "severity": 4, "confidence": 0.88, "enforcementType": "fix", "enforcementText": "[REDACTED]" } ], "suggestedRedaction": "Sure, here's the refund for John Smith ([REDACTED])...", "policyCitations": ["pol_pii_01"], "traceId": "trc_..."}API key scopes
Section titled “API key scopes”Every key has a set of scopes. The defaults are enough for the full API.
| Scope | Grants |
|---|---|
governance:read | record_turn, pre-inference, conversation state GET/DELETE |
governance:check | check_output, check_tool_call, post-inference |
policies:read | future: listing policies |
policies:ack | future: recording policy acknowledgements |
feedback:write | future: submitting thumbs-up/down feedback |
API key settings (feature gates)
Section titled “API key settings (feature gates)”Set via the InPolicy dashboard on the API key. Default: all off.
| Setting | Values | Effect |
|---|---|---|
post_inference_checking | "disabled" | "allowed" | Unlocks check_output + checkOutput: true on record_turn |
tool_call_governance | "disabled" | "allowed" | Unlocks check-tool-call |
conversation_ttl_seconds | number | null | Override default 4h TTL. Range [300, 604800]. |