Skip to main content

Content moderation

Every generation job — Voice, LLM endpoints and Hosted endpoints — is content-moderated before it is generated and again before it is returned. Moderation is always on. There is nothing to enable and nothing to configure on your side.

Two phases​

queued → moderating → generating → moderating → completed | rejected | failed
  1. Inputs. As soon as the job is accepted, every text input you sent is checked, and every image, video or audio input is checked as its own item. Nothing is generated until all of them pass. A rejection here finishes the job as rejected and refunds a fixed-price charge, since nothing was generated.
  2. Outputs. Once generation finishes, every text output and every generated artifact is checked. A rejection here finishes the job as rejected and deletes the generated content. The charge for the generation stands.

While either phase runs the job reports status: "moderating" when you poll. By default webhooks are delivered only for terminal states; turn on status events to also receive each phase as it starts.

Which phase: moderation_phase​

A moderating or rejected job also carries moderation_phase, on the poll response and on the rejection webhook:

statusmoderation_phaseMeaning
moderatinginputYour inputs are being checked. Nothing has been generated yet.
moderatingoutputThe generated content is being checked.
rejectedinputYour inputs were rejected. Nothing was generated; a fixed-price charge was refunded.
rejectedoutputThe generated content was rejected and deleted. The charge stands.

The field is absent for every other status. Branch on status first, then on moderation_phase.

An endpoint that runs a GPU workflow behind an LLM template is one job and is moderated once, at the endpoint you called.

What a rejection looks like​

{
"job_id": "6a0c2d1e-4f3b-4b1a-9f2c-8d7e6a5b4c30",
"status": "rejected",
"moderation_phase": "output",
"error": "The content was rejected by moderation.",
"error_code": "CONTENT_REJECTED",
"created_at": "2026-09-16T10:03:58.000Z",
"completed_at": "2026-09-16T10:04:12.000Z",
"moderation": {
"result": "reject",
"reason": "The image shows graphic violence."
}
}

A rejected job has no outputs. The moderation object is part of an endpoint's response unless the endpoint's operator turned it off. It appears once the job has ended, on the poll response and on the webhook:

FieldValue
resultpass, reject, or unavailable when moderation could not reach a decision.
reasonOnly on reject: why the content was rejected, as free text. Several reasons are joined by ; .

reason is free text written by the moderation service. Show it to your end users if it helps them, but do not branch on its wording — branch on result and error_code.

GET /jobs/{job_id} also carries a moderation object with one decision per phase (input, output) and the same reason, so you can tell an input rejection — nothing generated, fixed-price charge refunded — from an output rejection, where the charge stands.

When moderation cannot decide​

If the moderation service cannot reach a decision — it is unavailable, or it never answers — the job finishes as failed with error_code: "MODERATION_UNAVAILABLE". Generated content is deleted rather than returned unchecked. Retry the request after a short backoff.

What is checked​

Every text and media field of an endpoint is checked by default. An operator can exclude a field from moderation in the endpoint's schema; an excluded field is simply not sent. Numeric and boolean fields carry nothing to moderate and are never sent.