Skip to main content

API Reference

This page covers the public PolicyGuard HTTP API. Where a deployment exposes interactive docs, you can also browse them at:

  • OpenAPI JSON: GET /openapi.json
  • Swagger UI: GET /docs
  • ReDoc: GET /redoc

Authentication

PolicyGuard accepts either of:

  • JWT (Bearer): Authorization: Bearer <jwt>
  • API key: X-API-Key: <api_key> (format: sk-vai-...)
Endpoint GroupAccepts
Content safety (/api/topic_guard, /api/topic_guard_oneshot, /api/v1/moderations)JWT or API key
CRUD endpoints (guards, policy groups, policies, templates)JWT only

When auth is disabled (local testing), anonymous access is allowed.


API Keys

API keys are managed through the Virtue Auth integration and require a JWT for management endpoints.

GET /api/api-keys

List API keys for the current user.

POST /api/api-keys

Create a new API key. The full key value is only returned once — store it securely.

Request:

{
"name": "my-key",
"expires_at": "2026-12-31T00:00:00Z",
"scope": "all"
}

Response:

{
"id": "string",
"name": "my-key",
"key": "sk-vai-xxxxxxxxxxxxxxxxxxxxxxxx",
"key_prefix": "sk-vai-xxxx",
"scope": "all",
"expires_at": "2026-12-31T00:00:00Z",
"created_at": "2026-01-15T10:30:00Z"
}

DELETE /api/api-keys/{key_id}

Delete an API key by ID.


Policy Groups

Policy groups bundle individual policies and define the threshold and strictness applied when those policies are evaluated. All endpoints require JWT.

GET /api/policy_groups

List policy groups owned by the current user, including available templates.

GET /api/policy_groups/{group_uuid}

Get a policy group by UUID. Templates are readable by all users.

POST /api/policy_groups

Create a policy group with one or more policies.

Request:

{
"name": "Customer Support Safety",
"threshold": 0.5,
"strictness_level": "medium",
"is_template": false,
"policies": [
{
"name": "PII Disclosure",
"description": "Block disclosure of personal information.",
"block_activities": ["sharing SSN", "sharing credit card numbers"],
"safe_activities": ["general account questions"],
"enabled": true
}
]
}
FieldTypeDefaultDescription
namestringrequiredPolicy group name
thresholdfloat0.5Classification threshold 0.0–1.0
strictness_levelstringmediumlow / medium / high
is_templatebooleanfalseMark as a shared template
policiesarray[]Initial policies

PUT /api/policy_groups/{group_uuid}

Update a policy group. Replaces the full policy list.

DELETE /api/policy_groups/{group_uuid}

Delete a policy group.

GET /api/policy_groups/{group_uuid}/history

Get version history for a policy group.

Query params: limit (int, default 10).

POST /api/policy_groups/{group_uuid}/copy

Copy a policy group. The copy's name defaults to <original name>_copy. Pass ?name= to override.


Policies

Individual policies within a policy group. All endpoints require JWT.

POST /api/policy_groups/{group_uuid}/policies

Add a policy to a policy group.

Request body:

{
"name": "Financial Fraud",
"description": "Block content that facilitates financial fraud.",
"block_activities": [
"wire transfers to unknown accounts",
"sharing bank credentials"
],
"safe_activities": ["general banking education"],
"enabled": true
}

PUT /api/policy_groups/{group_uuid}/policies/{policy_id}

Update a policy by _id. Partial fields are allowed.

DELETE /api/policy_groups/{group_uuid}/policies/{policy_id}

Delete a policy by _id.


Templates

Pre-built policy groups available to all users.

GET /api/templates

List all template policy groups.

POST /api/templates/{template_id}/copy

Copy a template to create a new policy group owned by the current user. Pass ?name= to override the default copy name.


Policy Extraction

POST /api/policy_extraction

Upload a PDF policy document and have PolicyGuard automatically extract policies from it using AI.

Request: multipart/form-data with a file field containing the PDF.

Response: a PolicyGroupOutput with extracted policies populated.


Guards

Guards link one or more policy groups into a single classifier endpoint that customer applications call by UUID. All endpoints require JWT.

GET /api/guards

List guards owned by the current user, including performance metrics.

GET /api/guards/{guard_uuid}

Get a guard by UUID.

POST /api/guards

Create a guard. Returns 201 Created.

Request:

