Skip to content

Policy Engine API

The Policy Engine API lets admins build and manage the full policy stack: packs containing rules, chains that assemble packs in priority order, and a simulation endpoint for safe pre-flight testing. All endpoints require admin authentication (Authorization: Bearer <admin-token>).

A policy pack is a named, versioned container of rules. Rules within a pack are evaluated in ascending sequence order. Each rule declares:

  • conditions — what must match (entity types, regex, provider/model, risk score, user group)
  • applies_toinput, output, or both
  • action — the terminal action taken on a match (ALLOW, BLOCK, CANCEL, REDACT, ROUTE_TO)

All active conditions within a single rule are ANDed. The first rule whose conditions all match fires its action; subsequent rules in the same pack are not evaluated.

Pack types:

Type Description
custom Tenant-created packs — fully editable
bundle System-supplied compliance bundles — rules are read-only
template Instantiated from a policy template

A chain assembles multiple packs into an ordered sequence for a given scope. Two scopes exist:

Scope Description
org The organisation-level primary chain — applies to all users
user Per-user personal override chain — evaluated before the org chain

During evaluation, the user chain is checked first. If no terminal action is reached, the org chain is evaluated next.

Each chain has a combining_algorithm:

Algorithm Behaviour
first_applicable Firewall default. Evaluation stops at the first matched terminal action.
deny_overrides XACML-style. All rules are evaluated; any BLOCK or CANCEL takes precedence over ALLOW.

The fully resolved policy for a specific user combines the user chain, org chain, and all System Default settings via a three-level cascade:

System Default → Group (lowest priority)
→ Org chain (policies)
→ User chain (personal overrides, highest priority)

GET /api/v1/admin/policy-packs/

Returns all packs visible to the tenant — both custom packs and system bundles.

Response 200 OK

[
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"tenant_id": "9c0e1d2f-...",
"name": "PCI-DSS Baseline",
"description": "Blocks transmission of PANs and CVVs.",
"pack_type": "bundle",
"compliance_standard": "PCI-DSS",
"version": "1.0.0",
"is_active": true,
"rule_count": 8,
"created_at": "2025-11-01T00:00:00Z",
"updated_at": "2026-01-15T12:00:00Z"
}
]

POST /api/v1/admin/policy-packs/

Creates a new custom pack. Bundle and template packs cannot be created via this endpoint.

Request body

{
"name": "Internal Data Policy",
"description": "Prevents leaking confidential project names.",
"compliance_standard": null
}

Response 201 Created — returns the created pack object.


GET /api/v1/admin/policy-packs/{id}

Returns the pack metadata plus the full ordered list of rules.

Response 200 OK

{
"id": "3fa85f64-...",
"name": "Internal Data Policy",
"pack_type": "custom",
"version": "1.0.0",
"is_active": true,
"rule_count": 2,
"rules": [
{
"id": "a1b2c3d4-...",
"name": "Block project code names",
"sequence": 1,
"applies_to": "input",
"conditions": {
"regex_patterns": ["Project (?:Apollo|Hermes|Athena)"]
},
"action": { "type": "BLOCK", "message": "Confidential project names are not permitted." },
"is_active": true
}
]
}

PUT /api/v1/admin/policy-packs/{id}

Updates the pack name, description, or is_active flag. Only custom packs can be updated.

Request body (all fields optional)

{
"name": "Internal Data Policy v2",
"description": "Updated description.",
"is_active": false
}

Response 200 OK — returns the updated pack.


DELETE /api/v1/admin/policy-packs/{id}

Permanently deletes a custom pack and its rules. Returns 204 No Content. System bundles cannot be deleted.


GET /api/v1/admin/policy-packs/{id}/rules/

Returns all rules for the specified pack, ordered by sequence.


POST /api/v1/admin/policy-packs/{id}/rules/

Adds a new rule to the pack. The rule is appended at the end of the sequence unless sequence is specified.

Request body

{
"name": "Redact SSN on output",
"description": "Replaces detected SSNs in model responses.",
"sequence": 5,
"applies_to": "output",
"conditions": {
"entity_types": ["ssn"],
"min_risk_score": 0.8
},
"action": {
"type": "REDACT",
"replacement": "[SSN REDACTED]"
},
"is_active": true
}

Condition fields

Field Type Description
entity_types string[] DLP entity type labels (e.g. "credit_card", "ssn", "api_key")
regex_patterns string[] One or more regex patterns — any match fires
providers string[] Limit to specific AI providers (e.g. "openai", "anthropic")
models string[] Limit to specific model IDs
user_groups string[] Limit to users in these groups
min_risk_score float Minimum DLP confidence score (0.0–1.0)

Action types

Action type Additional fields Description
ALLOW Explicitly permit; stops chain evaluation
BLOCK message Reject the request/response with a 400
CANCEL message Cancel the streaming response mid-flight
REDACT replacement Replace matched spans in the text
ROUTE_TO endpoint_id Forward to an alternative provider endpoint

Response 201 Created — returns the created rule.


PUT /api/v1/admin/policy-packs/{id}/rules/{rule_id}

Updates an existing rule. Only provided fields are modified.

Response 200 OK


DELETE /api/v1/admin/policy-packs/{id}/rules/{rule_id}

Returns 204 No Content.


POST /api/v1/admin/policy-packs/{id}/rules/reorder

Sets a new sequence for one or more rules in a single atomic operation.

