Skip to content

API reference: Content filters

Content filters allow admins to block requests containing specific keywords or topics, or to prepend custom instructions to the system prompt. Filters are evaluated before the DLP pipeline and policy engine.

All endpoints require admin authentication. Authentication uses the standard admin Bearer token.

Base path: /api/admin/content-filters


MethodPathDescription
GET/api/admin/content-filters/List all content filters
GET/api/admin/content-filters/{filter_id}Get a single content filter
POST/api/admin/content-filters/Create a content filter
PUT/api/admin/content-filters/{filter_id}Update a content filter
DELETE/api/admin/content-filters/{filter_id}Delete a content filter

FieldTypeDescription
idUUIDUnique identifier for the filter
namestringHuman-readable name
descriptionstring | nullOptional description
filter_typestringOne of keyword_block, topic_block, custom_instruction
configobjectType-specific configuration (see below)
scopestring"org" or "group"
group_idUUID | nullRequired when scope = "group"
enabledbooleanWhether the filter is active
priorityintegerEvaluation priority — lower number = higher priority
tenant_idUUIDTenant this filter belongs to

keyword_block

{
"keywords": ["confidential", "internal-only", "do not distribute"]
}

Blocks any request whose prompt contains one or more of the listed keywords (case-insensitive).

topic_block

{
"topics": ["competitor analysis", "M&A targets", "unreleased roadmap"]
}

Blocks requests whose content is classified as belonging to one of the listed topics.

custom_instruction

{
"instruction": "You are a professional assistant. Do not discuss personal opinions or political topics."
}

Prepends the instruction string to the system prompt of every AI request that matches the filter’s scope.


List all content filters for the admin’s organization, ordered by priority ascending (lower number = higher priority, evaluated first).

Authentication: Admin Bearer token

Response 200 OK:

[
{
"id": "cf_01abc123-...",
"name": "block-confidential-keywords",
"description": "Block prompts containing confidentiality markers",
"filter_type": "keyword_block",
"config": {
"keywords": ["confidential", "proprietary", "internal only"]
},
"scope": "org",
"group_id": null,
"enabled": true,
"priority": 10,
"tenant_id": "ten_01..."
}
]

Returns an empty array if no filters exist.


GET /api/admin/content-filters/{filter_id}

Section titled “GET /api/admin/content-filters/{filter_id}”

Get a single content filter by its UUID.

Path parameters:

ParameterTypeDescription
filter_idUUIDThe content filter’s UUID

Response 200 OK: ContentFilter object (same schema as list item above).

Response 404 Not Found:

{ "detail": "Content filter not found" }

Create a new content filter.

Authentication: Admin Bearer token

Request body:

FieldTypeRequiredDescription
namestringYesFilter name
descriptionstringNoOptional description
filter_typestringYeskeyword_block, topic_block, or custom_instruction
configobjectYesType-specific config (see config shapes above)
scopestringYes"org" or "group"
group_idUUIDConditionalRequired when scope = "group"
enabledbooleanNoDefaults to true
priorityintegerYesEvaluation priority

Example request — create a keyword block filter:

POST /api/admin/content-filters/
Authorization: Bearer <admin_token>
Content-Type: application/json
{
"name": "block-confidential-keywords",
"filter_type": "keyword_block",
"config": {
"keywords": ["confidential", "proprietary", "internal only"]
},
"scope": "org",
"enabled": true,
"priority": 10
}

Response 201 Created: The created ContentFilter object.

Validation errors 400 Bad Request:

  • scope = "group" but no group_id provided
  • filter_type = "keyword_block" but config.keywords is missing or empty
  • filter_type = "topic_block" but config.topics is missing or empty
  • filter_type = "custom_instruction" but config.instruction is missing or empty

PUT /api/admin/content-filters/{filter_id}

Section titled “PUT /api/admin/content-filters/{filter_id}”

Update an existing content filter. All fields are optional — only provided fields are updated.

Path parameters:

ParameterTypeDescription
filter_idUUIDThe content filter’s UUID

Request body: Partial ContentFilter (same fields as POST, all optional).

Example — disable a filter:

PUT /api/admin/content-filters/cf_01abc123-...
Authorization: Bearer <admin_token>
Content-Type: application/json
{
"enabled": false
}

Response 200 OK: The updated ContentFilter object.

Response 404 Not Found: Filter not found. Response 400 Bad Request: Validation error (same rules as POST).


DELETE /api/admin/content-filters/{filter_id}

Section titled “DELETE /api/admin/content-filters/{filter_id}”

Delete a content filter permanently.

Path parameters:

ParameterTypeDescription
filter_idUUIDThe content filter’s UUID

Response 204 No Content: Filter deleted.

Response 404 Not Found: Filter not found.


Filters are evaluated in ascending priority order (lower number = evaluated first). The first matching filter determines the outcome for the request. If a keyword_block or topic_block filter matches, the request is rejected before reaching the DLP pipeline.

custom_instruction filters do not block — they modify the system prompt and evaluation continues to the next filter. If multiple custom_instruction filters match, all instructions are applied in priority order.