Content Filters
Content Filters provide a rule-based content moderation layer that runs independently of the DLP pipeline. You can block requests containing specific keywords or topics, or prepend custom instructions to the system prompt for all requests in a given scope.
Filters are evaluated in ascending priority order (lower number = higher priority). The first matching block filter wins — once a request is blocked, remaining filters are not evaluated. Custom instruction filters are not blocking; they accumulate and all apply.
Filter types
Section titled “Filter types”| Type | Slug | Behavior | Config schema |
|---|---|---|---|
| Keyword Block | keyword_block |
Blocks requests containing any of the listed keywords (case-insensitive substring match) | {"keywords": ["term1", "term2"], "message": "..."} |
| Topic Block | topic_block |
Blocks requests matching any of the listed topics (case-insensitive substring match) | {"topics": ["topic1", "topic2"], "message": "..."} |
| Custom Instruction | custom_instruction |
Prepends the instruction to the system prompt for all requests in scope | {"instruction": "Always respond in formal English."} |
The message field in block filters is optional. When omitted, the platform returns a default message:
- Keyword block: “Request blocked: contains prohibited content.”
- Topic block: “Request blocked: topic not allowed.”
Each filter has a scope that determines which requests it applies to:
| Scope | Behavior |
|---|---|
global |
Applies to all requests in the organization |
group |
Applies only to requests from users in the specified group. Requires group_id. |
Global filters always evaluate. Group-scoped filters evaluate only when the requesting user belongs to the filter’s target group.
Evaluation order
Section titled “Evaluation order”- All enabled filters are loaded from the database, sorted by
priorityascending (lower = higher priority, default is 100). - Each filter is checked for scope applicability (global or matching group).
- For
keyword_blockandtopic_blockfilters: if the user’s input matches, the request is blocked immediately. No further filters are evaluated. - For
custom_instructionfilters: the instruction is collected. All matching custom instruction filters contribute their instructions, which are prepended to the system prompt before the model call.
Admin API reference
Section titled “Admin API reference”All endpoints require admin authentication. Base path: /api/v1/admin/content-filters/.
| Method | Path | Description |
|---|---|---|
GET |
/api/v1/admin/content-filters/ |
List all content filters (ordered by priority) |
GET |
/api/v1/admin/content-filters/{filter_id} |
Get a single content filter by ID |
POST |
/api/v1/admin/content-filters/ |
Create a new content filter |
PUT |
/api/v1/admin/content-filters/{filter_id} |
Update an existing content filter |
DELETE |
/api/v1/admin/content-filters/{filter_id} |
Delete a content filter |
Create a keyword block filter
Section titled “Create a keyword block filter”curl -X POST https://platform.arbitex.ai/api/v1/admin/content-filters/ \ -H "Authorization: Bearer $ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "Block competitor mentions", "description": "Prevent users from discussing competitor products", "filter_type": "keyword_block", "config": { "keywords": ["CompetitorX", "RivalProduct", "AltVendor"], "message": "Competitor discussions are not permitted in this channel." }, "scope": "global", "enabled": true, "priority": 10 }'Response (201 Created):
{ "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "name": "Block competitor mentions", "description": "Prevent users from discussing competitor products", "filter_type": "keyword_block", "config": { "keywords": ["CompetitorX", "RivalProduct", "AltVendor"], "message": "Competitor discussions are not permitted in this channel." }, "scope": "global", "group_id": null, "enabled": true, "priority": 10, "created_at": "2026-04-08T20:00:00Z", "updated_at": "2026-04-08T20:00:00Z"}Create a group-scoped custom instruction
Section titled “Create a group-scoped custom instruction”curl -X POST https://platform.arbitex.ai/api/v1/admin/content-filters/ \ -H "Authorization: Bearer $ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "Legal team compliance instruction", "description": "Remind AI to include legal disclaimers", "filter_type": "custom_instruction", "config": { "instruction": "You are assisting a legal professional. Always include appropriate legal disclaimers and note that your responses do not constitute legal advice." }, "scope": "group", "group_id": "f0e1d2c3-b4a5-6789-0123-456789abcdef", "enabled": true, "priority": 50 }'List all filters
Section titled “List all filters”curl https://platform.arbitex.ai/api/v1/admin/content-filters/ \ -H "Authorization: Bearer $ADMIN_TOKEN"Returns all filters for the organization, sorted by priority ascending.
Update a filter
Section titled “Update a filter”curl -X PUT https://platform.arbitex.ai/api/v1/admin/content-filters/a1b2c3d4-e5f6-7890-abcd-ef1234567890 \ -H "Authorization: Bearer $ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "enabled": false }'Partial updates are supported. Only include the fields you want to change.
Delete a filter
Section titled “Delete a filter”curl -X DELETE https://platform.arbitex.ai/api/v1/admin/content-filters/a1b2c3d4-e5f6-7890-abcd-ef1234567890 \ -H "Authorization: Bearer $ADMIN_TOKEN"Returns 204 No Content on success.
Test a rule
Section titled “Test a rule”Validate a rule configuration and test it against sample content without saving.
POST /api/v1/admin/content-filters/testAuthorization: Bearer <admin-token>Content-Type: application/json
{ "rule": { "filter_type": "keyword_block", "config": { "keywords": ["confidential", "internal-only"] } }, "sample_text": "This document is confidential — do not distribute."}Response 200 OK:
{ "matched": true, "action": "block", "matches": [ { "match": "confidential", "start": 18, "end": 30 } ], "execution_time_ms": 0.4}Bulk import rules
Section titled “Bulk import rules”Import multiple rules from a JSON array. Existing rules are not affected unless upsert: true is set and name matches.
POST /api/v1/admin/content-filters/bulk-importAuthorization: Bearer <admin-token>Content-Type: application/json
{ "upsert": false, "rules": [ { ... rule object without id ... }, { ... } ]}Response 200 OK:
{ "created": 5, "updated": 0, "errors": []}Audit log integration
Section titled “Audit log integration”Content filter trigger events appear in audit logs with action content_filter.triggered:
{ "action": "content_filter.triggered", "details": { "rule_id": "cfr_01HXYZ", "rule_name": "Block Competitor Mentions", "filter_action": "block", "scope": "request", "match_count": 1 }}Query recent trigger events:
curl -H "Authorization: Bearer $ADMIN_TOKEN" \ "https://platform.arbitex.ai/api/v1/admin/audit-logs?action=content_filter.triggered&limit=50"Validation rules
Section titled “Validation rules”The API enforces the following validation:
keyword_blockrequires a non-emptykeywordslist inconfigtopic_blockrequires a non-emptytopicslist inconfigcustom_instructionrequires a non-emptyinstructionstring inconfiggroupscope requires agroup_id- Invalid combinations return
400 Bad Request
Content filter fields
Section titled “Content filter fields”| Field | Type | Required | Default | Description |
|---|---|---|---|---|
name |
string (max 255) | yes | — | Human-readable label |
description |
string (max 1000) | no | null | Purpose description |
filter_type |
enum | yes | — | keyword_block, topic_block, or custom_instruction |
config |
object | yes | — | Type-specific configuration (see Filter Types above) |
scope |
enum | no | global |
global or group |
group_id |
UUID | conditional | null | Required when scope is group |
enabled |
boolean | no | true |
Whether the filter is active |
priority |
integer | no | 100 |
Evaluation order (lower = higher priority) |