List jobs

Retrieve a paginated, filterable list of moderation jobs for your account.

GEThttps://api.omnifence.ai/api/v1/jobs

Requires the job:read scope. Requests without this scope receive a 403 FORBIDDEN response. See authentication.

Jobs are returned newest-first (created_at descending) and scoped to your account. Use limit (max 100) and offset to page through results; total in the response is the unpaginated count.

Filters#

Parameter Description
type Job modality: text, image, video, or audio. generate, pre, post and chat are non-moderation or retired values, kept so historical jobs stay filterable.
decision Moderation outcome: pass or reject.
status Job status. See below.
search Prefix-match on job_id.
api_key_id The API key a job was submitted with. Pass none for the jobs with no key. See below.
from Inclusive lower bound on created_at (ISO 8601).
to Exclusive upper bound on created_at (ISO 8601).

API key attribution#

Each job submitted with an API key records that key. Each row in the response carries api_key_id and api_key_name, so you can split traffic by key. For example, you can use one key per environment, customer, or service without keeping your own mapping.

Both fields are null on a job that no key submitted: one sent from the dashboard, and any job created before key attribution shipped. Filter to exactly those with api_key_id=none.

api_key_name is resolved when you read the job, not stored on it. A key you renamed shows its current name on every past job, and a key you deleted resolves to null. api_key_id is stored on the job and never changes, so it stays correct in both cases. Use the id as the stable identifier.

Status filter#

status accepts a comma-separated list of one or more job statuses:

Status Meaning
queued Accepted and being moderated.
processing Reserved. No moderation job reports it today.
completed Finished. See is_prohibited for the outcome.
failed Terminated with an error before a decision.

A moderation job stays queued for its whole run and then flips straight to completed or failed; it never reports processing. queued and processing are both in-flight states and completed and failed are terminal, so request both in-flight values to stay correct if that changes:

Code
GET /api/v1/jobs?status=queued,processing

An unknown status value returns 400 INVALID_REQUEST.

Polling for completion#

Webhooks are the primary, low-latency way to learn that a job finished. Register one when you submit, or via register webhook. Webhook delivery is best-effort, so use this endpoint as a cheap reconciliation safety net rather than your primary signal:

  • Poll GET /api/v1/jobs?status=queued,processing on an interval. One request covers every outstanding job, regardless of how many you have in flight. That is far cheaper than polling each job individually with get job status.
  • A job that drops out of the in-flight list has reached a terminal state. Fetch the terminal set (status=completed,failed, optionally narrowed with from) to pick up any outcome whose webhook was missed.
  • Keep the interval modest. Every request counts toward your rate limit. Webhooks carry the fast path; reconciliation only needs to catch stragglers.

Example#

Shell
curl -G "https://api.omnifence.ai/api/v1/jobs" \
  -H "Authorization: Bearer $API_KEY" \
  --data-urlencode "status=queued,processing" \
  --data-urlencode "limit=100"

Request#

Headers#

Name Type Required Description
Authorization string Yes Your API key as a Bearer token: Bearer YOUR_API_KEY.

Query parameters#

Name Type Required Description
limit integer No Default 50. Min 1, max 100.
offset integer No Default 0. Min 0.
type string No Filter by job modality. text, image, video, audio are the active moderation modalities. generate and pre/post/chat are non-moderation or retired types, kept so historical jobs stay filterable. One of pre, post, chat, text, image, video, audio, generate.
decision string No Filter by moderation decision. One of pass, reject.
status string No Filter by job status. Comma-separated list of: queued, processing, completed, failed. Example: status=queued,processing returns all in-flight jobs, which is useful for low-cost reconciliation polling alongside webhooks.
search string No Prefix-match filter on job_id. Length max 64.
api_key_id string No Filter to jobs submitted with a single API key. Pass the key id, or the literal none to return only the jobs with no key attribution (dashboard submissions and jobs created before key attribution shipped). Length max 128.
from string (date-time) No Inclusive lower bound on job created_at (ISO 8601).
to string (date-time) No Exclusive upper bound on job created_at (ISO 8601).

Responses#

200 OK#

Field Type Always present Description
jobs array of object Yes
jobs[].is_prohibited null or boolean Yes
jobs[].job_id string (uuid) Yes
jobs[].type string Yes One of pre, post, chat, text, image, video, audio, generate.
jobs[].status string Yes One of queued, processing, completed, failed.
jobs[].api_key_id null or string Yes Id of the API key the job was submitted with. Null for jobs submitted from a dashboard session, and for jobs created before key attribution shipped.
jobs[].api_key_name null or string Yes Display name of that API key, resolved at read time. Null when the key was never named or has since been deleted. api_key_id still identifies it.
jobs[].created_at string (date-time) Yes
jobs[].completed_at null or string (date-time) Yes
total integer Yes
limit integer Yes
offset integer Yes
Example responseJSON
{
  "jobs": [
    {
      "is_prohibited": false,
      "job_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "type": "pre",
      "status": "queued",
      "api_key_id": "string",
      "api_key_name": "string",
      "created_at": "2026-05-19T12:00:00.000Z",
      "completed_at": "2026-05-19T12:00:00.000Z"
    }
  ],
  "total": 0,
  "limit": 0,
  "offset": 0
}