Moderations API (OpenAI Compatible)¶
Classify content for harm with AWS Bedrock Guardrails or Amazon Comprehend toxicity detection through an OpenAI-compatible Moderations interface.
Why Choose Moderations?¶
-
Configurable Content Safety
Bring your own Bedrock guardrail: categories, thresholds, denied topics, word filters, and sensitive-information policies are fully configurable in AWS. -
Works Out of the Box
Amazon Comprehend toxicity detection requires no setup at all, so/v1/moderationsworks immediately on any deployment. -
Drop-in OpenAI Compatibility
OpenAI moderation model names are accepted as aliases. Existing integrations work by changing the base URL. -
Private AWS Backend
Classifications run entirely in your own AWS account — no traffic to third-party endpoints.
Quick Start: Available Endpoint¶
| Endpoint | Method | What It Does | Powered By | MCP Tool |
|---|---|---|---|---|
/v1/moderations |
POST | Classify inputs with a guardrail or toxicity detection | AWS Bedrock Guardrails / Amazon Comprehend | openai_moderation |
Example request:
curl -X POST "$BASE/v1/moderations" \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"input": "Some text to classify"
}'
Example response:
{
"id": "modr-0f1b3c6e8d9a4b5c",
"model": "abcd1234efgh:1",
"results": [
{
"flagged": true,
"categories": {"hate": true, "harassment": false, "...": false},
"category_scores": {"hate": 0.75, "harassment": 0.25, "...": 0.0},
"category_applied_input_types": {"hate": ["text"], "harassment": ["text"], "...": ["text"]}
}
]
}
Feature Compatibility¶
| Feature | Status | Notes |
|---|---|---|
| Input | ||
input string / array of strings |
Each element yields one independent result | |
input text parts |
{"type": "text", "text": ...} |
|
input image parts |
Guardrail models only; PNG and JPEG | |
| Empty string input | Returns an unflagged result without calling AWS (OpenAI parity); whitespace-only strings are not covered by this shortcut and are classified normally (billed Comprehend call) | |
model |
Guardrail, Comprehend, or an OpenAI moderation model alias (see below) | |
| Output | ||
flagged |
Also raised by guardrail policies without a mapped category, and on Comprehend by the overall toxicity score or unmapped labels such as profanity | |
categories / category_scores |
Mapped categories only; OpenAI categories without a counterpart stay false / 0.0 |
|
category_applied_input_types |
Reflects each classified element's modality | |
| Usage tracking | ||
| Guardrail text units / images | Billing units (one text unit per 1,000 characters per input; one unit per image) | |
| Comprehend units | Billing unit (100 characters, minimum 3 per call) | |
| Other | ||
| Model discovery | Moderation models and their aliases appear in the model listings | |
| Long text inputs | Comprehend inputs of any length are split into API-sized segments transparently |
Legend:
- Supported — Fully compatible with OpenAI API
- Available on Select Models — Check your model's capabilities
- Partial — Supported with limitations
- Unsupported — Not available in this implementation
- Extra Feature — Enhanced capability beyond OpenAI API
Model Support¶
Both moderation models appear in the /v1/models and /search_models listings (mcp_tool=openai_moderation) with their OpenAI aliases.
AWS Bedrock Guardrails¶
| Model | OpenAI aliases | Notes |
|---|---|---|
amazon.bedrock-runtime-guardrail |
omni-moderation-latest, omni-moderation-2024-09-26 |
The server's default guardrail. Text and image inputs. Listed only when a guardrail is configured |
<guardrail-id>, <guardrail-id>:<version>, or guardrail ARN |
— | Any explicit guardrail (requires guardrail override to be allowed) |
Amazon Comprehend¶
| Model | OpenAI aliases | Notes |
|---|---|---|
amazon.comprehend-toxicity |
text-moderation-latest, text-moderation-stable |
Toxicity detection. English text only, no images |
Comparison¶
| Capability | AWS Bedrock Guardrails | Amazon Comprehend |
|---|---|---|
| Setup | Create and configure a guardrail in AWS Bedrock | None — works out of the box |
| Text inputs | Any language supported by the guardrail | English only |
| Image inputs | PNG and JPEG | Not supported |
| Mapped categories | hate, harassment, sexual, violence, illicit |
hate, harassment, sexual, violence, violence/graphic |
| Category scores | Quantized confidence levels (0.0 / 0.25 / 0.5 / 0.75) |
Continuous scores (0.0 – 1.0) |
| Custom policies | Denied topics, word filters, PII, prompt attacks, contextual grounding | Fixed toxicity labels |
| Tunable thresholds | Per-filter strengths configured on the guardrail | Fixed flagging threshold (score ≥ 0.5) |
moderation request parameter |
Applied to generations natively | Moderations API only |
| Input length | ApplyGuardrail text unit limits | Unlimited (split into 1 KB segments transparently) |
Selecting the Model¶
The model parameter selects the moderation model:
model value |
Model used |
|---|---|
| Omitted | The server's default guardrail, or Comprehend toxicity detection when none is configured |
amazon.bedrock-runtime-guardrail |
The server's default guardrail (an error when none is configured) |
omni-moderation-* |
Same as amazon.bedrock-runtime-guardrail, falling back to Comprehend when no guardrail is configured |
amazon.comprehend-toxicity / text-moderation-* |
Comprehend toxicity detection, even when a guardrail is configured |
<guardrail-id> or <guardrail-id>:<version> |
That guardrail (requires guardrail override to be allowed) |
| Guardrail ARN | That guardrail, applied in the region embedded in the ARN |
The server guardrail comes from AWS_BEDROCK_GUARDRAIL_IDENTIFIER / AWS_BEDROCK_GUARDRAIL_VERSION, or from the X-Amzn-Bedrock-GuardrailIdentifier / X-Amzn-Bedrock-GuardrailVersion request headers when AWS_BEDROCK_ALLOW_GUARDRAIL_OVERRIDE is enabled. Explicit guardrails in model also require that setting.
Guardrails are regional: a plain guardrail ID is applied in the primary Bedrock region, while an ARN selects its own region. Comprehend calls use AWS_COMPREHEND_REGION (with multi-region failover otherwise).
Moderating generations directly
The guardrail selection and category mapping also power the moderation request parameter of the Chat Completions and Responses APIs: the guardrail is applied to the generation itself, and the classification of the input and output is reported in the response's moderation field — for Chat Completions on non-streaming requests only, and for Responses also on the terminal event when streaming. The moderation parameter requires a guardrail — Comprehend is not available there — and is rejected (400) on Bedrock Mantle-served models.
Category Mapping¶
AWS Bedrock Guardrails — content policy filters map to the OpenAI moderation categories:
| AWS Bedrock filter | OpenAI category |
|---|---|
HATE |
hate |
INSULTS |
harassment |
SEXUAL |
sexual |
VIOLENCE |
violence |
MISCONDUCT |
illicit |
Filter confidence levels become scores: NONE → 0.0, LOW → 0.25, MEDIUM → 0.5, HIGH → 0.75.
Every other guardrail policy — denied topics, word filters, sensitive information (PII), prompt attacks, contextual grounding — still contributes to the top-level flagged field whenever the guardrail intervenes, even though no individual category is set.
Amazon Comprehend — toxicity labels map to the OpenAI moderation categories, with their detection scores (0.0–1.0) reported directly:
| Comprehend label | OpenAI category |
|---|---|
HATE_SPEECH |
hate |
HARASSMENT_OR_ABUSE |
harassment |
INSULT |
harassment |
SEXUAL |
sexual |
VIOLENCE_OR_THREAT |
violence |
GRAPHIC |
violence/graphic |
PROFANITY |
(flagged only) |
An input is flagged when its overall toxicity or any label score reaches 0.5. Long texts are split into 1 KB segments and the highest score per category is kept.
With either model, OpenAI sub-categories without a counterpart (e.g. self-harm, sexual/minors) are always false.
Inputs¶
Each input element is classified independently and yields one entry in results:
inputas a string — one text classification.inputas an array of strings — one classification per string.inputas an array of parts —{"type": "text", "text": ...}and{"type": "image_url", "image_url": {"url": ...}}parts. Images must be PNG or JPEG, and require a guardrail model.
Each result's category_applied_input_types reflects the classified element's modality: ["text"] for every category on text inputs; on image inputs, ["image"] for the categories that support images and [] for the text-only ones.
An input array holds at most 2048 elements. Each element is classified — and billed — independently by a separate AWS call, so large arrays incur a proportional number of AWS calls.
MCP / AI agent usage: image_url.url accepts an HTTPS URL, data URI (data:<mime>;base64,<data>), base64 string, or S3 URI — no binary upload needed.
curl -X POST "$BASE/v1/moderations" \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"input": [
{"type": "text", "text": "Describe this image"},
{"type": "image_url", "image_url": {"url": "https://example.com/photo.png"}}
]
}'
Billing¶
- Guardrails — AWS bills per text unit and per image processed by the ApplyGuardrail API; see AWS Bedrock pricing. No Bedrock model invocation is involved.
- Comprehend — AWS bills toxicity detection per 100-character unit with a 3-unit minimum per call; see Amazon Comprehend pricing. Billed units appear in usage logs and cost tracking as
comprehend_unitsunder theamazon.comprehend-toxicitymodel.