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 Group | Accepts |
|---|---|
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
}
]
}
| Field | Type | Default | Description |
|---|---|---|---|
name | string | required | Policy group name |
threshold | float | 0.5 | Classification threshold 0.0–1.0 |
strictness_level | string | medium | low / medium / high |
is_template | boolean | false | Mark as a shared template |
policies | array | [] | 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"
}
}
| Field | Type | Default | Description |
|---|---|---|---|
name | string | required | Guard name (1–255 chars) |
description | string | — | Optional description |
policy_group_uuids | array | [] | UUIDs of policy groups to link |
enabled | boolean | true | Enable/disable the guard |
settings.max_text_length | int | — | Max characters accepted |
settings.cache_enabled | boolean | — | Cache classification results |
settings.log_requests | boolean | — | Log requests to observability |
settings.overflow | string | truncate | truncate 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" }
]
}
| Field | Type | Required | Description |
|---|---|---|---|
text | string | Yes | Text to classify |
guard_uuid | string | Yes | Guard UUID |
messages | array | No | Conversation 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"
}
| Field | Type | Default | Description |
|---|---|---|---|
text | string | required | Text to classify (min 1 char) |
policies | array | required | Policies to evaluate (1–50 items) |
threshold | float | 0.5 | Classification threshold |
strictness_level | string | medium | low / 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"
}
| Field | Type | Required | Description |
|---|---|---|---|
input | string or string[] | Yes | Text(s) to classify |
model | string | Yes | Guard 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).