{
"name": "Customer Support Guard",
"description": "Used by the customer support chatbot.",
"policy_group_uuids": ["pg_uuid_1", "pg_uuid_2"],
"enabled": true,
"settings": {
"max_text_length": 128000,
"cache_enabled": true,
"log_requests": true,
"overflow": "truncate"
}
}
FieldTypeDefaultDescription
namestringrequiredGuard name (1–255 chars)
descriptionstringOptional description
policy_group_uuidsarray[]UUIDs of policy groups to link
enabledbooleantrueEnable/disable the guard
settings.max_text_lengthintMax characters accepted
settings.cache_enabledbooleanCache classification results
settings.log_requestsbooleanLog requests to observability
settings.overflowstringtruncatetruncate or throw when text exceeds limit

PUT /api/guards/{guard_uuid}

Update a guard. Only provided fields are changed.

DELETE /api/guards/{guard_uuid}

Delete a guard.


Content Safety

These endpoints accept either a JWT or an API key.

POST /api/topic_guard

Classify text using a saved guard. All policy groups linked to the guard are evaluated in parallel; the content is flagged if any group flags it.

Request body:

{
"text": "Text to evaluate",
"guard_uuid": "gd_your_guard_uuid",
"messages": [
{ "role": "system", "content": "You are a helpful assistant." },
{ "role": "user", "content": "earlier user message" }
]
}
FieldTypeRequiredDescription
textstringYesText to classify
guard_uuidstringYesGuard UUID
messagesarrayNoConversation history (role: system / user / assistant)

Response:

{
"flag": false,
"id": "gd_your_guard_uuid",
"guard": "Customer Support Guard",
"results": [
{
"policy_group_uuid": "pg_example",
"policy_group_name": "Customer Support Safety",
"flagged": false,
"threshold": 0.5,
"strictness_level": "medium",
"probs": { "PII Disclosure": 0.03 },
"categories": { "PII Disclosure": false },
"reasoning": null
}
],
"latency_ms": 85.2
}

POST /api/topic_guard_oneshot

Classify text with ad-hoc policies that are not saved to the database. Useful for testing policies before creating a guard.

Request:

{
"text": "Text to classify",
"policies": [
{
"name": "Example Policy",
"description": "Block X, allow Y.",
"block_activities": ["X"],
"safe_activities": ["Y"],
"enabled": true
}
],
"threshold": 0.5,
"strictness_level": "medium"
}
FieldTypeDefaultDescription
textstringrequiredText to classify (min 1 char)
policiesarrayrequiredPolicies to evaluate (1–50 items)
thresholdfloat0.5Classification threshold
strictness_levelstringmediumlow / medium / high

Response:

{
"flag": false,
"threshold": 0.5,
"strictness_level": "medium",
"probabilities": { "Example Policy": 0.07 },
"results": { "Example Policy": false },
"reasoning": "string",
"latency_ms": 85.2,
"timestamp": "2026-01-15T10:30:00Z"
}

GET /api/cache/stats

Return cache stats. Fields depend on the cache backend.

POST /api/cache/clear

Clear the classification cache.


OpenAI Compatibility

PolicyGuard provides a drop-in replacement for the OpenAI Moderation API. Point your existing OpenAI SDK at PolicyGuard's base URL — no other code changes required.

POST /api/v1/moderations

Classify one or more texts using a guard.

Request:

{
"input": "string or array of strings",
"model": "gd_your_guard_uuid"
}
FieldTypeRequiredDescription
inputstring or string[]YesText(s) to classify
modelstringYesGuard UUID to use as the classifier

Response:

{
"id": "modr-abc123",
"model": "gd_your_guard_uuid",
"results": [
{
"flagged": true,
"categories": { "violence": true, "harassment": false },
"category_scores": { "violence": 0.94, "harassment": 0.08 },
"reasoning": [
"The text expresses intent to cause physical harm to another person."
]
}
]
}

Each item in results corresponds to one input string in the same order.

Python SDK Example

from openai import OpenAI

client = OpenAI(
base_url="https://policyguard.example.com/api/v1",
api_key="sk-vai-your-api-key",
)

response = client.moderations.create(
input="I want to hurt someone",
model="gd_your_guard_uuid",
)

result = response.results[0]
print(result.flagged) # True
print(result.categories) # {"violence": True, ...}
print(result.category_scores) # {"violence": 0.94, ...}

Health and Metrics

GET /health

No authentication required.

{
"status": "healthy",
"version": "2.0.0",
"environment": "development"
}

GET /metrics

Prometheus metrics endpoint. Enabled by metrics.enabled in the deployment config and mounted at metrics.path (default /metrics).