Policies
Create and manage policies that automatically evaluate agent actions.
All endpoints require a Bearer token (Authorization: Bearer aira_live_xxxxx). Base URL: https://api.airaproof.com/api/v1
For a conceptual overview of how policies work, see the Policy Engine guide.
Create Policy
POST /api/v1/policies
Authorization: Bearer aira_live_xxxxxCreates a new policy. Policies are created in draft status by default and must be activated before they evaluate actions.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Human-readable policy name |
description | string | No | Policy description |
mode | string | Yes | Evaluation mode: rules, ai, consensus, or content_scan |
decision | string | Yes | Decision when policy matches: allow, require_approval, or deny |
priority | integer | No | Evaluation priority (higher = first). Default: 0 |
conditions | array | No | Array of condition objects for filtering. Each: {field, op, value}. Operators: eq, neq, in, not_in, contains, regex, gt, lt, gte, lte. |
ai_prompt | string | Conditional | Natural language policy prompt. Required for ai and consensus modes. |
ai_models | string[] | Conditional | Model IDs. Required for ai (1 model) or consensus (2+ models). |
scan_config | object | Conditional | For content_scan mode: {libraries: ["credentials", "pii"], custom_patterns: [...]} |
Example: Rules Policy
curl -X POST https://api.airaproof.com/api/v1/policies \
-H "Authorization: Bearer aira_live_xxxxx" \
-H "Content-Type: application/json" \
-d '{
"name": "Block High-Value Transfers",
"mode": "rules",
"decision": "deny",
"priority": 100,
"conditions": [
{"field": "action_type", "op": "eq", "value": "wire_transfer"},
{"field": "details", "op": "regex", "value": "amount.*[2-9]\\d{4}"}
]
}'Example: AI Policy
curl -X POST https://api.airaproof.com/api/v1/policies \
-H "Authorization: Bearer aira_live_xxxxx" \
-H "Content-Type: application/json" \
-d '{
"name": "PII Export Gate",
"mode": "ai",
"decision": "deny",
"priority": 200,
"ai_prompt": "Deny any action that involves sending customer data to a third-party API unless the agent is the data-export-agent and the endpoint is on our approved list.",
"ai_models": ["claude-opus-4-8"]
}'Example: Consensus Policy
curl -X POST https://api.airaproof.com/api/v1/policies \
-H "Authorization: Bearer aira_live_xxxxx" \
-H "Content-Type: application/json" \
-d '{
"name": "Financial Decision Review",
"mode": "consensus",
"decision": "deny",
"priority": 300,
"ai_prompt": "Deny any financial transaction above $25,000 unless the customer has been verified in the last 30 days.",
"ai_models": ["claude-opus-4-8", "claude-sonnet-4-6", "gpt-5.5"]
}'Example: Content Scan Policy
curl -X POST https://api.airaproof.com/api/v1/policies \
-H "Authorization: Bearer aira_live_xxxxx" \
-H "Content-Type: application/json" \
-d '{
"name": "Credential Scanner",
"mode": "content_scan",
"decision": "deny",
"priority": 100,
"scan_config": {
"libraries": ["credentials", "pii"],
"custom_patterns": [
{
"name": "internal_url",
"regex": "https?://(internal|staging|dev)\\.[a-z0-9.-]+",
"severity": "critical",
"description": "Internal URL in production code"
}
]
},
"conditions": [
{"field": "action_type", "op": "eq", "value": "pr_code_scan"}
]
}'Example: Code Governance Policy (PR-scoped)
curl -X POST https://api.airaproof.com/api/v1/policies \
-H "Authorization: Bearer aira_live_xxxxx" \
-H "Content-Type: application/json" \
-d '{
"name": "AI Agent Governance",
"mode": "ai",
"decision": "deny",
"priority": 100,
"ai_models": ["claude-opus-4-8"],
"ai_prompt": "Review agent code for prompt safety, PII leakage, unbounded tool access...",
"conditions": [
{"field": "action_type", "op": "eq", "value": "pr_code_scan"},
{"field": "agent_id", "op": "contains", "value": "acme/agent-platform"}
]
}'Response (201 Created)
{
"id": "eed209f3-4eb2-486b-bea1-b823a25804b9",
"name": "Block High-Value Transfers",
"mode": "rules",
"decision": "deny",
"priority": 100,
"conditions": [
{"field": "action_type", "op": "eq", "value": "wire_transfer"}
],
"ai_prompt": null,
"ai_models": null,
"scan_config": null,
"active": true,
"created_at": "2026-04-05T10:00:00.000Z",
"updated_at": null,
"request_id": "req_01JAB..."
}Error Codes
| Status | Code | Description |
|---|---|---|
| 400 | INVALID_MODE | Mode must be rules, ai, or consensus |
| 400 | CONDITIONS_REQUIRED | Rules mode requires conditions field |
| 400 | POLICY_TEXT_REQUIRED | AI/consensus mode requires policy_text field |
| 400 | MODELS_REQUIRED | AI/consensus mode requires models field |
| 400 | INVALID_MODEL | One or more model IDs are not supported |
List Policies
GET /api/v1/policies?page=1&per_page=20
Authorization: Bearer aira_live_xxxxxReturns a paginated list of policies for the organization.
Query Parameters
| Parameter | Type | Description |
|---|---|---|
page | integer | Page number (default: 1) |
per_page | integer | Items per page (default: 20, max: 100) |
mode | string | Filter by mode: rules, ai, consensus |
status | string | Filter by status: draft, active, inactive |
Response (200 OK)
{
"policies": [
{
"id": "pol_01JAB...",
"name": "Block High-Value Transfers",
"mode": "rules",
"decision": "deny",
"priority": 100,
"status": "active",
"created_at": "2026-04-05T10:00:00.000Z"
},
{
"id": "pol_01JAC...",
"name": "PII Export Gate",
"mode": "ai",
"decision": "deny",
"priority": 200,
"status": "active",
"created_at": "2026-04-05T10:05:00.000Z"
}
],
"pagination": {
"page": 1,
"per_page": 20,
"total": 2
}
}Get Policy
GET /api/v1/policies/{policy_uuid}
Authorization: Bearer aira_live_xxxxxReturns full policy details including conditions, policy text, and scope.
Response (200 OK)
{
"id": "pol_01JAB...",
"name": "Block High-Value Transfers",
"description": "Deny wire transfers above $25,000",
"mode": "rules",
"decision": "deny",
"priority": 100,
"status": "active",
"conditions": {
"all": [
{ "field": "action_type", "op": "eq", "value": "wire_transfer" },
{ "field": "amount", "op": "gt", "value": 25000 }
]
},
"policy_text": null,
"models": null,
"scope": {
"agent_ids": [],
"action_types": ["wire_transfer"]
},
"evaluation_count": 1482,
"last_evaluated_at": "2026-04-05T14:22:00.000Z",
"created_at": "2026-04-05T10:00:00.000Z",
"updated_at": "2026-04-05T10:00:00.000Z",
"request_id": "req_01JAB..."
}Error Codes
| Status | Code | Description |
|---|---|---|
| 404 | POLICY_NOT_FOUND | Policy does not exist |
Update Policy
PATCH /api/v1/policies/{policy_uuid}
Authorization: Bearer aira_live_xxxxxUpdates a policy. Only the provided fields are changed. Active policies can be updated — changes take effect immediately.
Request Body
All fields from Create Policy are accepted. Only include the fields you want to change.
curl -X PATCH https://api.airaproof.com/api/v1/policies/pol_01JAB... \
-H "Authorization: Bearer aira_live_xxxxx" \
-H "Content-Type: application/json" \
-d '{
"priority": 150,
"description": "Updated: deny wire transfers above $25,000"
}'Response (200 OK)
Returns the full updated policy object (same shape as Get Policy).
Error Codes
| Status | Code | Description |
|---|---|---|
| 404 | POLICY_NOT_FOUND | Policy does not exist |
| 400 | INVALID_MODE | Cannot change mode of an existing policy |
Delete Policy
DELETE /api/v1/policies/{policy_uuid}
Authorization: Bearer aira_live_xxxxxDeletes a policy. Active policies must be deactivated first.
Response (200 OK)
{
"id": "pol_01JAB...",
"deleted": true,
"request_id": "req_01JAB..."
}Error Codes
| Status | Code | Description |
|---|---|---|
| 404 | POLICY_NOT_FOUND | Policy does not exist |
| 409 | POLICY_ACTIVE | Cannot delete an active policy. Deactivate it first. |
Activate Policy
POST /api/v1/policies/{policy_uuid}/activate
Authorization: Bearer aira_live_xxxxxActivates a draft or inactive policy. Once active, the policy evaluates actions on every authorize() call.
Response (200 OK)
{
"id": "pol_01JAB...",
"status": "active",
"activated_at": "2026-04-05T11:00:00.000Z",
"request_id": "req_01JAB..."
}Error Codes
| Status | Code | Description |
|---|---|---|
| 404 | POLICY_NOT_FOUND | Policy does not exist |
| 409 | ALREADY_ACTIVE | Policy is already active |
Deactivate Policy
POST /api/v1/policies/{policy_uuid}/deactivate
Authorization: Bearer aira_live_xxxxxDeactivates an active policy. Deactivated policies are not evaluated.
Response (200 OK)
{
"id": "pol_01JAB...",
"status": "inactive",
"deactivated_at": "2026-04-05T12:00:00.000Z",
"request_id": "req_01JAB..."
}Error Codes
| Status | Code | Description |
|---|---|---|
| 404 | POLICY_NOT_FOUND | Policy does not exist |
| 409 | NOT_ACTIVE | Policy is not currently active |
Dry Run
POST /api/v1/policies/{policy_uuid}/dry-run
Authorization: Bearer aira_live_xxxxxTests a policy against a simulated action without recording the evaluation or producing a receipt. Works on both draft and active policies.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
action_type | string | Yes | Simulated action type |
details | string | Yes | Simulated action details |
agent_id | string | No | Simulated agent ID |
model_id | string | No | Simulated model ID |
Example Request
curl -X POST https://api.airaproof.com/api/v1/policies/pol_01JAB.../dry-run \
-H "Authorization: Bearer aira_live_xxxxx" \
-H "Content-Type: application/json" \
-d '{
"action_type": "wire_transfer",
"details": "Transfer $50,000 to vendor account",
"agent_id": "payments-agent",
"model_id": "claude-sonnet-4-6"
}'Response (200 OK)
{
"policy_uuid": "pol_01JAB...",
"policy_name": "Block High-Value Transfers",
"decision": "deny",
"reasoning": "Wire transfer amount exceeds $25,000 threshold.",
"confidence": 0.96,
"dry_run": true,
"request_id": "req_01JAB..."
}Error Codes
| Status | Code | Description |
|---|---|---|
| 404 | POLICY_NOT_FOUND | Policy does not exist |
Policy Decisions on the Authorization Response
Policy evaluation results are not returned as a separate object on the Authorization response. Instead, the outcome is reflected directly in the action's lifecycle:
| Decision | Resulting status | Notes |
|---|---|---|
allow | authorized | Agent may execute immediately. |
require_approval | pending_approval | Held for human review; a warning may be included in the warnings field. |
deny | request fails | The API returns 403 POLICY_DENIED; the action is recorded with status denied_by_policy. |
When a policy raises a warning (for example, an approval policy firing), the message appears in the warnings array on the Authorization response:
{
"action_uuid": "act_01JAB...",
"status": "pending_approval",
"created_at": "2026-04-07T14:30:00.000Z",
"request_id": "req_01JAB...",
"warnings": [
"Action held for approval by policy 'High-Value Transfers'."
]
}A denial is surfaced as a 403 POLICY_DENIED error containing the policy_uuid in details:
{
"code": "POLICY_DENIED",
"message": "Action denied by policy 'Block High-Value Transfers': Transfer amount exceeds 25,000 EUR threshold.",
"details": {
"action_uuid": "act_01JAB...",
"policy_uuid": "pol_01JAB..."
},
"request_id": "req_01JAB..."
}