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
- 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
rejectedand refunds a fixed-price charge, since nothing was generated. - Outputs. Once generation finishes, every text output and every generated artifact is checked.
A rejection here finishes the job as
rejectedand 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:
status | moderation_phase | Meaning |
|---|---|---|
moderating | input | Your inputs are being checked. Nothing has been generated yet. |
moderating | output | The generated content is being checked. |
rejected | input | Your inputs were rejected. Nothing was generated; a fixed-price charge was refunded. |
rejected | output | The 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:
| Field | Value |
|---|---|
result | pass, reject, or unavailable when moderation could not reach a decision. |
reason | Only 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.