Developer Dashboard

Moderation API Reference

The Moderation API helps you identify potentially harmful content in user or model output. Use it to classify standalone text and, with omni-moderation-latest, image inputs. Treat the result as a policy signal for filtering, review queues, account intervention, or human escalation—not as a complete safety system by itself.

Endpoint

POST https://api.avalai.ir/v1/moderations

Choose a Workflow

WorkflowUse whenEndpoint or parameter
Classify standalone inputsYou need a policy signal for text or image content without generating a responsePOST /v1/moderations
Moderate generated contentYou need moderation scores for both the request and the generated answermoderation: {"model": "omni-moderation-latest"} on supported /v1/responses or /v1/chat/completions requests
Review and escalationYou need a durable audit trail or a human review queueStore flagged, categories, category_scores, category_applied_input_types, request_id, and your hashed safety_identifier

Request Body

ParameterTypeRequiredDescription
inputstring, array, or content item arrayYesText to classify. With omni-moderation-latest, inputs can include text and image URL items.
modelstringNoModeration model to use. Current AvalAI moderation models include omni-moderation-latest, omni-moderation-2024-09-26, text-moderation-latest, text-moderation-stable, and cf.llama-guard-3-8b.

Tip

omni-moderation-latest supports text and images, but not audio. OpenAI's reference limit for moderation images is 20 MB; confirm AvalAI route and provider limits before relying on that maximum in production.

Examples

Basic Moderation Request

bash
curl https://api.avalai.ir/v1/moderations \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $AVALAI_API_KEY" \
  -d '{
    "model": "omni-moderation-latest",
    "input": "I want to kill them."
}'

Python Example

python
import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["AVALAI_API_KEY"],
    base_url="https://api.avalai.ir/v1",
)

response = client.moderations.create(
    model="omni-moderation-latest",
    input="I want to kill them.",
)

# Check if the text is flagged
if response.results[0].flagged:
    print("This content was flagged!")

# Check specific categories
categories = response.results[0].categories
for category, flagged in categories.items():
    if flagged:
        print(f"Content flagged for {category}")

JavaScript Example

javascript
import OpenAI from "openai";

const client = new OpenAI({
  apiKey: process.env.AVALAI_API_KEY,
  baseURL: "https://api.avalai.ir/v1",
});

const response = await client.moderations.create({
  model: "omni-moderation-latest",
  input: "I want to kill them.",
});

// Check if the text is flagged
if (response.results[0].flagged) {
  console.log("This content was flagged!");
}

// Check specific categories
const categories = response.results[0].categories;
for (const [category, flagged] of Object.entries(categories)) {
  if (flagged) {
    console.log(`Content flagged for ${category}`);
  }
}

Image and Text Moderation

Use omni-moderation-latest when you need one request to classify text plus an image URL:

bash
curl https://api.avalai.ir/v1/moderations \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $AVALAI_API_KEY" \
  -d '{
    "model": "omni-moderation-latest",
    "input": [
      { "type": "text", "text": "Describe whether this content is safe." },
      {
        "type": "image_url",
        "image_url": {
          "url": "https://example.com/image.png"
        }
      }
    ]
  }'

Generated Output Moderation

OpenAI-compatible generation endpoints may support a top-level moderation object that returns moderation scores alongside the model input and generated output. When AvalAI support is enabled for your selected route, pass moderation: {"model": "omni-moderation-latest"} to /v1/responses or /v1/chat/completions; otherwise, call /v1/moderations before and/or after generation.

python
import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["AVALAI_API_KEY"],
    base_url="https://api.avalai.ir/v1",
)

response = client.responses.create(
    model="gpt-5.5",
    input="A user asks for harmful instructions. Refuse briefly and redirect safely.",
    moderation={"model": "omni-moderation-latest"},
)

input_moderation = response.moderation.input
output_moderation = response.moderation.output

print(input_moderation.flagged)
print(output_moderation.flagged)
javascript
import OpenAI from "openai";

const client = new OpenAI({
  apiKey: process.env.AVALAI_API_KEY,
  baseURL: "https://api.avalai.ir/v1",
});