Request body

{
"entries": [
{ "id": "a1b2c3d4-...", "sequence": 1 },
{ "id": "b2c3d4e5-...", "sequence": 2 },
{ "id": "c3d4e5f6-...", "sequence": 3 }
]
}

Response 200 OK — returns the full updated rule list.


GET /api/v1/admin/policy-chains/

Returns all policy chains (user + org scope) with referenced pack summaries in sequence order.

Response 200 OK

[
{
"id": "chain-uuid-...",
"scope": "org",
"combining_algorithm": "first_applicable",
"packs": [
{
"id": "entry-uuid-...",
"pack_id": "pack-uuid-...",
"pack_name": "PCI-DSS Baseline",
"pack_type": "bundle",
"rule_count": 8,
"sequence": 1,
"is_active": true
}
],
"created_at": "2025-11-01T00:00:00Z",
"updated_at": "2026-03-10T08:00:00Z"
}
]

PUT /api/v1/admin/policy-chains/org

Replaces the chain’s pack order and combining algorithm. All existing entries are replaced.

Request body

{
"packs": [
{ "id": "pack-uuid-a", "sequence": 1 },
{ "id": "pack-uuid-b", "sequence": 2 }
],
"combining_algorithm": "deny_overrides"
}

Response 200 OK


POST /api/v1/admin/policy-chains/simulate

Evaluates a hypothetical prompt against the org chain without routing to any AI provider. Returns the match result and a full evaluation trace showing which rules were checked and why.

Request body

{
"prompt": "Please send me a list of all employees with their SSNs.",
"provider": "openai",
"model": "gpt-4o",
"user_groups": ["finance"],
"content_categories": [],
"product": null,
"adversarial_risk_score": null,
"threat_types": null,
"cumulative_risk_score": null
}
Field Type Required Description
prompt string Yes The hypothetical prompt text to evaluate
provider string Yes AI provider name (e.g., "openai", "anthropic")
model string Yes Model ID (e.g., "gpt-4o")
user_groups string[] No User group memberships to simulate (default [])
content_categories string[] No Content category slugs; when provided, used directly instead of running the classifier
product string No Product override: ai_chat (default), ai_app_protect, smtp_scan, api_scan
adversarial_risk_score float No Simulated adversarial risk score (0.0–1.0) for rules using adversarial_risk_score_min
threat_types string[] No Simulated threat type labels
cumulative_risk_score float No Simulated cumulative risk score (0.0–1.0) for rules using cumulative_risk_score_min

Response 200 OK

{
"matched": true,
"matched_pack_id": "pack-uuid-...",
"matched_pack_name": "PII Baseline",
"matched_rule_id": "rule-uuid-...",
"matched_rule_name": "Block SSN requests",
"matched_sequence": 2,
"action": { "type": "BLOCK", "message": "PII requests are not permitted." },
"match_reason": "entity_type=ssn matched",
"evaluation_trace": [
{
"pack_id": "pack-uuid-...",
"pack_name": "PII Baseline",
"rule_id": "rule-uuid-...",
"rule_name": "Allow finance group PII preview",
"sequence": 1,
"matched": false,
"match_reason": null
},
{
"pack_id": "pack-uuid-...",
"pack_name": "PII Baseline",
"rule_id": "rule-uuid-...",
"rule_name": "Block SSN requests",
"sequence": 2,
"matched": true,
"match_reason": "entity_type=ssn matched"
}
]
}

The trace lists every rule evaluated, in order, until the chain terminates. Use this to debug unexpected allow/block decisions before deploying policy changes.


GET /api/v1/admin/policy-packs/bundles/

Returns all system-supplied policy bundles available for inclusion in org chains.


GET /api/v1/admin/policy/effective/{user_id}

Resolves the fully effective policy for a specific user by cascading System Default → Group → User. Each setting in the response includes a source field indicating where the value originated.

Response 200 OK

{
"user_id": "user-uuid-...",
"quotas": {
"daily_token_limit": { "value": 500000, "source": "group" },
"monthly_token_limit": { "value": 5000000, "source": "system_default" }
},
"model_access": {
"allowed_providers": { "value": ["openai", "anthropic"], "source": "org_chain" }
},
"dlp_rules": { "source": "org_chain" },
"content_filters": { "source": "org_chain" }
}

Errors

Status Condition
404 Not Found User ID does not exist in the tenant

Policy templates provide reusable configuration bundles that can be applied to groups with a single API call.

GET /api/v1/admin/policy-templates
GET /api/v1/admin/policy-templates/{template_id}
POST /api/v1/admin/policy-templates

Request body

{
"name": "Healthcare Baseline",
"description": "HIPAA-aligned defaults for clinical users.",
"template_type": "compliance",
"config": {
"dlp_rules": ["phi_detector"],
"content_filters": ["medical_jailbreak"]
}
}
PUT /api/v1/admin/policy-templates/{template_id}
DELETE /api/v1/admin/policy-templates/{template_id}

Returns 204 No Content.

POST /api/v1/admin/policy-templates/apply/{group_id}/{template_id}

Applies the template’s configuration to the specified group. Returns an ApplyTemplateResponse summarising which settings were modified.


Status Meaning
400 Bad Request Invalid request body or rule validation failure
403 Forbidden Caller is not an admin
404 Not Found Pack, rule, chain, or template not found
409 Conflict Attempt to mutate a read-only bundle pack