TAP Content Safety API
Overview
TAP can call the content safety moderation API to analyze text and images before deciding whether content needs review, blocking, or normal processing.
The TAP-facing tool runs the auditable TAP content safety workflow. That workflow combines Azure AI Content Safety with the TAP local semantic moderation layer for text, including spam, harassment, self-harm, sexual, violence, and hate signals. Image-only requests continue to use Azure Content Safety and skip the local text-only model.
The endpoint returns moderation findings only. It does not update TAP posts, tags, captions, or user records.
All requests require the normal APIM authentication headers: Authorization: Bearer {access_token} and Ocp-Apim-Subscription-Key: {subscription_key}.
Endpoints
The APIM paths include /ai. Direct Mastra app smoke tests use the same paths without /ai.
| Method | Endpoint | Description |
|---|---|---|
POST | /ai/tap/tools/content-safety | TAP-facing tool. Runs the TAP workflow and returns the standard { data } tool envelope. |
POST | /ai/other/tools/azure-content-safety | Low-level Azure-only provider tool for direct Azure Content Safety checks. |
In Bruno, baseUrl already includes /ai, so Bruno request files use /tap/tools/content-safety and /other/tools/azure-content-safety.
Use /tap/tools/content-safety for application calls that need TAP spam and semantic safety detection. Use /other/tools/azure-content-safety only when you specifically need the low-level Azure provider result.
Request
Send text, images, or both. At least one of text or images is required.
{
"text": "Example text to moderate.",
"images": [
{
"url": "https://example.test/signed-image.jpg",
"label": "post-12345"
}
],
"threshold": 2,
"categories": ["Hate", "Violence"],
"azureTimeoutMs": 750,
"haltOnBlocklistHit": true
}
Example TAP policy moderation request:
curl -X POST "{tap_apim_base_url}/ai/tap/tools/content-safety" \
-H "Authorization: Bearer {access_token}" \
-H "Ocp-Apim-Subscription-Key: {subscription_key}" \
-H "Content-Type: application/json" \
-d '{
"text": "Example text to moderate.",
"threshold": 2,
"haltOnBlocklistHit": true
}'
Example low-level Azure-only request:
curl -X POST "{tap_apim_base_url}/ai/other/tools/azure-content-safety" \
-H "Authorization: Bearer {access_token}" \
-H "Ocp-Apim-Subscription-Key: {subscription_key}" \
-H "Content-Type: application/json" \
-d '{
"text": "Example text to moderate.",
"threshold": 2
}'
Request Fields
| Field | Type | Required | Description |
|---|---|---|---|
text | string | No | Text to moderate. Required when images is omitted. Maximum 10,000 characters. |
images | array | No | Images to moderate. Required when text is omitted. |
images[].url | string | No | HTTP or HTTPS image URL accessible by the moderation service. Required when images[].data is omitted. |
images[].data | string | No | Base64 image payload or data URL. Required when images[].url is omitted. |
images[].label | string | No | Caller-provided correlation label returned with the image result. |
threshold | integer | No | Severity threshold from 0 to 7. Defaults to the TAP workflow threshold. |
categories | string array | No | Optional Azure Content Safety category filter. |
azureTimeoutMs | integer | No | Optional timeout for the Azure provider branch. Text-only requests default lower than image requests. |
blocklistNames | string array | No | Optional custom blocklists to evaluate against text. Only send names that are configured in the target environment. |
haltOnBlocklistHit | boolean | No | When true, Azure text moderation stops after the first blocklist hit. |
Tool Response
/tap/tools/content-safety returns the standard tool-route envelope:
{
"data": {
"flagged": false,
"threshold": 2,
"authMode": "managed-identity",
"workflowId": "tap.content-safety.v1",
"text": {
"categories": [
{ "category": "Violence", "severity": 0 },
{ "category": "SelfHarm", "severity": 0 },
{ "category": "Sexual", "severity": 0 },
{ "category": "Hate", "severity": 0 }
],
"blocklistHits": [],
"maxSeverity": 0,
"flagged": false
},
"images": [
{
"label": "post-12345",
"categories": [
{ "category": "Violence", "severity": 0 },
{ "category": "SelfHarm", "severity": 0 },
{ "category": "Sexual", "severity": 0 },
{ "category": "Hate", "severity": 0 }
],
"maxSeverity": 0,
"flagged": false
}
],
"decision": "allow",
"providerResults": {
"azureContentSafety": {
"status": "completed",
"categories": [],
"blocklistHits": [],
"images": []
},
"localSemantic": {
"status": "completed",
"decision": "allow",
"categories": {}
},
"mergePolicy": {
"strategy": "flag-if-any-required-provider-flags",
"threshold": 2,
"winningProviders": []
}
}
}
}
Response Fields
| Field | Type | Description |
|---|---|---|
data.flagged | boolean | true when the merged TAP policy flags text or any image. |
data.threshold | integer | Threshold used for this request. |
data.authMode | string or null | Azure authentication mode when Azure ran. |
data.text.flagged | boolean | Text-level merged moderation result. |
data.text.maxSeverity | integer | Highest merged severity for the text. |
data.text.categories | array | Azure-compatible category severity results for the text. May include TAP-added categories such as Harassment and Spam. |
data.text.blocklistHits | array | Azure blocklist matches returned for the text. |
data.images[].label | string | Correlation label from the request image entry. |
data.images[].flagged | boolean | Image-level Azure moderation result. |
data.images[].maxSeverity | integer | Highest severity returned for the image. |
data.images[].categories | array | Category severity results for the image. |
data.workflowId | string | Stable result identifier. Current value is tap.content-safety.v1. |
data.decision | string | TAP policy decision: allow, flag, block, or review. |
data.providerResults.azureContentSafety | object | Azure provider status, latency, categories, blocklist hits, image findings, and raw provider evidence when available. |
data.providerResults.localSemantic | object | TAP local semantic provider status, decision, model version, policy version, and category scores. |
data.providerResults.mergePolicy | object | Merge strategy and providers that contributed to the final flagged decision. |
data.notes | string array | Non-fatal processing notes, when present. |
Validation and execution failures use the standard error envelope:
{
"error": "Request failed"
}
Notes
- Use signed media URLs that remain accessible for the duration of the moderation request.
thresholdis a caller override for this request only.- Blocklist checks apply to text moderation and require configured blocklist names in the target environment.
- The previous TAP blocklist agent routes are retired; use
/tap/tools/content-safetyfor active TAP content safety checks.