const response = await client.responses.create({
  model: "gpt-5.5",
  input:
    "A user asks for harmful instructions. Refuse briefly and redirect safely.",
  moderation: { model: "omni-moderation-latest" },
});

console.log(response.moderation.input.flagged);
console.log(response.moderation.output.flagged);
bash
curl https://api.avalai.ir/v1/responses \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $AVALAI_API_KEY" \
  -d '{
    "model": "gpt-5.5",
    "input": "A user asks for harmful instructions. Refuse briefly and redirect safely.",
    "moderation": { "model": "omni-moderation-latest" }
  }'

Tip

Inline moderation results should be reviewed before showing the generated text to a user. For streamed responses, moderation scores arrive after the full output is available, not with partial output deltas.

Multiple Inputs in One Request

You can moderate multiple standalone texts in one /v1/moderations request. This is different from the asynchronous /v1/batch API.

python
response = client.moderations.create(
    model="omni-moderation-latest",
    input=[
        "I want to kill them.",
        "The weather is nice today.",
        "I'm going to harm myself.",
    ],
)

# Process each result
for i, result in enumerate(response.results):
    print(f"Text {i+1}: {'Flagged' if result.flagged else 'Not flagged'}")

Response Format

json
{
  "id": "modr-5MWoLO",
  "model": "omni-moderation-latest",
  "results": [
    {
      "flagged": true,
      "categories": {
        "sexual": false,
        "hate": false,
        "harassment": false,
        "self-harm": false,
        "illicit": false,
        "illicit/violent": false,
        "sexual/minors": false,
        "hate/threatening": false,
        "violence/graphic": false,
        "self-harm/intent": false,
        "self-harm/instructions": false,
        "harassment/threatening": false,
        "violence": true
      },
      "category_scores": {
        "sexual": 3.6988e-06,
        "hate": 0.0034766977,
        "harassment": 0.0124246953,
        "self-harm": 2.0235e-06,
        "illicit": 0.0005227032,
        "illicit/violent": 3.682979e-07,
        "sexual/minors": 3.01e-08,
        "hate/threatening": 0.0017639078,
        "violence/graphic": 2.49108e-05,
        "self-harm/intent": 5.447e-07,
        "self-harm/instructions": 8.4e-09,
        "harassment/threatening": 0.0058918546,
        "violence": 0.9223177433
      },
      "category_applied_input_types": {
        "sexual": [
          "text"
        ],
        "hate": [
          "text"
        ],
        "harassment": [
          "text"
        ],
        "self-harm": [
          "text"
        ],
        "illicit": [
          "text"
        ],
        "illicit/violent": [
          "text"
        ],
        "sexual/minors": [
          "text"
        ],
        "hate/threatening": [
          "text"
        ],
        "violence/graphic": [
          "text"
        ],
        "self-harm/intent": [
          "text"
        ],
        "self-harm/instructions": [
          "text"
        ],
        "harassment/threatening": [
          "text"
        ],
        "violence": [
          "text"
        ]
      }
    }
  ]
}

Response Parameters

ParameterTypeDescription
idstringThe unique identifier for the moderation request.
modelstringThe model used for content moderation.
resultsarrayAn array of moderation results, one for each input.

Moderation Result Object

ParameterTypeDescription
flaggedbooleanWhether the model classifies the content as potentially harmful. Use this as a first-pass signal.
categoriesobjectPer-category boolean flags. Use these for routing, logging, escalation, and review decisions.
category_scoresobjectPer-category confidence scores from 0 to 1. Custom thresholds may need recalibration as models improve.
category_applied_input_typesobjectInput types that each category score applies to, such as text or image.

Categories

