Skip to main content
An image or video moderation job runs an always-on prohibited-content check, an optional NSFW label, and any custom categories you have configured. A completed job reports a single is_prohibited decision, a reason when the content is rejected, and the informational nsfw label when that check is enabled. The built-in checks below are specific to image and video. Custom categories run on every endpoint: image, video, text and audio.
A job result does not contain a categories object. Earlier versions of the API returned a per-category boolean map. Results now carry is_prohibited, reason, and nsfw only. The reason names the policy or custom category that tripped.

Built-in checks

AI Adult General

The core prohibited-content check. It decides whether the image or video breaks the content policy, which covers prohibited adult content and content that depicts, or appears to depict, a minor in a sexual or exploitative context. AI Adult General always runs and cannot be disabled. Every enabled custom category is evaluated as part of the same check.
Content that appears to depict a minor is rejected. Account termination is not automatic. It follows a manual review of repeated violations. See account termination.

NSFW

An informational label for nudity, sexual content, and other adult material. It is returned as a top-level nsfw boolean and never rejects a job on its own. An image can be nsfw: true and still pass. NSFW is enabled by default and you can turn it off. When it is off, the check does not run and the nsfw field is omitted from the result. See per-account category toggles.

Custom categories

A custom category is your own prohibited-content rule, written in plain language. Every enabled custom category runs on every endpoint, and a match rejects the job the same way a built-in policy breach does. You write the rule once and it applies to all four modalities, with one exception noted below. Custom categories are evaluated as part of the check each endpoint already runs, so enabling more of them does not add a separate check, however many you enable. Each category still adds its own system_prompt to that evaluation, so a long list of long categories makes the job a little slower, and a little more expensive on accounts priced by a multiplier over usage cost.
Turning the text toggle off skips the text check, and every custom category with it: an enabled category does not override the toggle, and those text jobs pass unchecked. Image, video and audio are unaffected. See per-account category toggles.
Write the system_prompt so it describes the content, not the medium. A rule phrased for images still applies to text and audio, because it is evaluated by intent. But a rule that names the content directly (“references to coffee”) behaves more predictably across all four endpoints than one that names the medium (“if the image shows coffee”).
Audio is judged on its transcript, so a custom category only fires there when the speech in the clip matches it. Music, sound effects and other non-speech audio are not screened. Manage custom categories on the Moderation page of the dashboard, or through the API: You can hold up to 10 custom categories per account. Each category has a name, a description, and a system_prompt, which is the instruction the check evaluates against. The slug is derived from the name, is immutable, and identifies the category in a rejection reason.
When a custom category rejects a job, the reason names it by slug in parentheses. This applies to a text or audio job as well as to an image one:

How the checks affect the decision

is_prohibited is true when the AI Adult General check finds prohibited content: a breach of the built-in policy, a custom category match, or content that appears to depict a minor. The nsfw label does not affect the decision. See decision logic for details.