> ## Documentation Index
> Fetch the complete documentation index at: https://docs.naga.ac/llms.txt
> Use this file to discover all available pages before exploring further.

# Moderation

> Classify text and images for harmful content with POST /v1/moderations before you show them or send them to a model.

Send text, images or both to `POST /v1/moderations` and NagaAI returns a verdict per input: whether any category tripped, and a score for each category. Use it to screen user messages before they reach a chat model, or model output before it reaches a user. The endpoint follows the OpenAI Moderations format, and the OpenAI SDK works unchanged. Choose a model whose `operations` include `moderation` in [`GET /v1/models`](https://docs.naga.ac/get-started/models).

## Check a message

```python Python theme={"theme":{"light":"github-light-default","dark":"github-dark-dimmed"}}
import os
from openai import OpenAI

client = OpenAI(base_url="https://api.naga.ac/v1", api_key=os.environ["NAGA_API_KEY"])

result = client.moderations.create(
    model="omni-moderation-latest",
    input="I will hurt you if you post that again.",
)

verdict = result.results[0]
if verdict.flagged:
    hits = [name for name, hit in verdict.categories.model_dump().items() if hit]
    print("Blocked:", ", ".join(hits))
else:
    print("Allowed")
```

```javascript Node.js theme={"theme":{"light":"github-light-default","dark":"github-dark-dimmed"}}
import OpenAI from "openai";

const client = new OpenAI({ baseURL: "https://api.naga.ac/v1", apiKey: process.env.NAGA_API_KEY });

const result = await client.moderations.create({
  model: "omni-moderation-latest",
  input: "I will hurt you if you post that again.",
});

const verdict = result.results[0];
if (verdict.flagged) {
  const hits = Object.entries(verdict.categories).filter(([, hit]) => hit).map(([name]) => name);
  console.log("Blocked:", hits.join(", "));
} else {
  console.log("Allowed");
}
```

```bash cURL theme={"theme":{"light":"github-light-default","dark":"github-dark-dimmed"}}
curl https://api.naga.ac/v1/moderations \
  -H "Authorization: Bearer $NAGA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "omni-moderation-latest", "input": "I will hurt you if you post that again."}'
```

Each entry of `results` has `flagged`, `categories` and `category_scores`. The response below is shortened to two categories:

```json theme={"theme":{"light":"github-light-default","dark":"github-dark-dimmed"}}
{
  "id": "modr-8f3a2c71",
  "model": "omni-moderation-latest",
  "results": [
    {
      "flagged": true,
      "categories": {"violence": true, "harassment": false},
      "category_scores": {"violence": 0.91, "harassment": 0.12},
      "category_applied_input_types": {"violence": ["text"], "harassment": ["text"]}
    }
  ]
}
```

## Check text and images together

`model` is required. `input` is a string, a list of strings, or a list of `text` and `image_url` parts. Parts in one list are judged together as a single input. An image is an `https` URL or a `data:` URI.

```python Python theme={"theme":{"light":"github-light-default","dark":"github-dark-dimmed"}}
import os
from openai import OpenAI

client = OpenAI(base_url="https://api.naga.ac/v1", api_key=os.environ["NAGA_API_KEY"])

result = client.moderations.create(
    model="omni-moderation-latest",
    input=[
        {"type": "text", "text": "Look what I found on the way home"},
        {"type": "image_url", "image_url": {"url": "https://docs.naga.ac/static/img/playground-chat.png"}},
    ],
)

verdict = result.results[0]
print(verdict.flagged, verdict.category_applied_input_types)
```

```javascript Node.js theme={"theme":{"light":"github-light-default","dark":"github-dark-dimmed"}}
import OpenAI from "openai";

const client = new OpenAI({ baseURL: "https://api.naga.ac/v1", apiKey: process.env.NAGA_API_KEY });

const result = await client.moderations.create({
  model: "omni-moderation-latest",
  input: [
    { type: "text", text: "Look what I found on the way home" },
    { type: "image_url", image_url: { url: "https://docs.naga.ac/static/img/playground-chat.png" } },
  ],
});

const verdict = result.results[0];
console.log(verdict.flagged, verdict.category_applied_input_types);
```

`omni-moderation-latest` also returns `category_applied_input_types`, which says whether text, an image or both triggered each category. Other models, such as `mistral-moderation`, have their own category set, so read `categories` from the response instead of hard-coding names.

## Billing

NagaAI charges each `image_url` part as a flat 250 input tokens, and text by its token count. The response carries no `usage` field, so read the charge in your activity log. See [Balance, metrics and logs](https://docs.naga.ac/account/balance-and-activity.md).

## Troubleshooting

### 400 `model_not_found`

The model does not exist or has no `moderation` operation. Check its `operations` in `GET /v1/models`.

### 400 with `Failed to read the file` or `Failed to validate the image`

NagaAI downloads each image URL before it moderates, and the download failed or the file is not an image. Check that the URL is public and loads in a browser, or send the image as a `data:` URI.

### 400 with `too large`

The image is over the size limit the message names. Send a smaller image.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.