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

# Webhooks

> Receive job results asynchronously via HTTP callbacks

Webhooks let you receive moderation results as soon as a job completes, without polling.

## Registration methods

You can set a webhook URL in two ways:

### Global webhook

Register a URL that receives all job completions for your account:

```bash theme={null}
curl -X POST https://api.omnifence.ai/api/v1/webhook/register \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://your-app.com/webhooks/omnifence"}'
```

Calling this endpoint again replaces the previously registered URL.

### Per-request webhook

Include a `webhook_url` field when submitting a moderation request. This overrides the global webhook for that specific job.

```bash theme={null}
curl -X POST https://api.omnifence.ai/api/v1/moderate/image \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "image=https://example.com/photo.jpg" \
  -F "webhook_url=https://your-app.com/webhooks/moderation"
```

## Webhook payload

When a job completes, the API sends a POST request to your URL with the following JSON body. The
shape depends on the modality.

### Prompt moderation result

```json theme={null}
{
  "is_prohibited": true,
  "reason": "The prompt requests sexual content involving a minor.",
  "job_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "status": "completed",
  "completed_at": "2026-05-19T12:00:01.500Z"
}
```

`reason` is present only when `is_prohibited` is `true`; a prompt that passes omits it.

### Image moderation result

```json theme={null}
{
  "is_prohibited": false,
  "categories": {
    "ai_adult_general": false,
    "underage": false,
    "nsfw": false
  },
  "job_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "status": "completed",
  "completed_at": "2026-05-19T12:00:05.000Z"
}
```

`categories.custom` is only included when at least one custom category ran for the job.

### Video moderation result

```json theme={null}
{
  "is_prohibited": true,
  "categories": {
    "ai_adult_general": false,
    "underage": false,
    "nsfw": true
  },
  "job_id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
  "status": "completed",
  "completed_at": "2026-05-19T12:05:30.000Z"
}
```

## Delivery behaviour

* Your server should return a `2xx` status code to acknowledge receipt.
* Delivery failures are logged but **not retried**. If your server is down, the result is still available via the [job status endpoint](/api-reference/endpoint/get-job).
* The request has a 10-second timeout.

## Best practices

* Use HTTPS for your webhook URL.
* Validate the payload before processing. The `job_id` and `type` fields let you match the result to your original request.
* Respond with `200` quickly, then process the result asynchronously.
