Aira

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_xxxxx

Creates a new policy. Policies are created in draft status by default and must be activated before they evaluate actions.

Request Body

FieldTypeRequiredDescription
namestringYesHuman-readable policy name
descriptionstringNoPolicy description
modestringYesEvaluation mode: rules, ai, or consensus
decisionstringYesDecision when policy matches: allow or deny
priorityintegerNoEvaluation priority (higher = first). Default: 0
conditionsobjectConditionalJSON condition object. Required when mode is rules.
policy_textstringConditionalNatural language policy text. Required when mode is ai or consensus.
modelsstring[]ConditionalModel IDs for evaluation. Required when mode is ai (1 model) or consensus (2-5 models).
scope.agent_idsstring[]NoLimit policy to specific agents. Empty = all agents.
scope.action_typesstring[]NoLimit policy to specific action types. Empty = all types.

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",
    "description": "Deny wire transfers above $25,000",
    "mode": "rules",
    "decision": "deny",
    "priority": 100,
    "conditions": {
      "all": [
        { "field": "action_type", "operator": "equals", "value": "wire_transfer" },
        { "field": "amount", "operator": "gt", "value": 25000 }
      ]
    },
    "scope": {
      "action_types": ["wire_transfer"]
    }
  }'

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,
    "policy_text": "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.",
    "models": ["claude-sonnet-4-6"]
  }'

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,
    "policy_text": "Deny any financial transaction above $25,000 unless the customer has been verified in the last 30 days.",
    "models": ["claude-sonnet-4-6", "gpt-5.4", "gemini-3.1-pro"]
  }'

Response (201 Created)

{
  "id": "pol_01JAB...",
  "name": "Block High-Value Transfers",
  "description": "Deny wire transfers above $25,000",
  "mode": "rules",
  "decision": "deny",
  "priority": 100,
  "status": "draft",
  "conditions": {
    "all": [
      { "field": "action_type", "operator": "equals", "value": "wire_transfer" },
      { "field": "amount", "operator": "gt", "value": 25000 }
    ]
  },
  "policy_text": null,
  "models": null,
  "scope": {
    "agent_ids": [],
    "action_types": ["wire_transfer"]
  },
  "created_at": "2026-04-05T10:00:00.000Z",
  "updated_at": "2026-04-05T10:00:00.000Z",
  "request_id": "req_01JAB..."
}

Error Codes

StatusCodeDescription
400INVALID_MODEMode must be rules, ai, or consensus
400CONDITIONS_REQUIREDRules mode requires conditions field
400POLICY_TEXT_REQUIREDAI/consensus mode requires policy_text field
400MODELS_REQUIREDAI/consensus mode requires models field
400INVALID_MODELOne or more model IDs are not supported

List Policies

GET /api/v1/policies?page=1&per_page=20
Authorization: Bearer aira_live_xxxxx

Returns a paginated list of policies for the organization.

Query Parameters

ParameterTypeDescription
pageintegerPage number (default: 1)
per_pageintegerItems per page (default: 20, max: 100)
modestringFilter by mode: rules, ai, consensus
statusstringFilter 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_xxxxx

Returns 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", "operator": "equals", "value": "wire_transfer" },
      { "field": "amount", "operator": "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

StatusCodeDescription
404POLICY_NOT_FOUNDPolicy does not exist

Update Policy

PATCH /api/v1/policies/{policy_uuid}
Authorization: Bearer aira_live_xxxxx

Updates 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

StatusCodeDescription
404POLICY_NOT_FOUNDPolicy does not exist
400INVALID_MODECannot change mode of an existing policy

Delete Policy

DELETE /api/v1/policies/{policy_uuid}
Authorization: Bearer aira_live_xxxxx

Deletes a policy. Active policies must be deactivated first.

Response (200 OK)

{
  "id": "pol_01JAB...",
  "deleted": true,
  "request_id": "req_01JAB..."
}

Error Codes

StatusCodeDescription
404POLICY_NOT_FOUNDPolicy does not exist
409POLICY_ACTIVECannot delete an active policy. Deactivate it first.

Activate Policy

POST /api/v1/policies/{policy_uuid}/activate
Authorization: Bearer aira_live_xxxxx

Activates 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

StatusCodeDescription
404POLICY_NOT_FOUNDPolicy does not exist
409ALREADY_ACTIVEPolicy is already active

Deactivate Policy

POST /api/v1/policies/{policy_uuid}/deactivate
Authorization: Bearer aira_live_xxxxx

Deactivates 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

StatusCodeDescription
404POLICY_NOT_FOUNDPolicy does not exist
409NOT_ACTIVEPolicy is not currently active

Dry Run

POST /api/v1/policies/{policy_uuid}/dry-run
Authorization: Bearer aira_live_xxxxx

Tests a policy against a simulated action without recording the evaluation or producing a receipt. Works on both draft and active policies.

Request Body

FieldTypeRequiredDescription
action_typestringYesSimulated action type
detailsstringYesSimulated action details
agent_idstringNoSimulated agent ID
model_idstringNoSimulated 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

StatusCodeDescription
404POLICY_NOT_FOUNDPolicy 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:

DecisionResulting statusNotes
allowauthorizedAgent may execute immediately.
require_approvalpending_approvalHeld for human review; a warning may be included in the warnings field.
denyrequest failsThe 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..."
}

On this page