CategoryDescriptionInputs
sexualContent meant to arouse sexual excitement or promote sexual services, excluding wellness or education contextsText and images
sexual/minorsSexual content involving a person under 18Text only
hateContent that expresses, incites, or promotes hate based on protected identityText only
hate/threateningHateful content that also includes violence or serious harm toward the targeted groupText only
harassmentContent that expresses or promotes harassing language toward a targetText only
harassment/threateningHarassment that includes violence or serious harmText only
illicitInstructions, advice, or facilitation for committing illicit actsText only
illicit/violentIllicit content that also involves violence or weaponsText only
self-harmContent that promotes, encourages, or depicts self-harmText and images
self-harm/intentContent where the speaker expresses intent to self-harmText and images
self-harm/instructionsInstructions or encouragement for self-harmText and images
violenceContent depicting death, violence, or physical injuryText and images
violence/graphicGraphic depiction of death, violence, or physical injuryText and images

Available Models

ModelDescriptionPricing
omni-moderation-latestLatest OpenAI moderation model for text and imagesFree
omni-moderation-2024-09-26Pinned OpenAI omni moderation snapshotFree
text-moderation-latestLatest text-only OpenAI moderation aliasFree
text-moderation-stableStable text-only OpenAI moderation aliasFree
cf.llama-guard-3-8bCloudflare-hosted Llama Guard moderation modelSee pricing

Implementation Best Practices

Content Filtering

Implement a tiered approach to content filtering:

  1. Pre-submission filtering: Apply client-side filters before sending content to the API
  2. API moderation: Use the Moderation API for more accurate detection
  3. Human review: For edge cases, implement human review processes

Category Thresholds

Customize category score thresholds based on your application's requirements:

python
def is_content_allowed(result, custom_thresholds=None):
    thresholds = {
        "sexual": 0.5,
        "hate": 0.5,
        "harassment": 0.5,
        "self-harm": 0.5,
        "illicit": 0.5,
        "illicit/violent": 0.5,
        "sexual/minors": 0.1,  # Stricter threshold
        "hate/threatening": 0.5,
        "violence/graphic": 0.5,
        "self-harm/intent": 0.5,
        "self-harm/instructions": 0.5,
        "harassment/threatening": 0.5,
        "violence": 0.5,
    }

    if custom_thresholds:
        thresholds.update(custom_thresholds)

    scores = result.category_scores
    if hasattr(scores, "model_dump"):
        scores = scores.model_dump()

    for category, threshold in thresholds.items():
        if scores.get(category, 0) >= threshold:
            return False

    return True

Moderation Boundaries

  • For tool-calling requests, moderation can cover tool-call arguments and tool outputs when they appear in conversation content.
  • Moderation does not inspect tool names, tool descriptions, tool schemas, or response-format schemas.
  • For streamed generation, treat partial deltas as unmoderated until the final moderation result arrives.
  • Inline moderation can return an error object for an input or output moderation step; check the result type before reading category scores in production.

Handling False Positives

To reduce false positives, consider:

  1. Using category scores rather than just the flagged field
  2. Implementing a secondary review for borderline cases
  3. Maintaining an allowlist for known safe content that might be flagged

Multiple-Input Processing

For efficiency, batch multiple content items in a single request:

python
def moderate_batch(texts, batch_size=25):
    results = []

    # Process in batches to avoid hitting request limits
    for i in range(0, len(texts), batch_size):
        batch = texts[i : i + batch_size]
        response = client.moderations.create(
            model="omni-moderation-latest",
            input=batch,
        )
        results.extend(response.results)

    return results

For large offline queues, use the asynchronous Batch API only when /v1/moderations is enabled for your account and workload.

Error Handling

The API may return various error codes:

Status CodeDescription
400Bad Request - Your request is invalid.
401Unauthorized - Your API key is wrong.
403Forbidden - You don't have permission to access this resource.
404Not Found - The specified resource could not be found.
429Too Many Requests - You have exceeded your rate limit.
500Internal Server Error - We had a problem with our server.

For more information on handling errors, see the Error Handling guide.

Content Policy Considerations

When implementing content moderation, consider:

  1. Transparency: Inform users about your content moderation policies
  2. Appeals process: Provide a way for users to appeal moderation decisions
  3. Cultural context: Be aware that content moderation may vary across cultures and regions
  4. Regular updates: Keep your moderation systems updated as language evolves