Authentication issues
401 UNAUTHORIZED
Cause: The API key is missing, malformed, or has been revoked.
Fix:
- Confirm the
Authorizationheader uses the exact format:Bearer YOUR_API_KEY - Check that the key has not been revoked in the dashboard
- Ensure the key belongs to an active account
Moderation submissions are
multipart/form-data, not JSON. Send each field with -F. A JSON body
returns 400 INVALID_REQUEST because the required field is never parsed.403 ACCOUNT_TERMINATED
Cause: Your account has been terminated, typically after a manual review of policy violations. See account termination.
Fix: Contact support at support@omnifence.ai. This state cannot be resolved through the API.
Submission failures
400 INVALID_REQUEST: missing fields
Cause: The required field for the endpoint was missing.
Fix: Include the field. For
/moderate/image, pass a publicly reachable image.
Using the wrong endpoint for your media type
Cause: Each modality has its own endpoint and its own required field, listed in the table above. Submitting an image to the text endpoint (or vice versa) returns400 INVALID_REQUEST.
Fix: Use the endpoint that matches your media type. /moderate/text takes a text field and
screens it against your configured moderation policies. See
text moderation.
400 INVALID_REQUEST: “image file upload is currently disabled”
Cause: The /moderate/image endpoint does not accept a direct file upload. It accepts only the image URL field.
Fix: Host the image at a publicly reachable URL and pass it as the image field.
When direct file upload is available, the
image file is limited to 10 MB. A larger file
returns 400 INVALID_REQUEST.400 INVALID_REQUEST: “video file upload is currently disabled”
Cause: The /moderate/video endpoint does not accept a direct file upload. It accepts only the video URL field.
Fix: Host the video at a publicly reachable URL and pass it as the video field.
Video job fails: video too large or unreachable
Cause: The video field points to a file larger than 100 MB, or the API could not download it.
The submission still returns 202, but the job later ends with status: "failed".
Fix: Host a video under 100 MB at a publicly reachable HTTP or HTTPS URL. The API rejects a URL
that resolves to a private or internal address, or that uses a non-HTTP scheme, at submission with
400 INVALID_REQUEST.
Image job fails: image unreachable
Cause: The API could not fetch the image URL. The submission still returns 202, but
the job later ends with status: "failed".
Fix: Host the image at a publicly reachable HTTP or HTTPS URL. The API rejects a URL that resolves
to a private or internal address, or that uses a non-HTTP scheme, at submission with
400 INVALID_REQUEST.
Webhook issues
Webhook is not receiving events
Possible causes and fixes:- No webhook registered: Call
POST /api/v1/webhook/registerwith your URL, or includewebhook_urlin the moderation request. - Webhook URL is HTTP: The API requires HTTPS. Use an HTTPS endpoint.
- Your server timed out: Webhook delivery has a 10-second timeout. Confirm your server responds within that window. See webhook reliability.
- Server returned non-
2xx: The delivery is retried for 12 attempts over about five hours, and is then abandoned. Check your server logs, and read the result fromGET /api/v1/job/{id}for anything that was already abandoned. See webhook reliability. - URL rejected outright: A URL that is malformed, not HTTPS, or resolves to a private or internal address is dropped without any retry. Re-register a valid HTTPS URL.
Webhook fired but the payload looks wrong
Fix: Verify you are reading the correct fields. The webhook payload format depends on the moderation type. See webhooks for the full schema.Signature verification fails
Every callback carrieswebhook-id, webhook-timestamp and webhook-signature headers. If your verifier rejects them, work through these in order:
- You verified a re-serialised body: The signature covers the exact bytes we sent. Parsing the JSON and re-serialising it reorders keys and changes whitespace, so the check can never pass. Pass the raw body —
express.raw({ type: 'application/json' })in Node,request.datain Flask, notrequest.get_json(). - Wrong secret: The secret is per account and starts with
whsec_. Paste the whole value, including that prefix, into your Standard Webhooks library. Reveal the current one under Account → Webhooks. - You rotated and have not redeployed: During the grace window
webhook-signaturecarries two space-delimitedv1,<base64>values and a library accepts whichever matches. Split that header on spaces — the comma belongs inside each value and is not a separator. - Your server clock has drifted: Libraries reject a
webhook-timestampmore than five minutes from their own clock. We sign each attempt as we send it, so a retry is always fresh; a failure across the board points at your clock, not at the retry. Run NTP. 403 FORBIDDENwhen reading the secret: The webhook-secret endpoints need thewebhook:managescope, which is off by default on API keys. Read the secret from the dashboard instead.
Job issues
Job stays queued for a long time
Cause: A moderation job reports queued for its whole run and then flips straight to completed or failed. It never reports processing or percentage progress, so a long queued period is normal work, not a stall. Times vary: text and image moderation typically complete in seconds; long videos and audio clips take longer, because transcription time scales with clip length.
Fix: Register a webhook instead of polling tightly. If a job has been queued for more than 10 minutes, resubmit and contact support if the issue persists.
404 JOB_NOT_FOUND
Cause: Either the job ID is incorrect, or the job belongs to a different client account. Jobs are scoped per account.
Fix: Confirm the job_id matches one returned by your account’s submission.
is_prohibited is null
Cause: The job has not yet completed (status is queued or processing), or it failed (status is failed).
Fix: Wait for status: "completed" before reading is_prohibited. For failed jobs, resubmit the request.
Rate limiting
429 RATE_LIMITED
Cause: You have exceeded your account’s request rate. See rate limiting.
Fix: Reduce request frequency or implement exponential backoff. See error recovery for a retry example.
Still stuck?
Contact support at support@omnifence.ai with yourjob_id and the API response body.