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:

TypeDescription
customTenant-created packs — fully editable
bundleSystem-supplied compliance bundles — rules are read-only
templateInstantiated from a policy template

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

ScopeDescription
orgThe organisation-level primary chain — applies to all users
userPer-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:

AlgorithmBehaviour
first_applicableFirewall default. Evaluation stops at the first matched terminal action.
deny_overridesXACML-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/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/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/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/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/admin/policy-packs/{id}

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


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

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


POST /api/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

FieldTypeDescription
entity_typesstring[]DLP entity type labels (e.g. "credit_card", "ssn", "api_key")
regex_patternsstring[]One or more regex patterns — any match fires
providersstring[]Limit to specific AI providers (e.g. "openai", "anthropic")
modelsstring[]Limit to specific model IDs
user_groupsstring[]Limit to users in these groups
min_risk_scorefloatMinimum DLP confidence score (0.0–1.0)

Action types

Action typeAdditional fieldsDescription
ALLOWExplicitly permit; stops chain evaluation
BLOCKmessageReject the request/response with a 400
CANCELmessageCancel the streaming response mid-flight
REDACTreplacementReplace matched spans in the text
ROUTE_TOendpoint_idForward to an alternative provider endpoint

Response 201 Created — returns the created rule.


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

Updates an existing rule. Only provided fields are modified.

Response 200 OK


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

Returns 204 No Content.


POST /api/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/admin/policy-chains/

Returns the organisation’s policy chain including all 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/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/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"]
}

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/admin/policy-packs/bundles/

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


GET /api/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

StatusCondition
404 Not FoundUser 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/admin/policy-templates
GET /api/admin/policy-templates/{template_id}
POST /api/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/admin/policy-templates/{template_id}
DELETE /api/admin/policy-templates/{template_id}

Returns 204 No Content.

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

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


StatusMeaning
400 Bad RequestInvalid request body or rule validation failure
403 ForbiddenCaller is not an admin
404 Not FoundPack, rule, chain, or template not found
409 ConflictAttempt to mutate a read-only bundle pack