Skip to content

Bulk Operations

Bulk operations enable efficient batch processing of multiple jobs in a single API call. OJS supports bulk enqueue, cancel, retry, and delete with configurable atomicity.

ModeBehaviorHTTP Status
atomicAll-or-nothing. If any item fails, the entire batch is rolled back.200 (all succeed) or 422 (all rolled back)
partialBest-effort. Each item is processed independently.207 Multi-Status

The default mode is partial.

Terminal window
POST /ojs/v1/jobs/batch
Content-Type: application/openjobspec+json
{
"mode": "partial",
"jobs": [
{ "type": "email.send", "args": ["alice@example.com", "Welcome!"] },
{ "type": "email.send", "args": ["bob@example.com", "Welcome!"] },
{ "type": "email.send", "args": ["carol@example.com", "Welcome!"] }
]
}
{
"results": [
{ "index": 0, "status": 201, "job_id": "01961234-0001-7abc-..." },
{ "index": 1, "status": 201, "job_id": "01961234-0002-7abc-..." },
{ "index": 2, "status": 409, "error": { "code": "OJS_DUPLICATE", "message": "Unique constraint violated" } }
],
"summary": {
"total": 3,
"succeeded": 2,
"failed": 1
}
}

Cancel multiple jobs by ID or filter:

Terminal window
POST /ojs/v1/jobs/batch/cancel
{
"job_ids": ["01961234-0001-...", "01961234-0002-..."]
}

Or cancel by filter:

Terminal window
POST /ojs/v1/jobs/batch/cancel
{
"filter": {
"job_type": "report.generate",
"queue": "default",
"state": "available"
}
}

Retry multiple dead letter or failed jobs:

Terminal window
POST /ojs/v1/jobs/batch/retry
{
"filter": {
"job_type": "payment.*",
"error_type": "connection_timeout"
}
}
Terminal window
DELETE /ojs/v1/jobs/batch
{
"filter": {
"state": "completed",
"completed_before": "2026-02-01T00:00:00Z"
}
}

Bulk operations support idempotency keys for safe retries:

Terminal window
POST /ojs/v1/jobs/batch
Idempotency-Key: batch-import-2026-02-15

If a request with the same idempotency key is received within 24 hours, the backend returns the original response without re-processing.

Backends MUST accept batches of at least 100 items. Backends SHOULD support up to 1,000 items per batch. Larger batches should be split by the client.

Bulk operations emit aggregate events:

EventData
batch.enqueuedtotal, succeeded, failed
batch.cancelledtotal, succeeded, failed
batch.retriedtotal, succeeded, failed