Jobs overview

The Jobs API lets you submit large numbers of operations for asynchronous execution. Instead of making thousands of individual API calls, you bundle commands into a batch, and OpusDNS processes them reliably in the background.

Core concepts

Batches and jobs

A batch is a container that holds one or more commands. When you submit a batch, OpusDNS creates individual jobs for each command (or each instance in a bulk command). Each job is processed independently and tracked through its own lifecycle.

Batch (up to 50,000 commands)
├── Job 1  →  domain_create "example.com"       → succeeded
├── Job 2  →  domain_create "example.net"       → succeeded
├── Job 3  →  domain_create "example.org"       → failed
└── ...

Single vs. bulk commands

There are two categories of commands:

Single-resource commands create one job per command. Each command targets a specific resource:

{
  "type": "domain_create",
  "payload": {
    "name": "example.com",
    "contacts": { "registrant": "contact_01h45ytscbebyvny4gc8cr8ma2" },
    "renewal_mode": "renew",
    "period": { "unit": "y", "value": 1 }
  }
}

Bulk commands use a template + instances pattern. The template defines shared settings, and each instance specifies a target resource with optional overrides. Each instance becomes its own job:

{
  "type": "domain_create_bulk",
  "payload": {
    "template": {
      "contacts": { "registrant": "contact_01h45ytscbebyvny4gc8cr8ma2" },
      "renewal_mode": "renew",
      "period": { "unit": "y", "value": 1 }
    },
    "instances": [
      { "name": "example.com" },
      { "name": "example.net" },
      { "name": "example.org" }
    ]
  }
}

This is significantly more efficient than submitting 3 individual domain_create commands — shared fields are defined once in the template rather than repeated in every command.

Instance-level overrides completely replace the template's setting for that field — they are not merged. If an instance specifies contacts, it replaces the template's contacts entirely.

Submitting a batch

Create a batch with POST /v1/jobs:

curl "$OPUSDNS_API_BASE/v1/jobs" \
  --request POST \
  --header "X-Api-Key: $OPUSDNS_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "label": "Q1 2026 bulk registration",
    "commands": [
      {
        "type": "domain_create",
        "payload": {
          "name": "example1.com",
          "contacts": {
            "registrant": "contact_01h45ytscbebyvny4gc8cr8ma2"
          },
          "renewal_mode": "renew",
          "period": { "unit": "y", "value": 1 }
        }
      },
      {
        "type": "domain_create",
        "payload": {
          "name": "example2.com",
          "contacts": {
            "registrant": "contact_01h45ytscbebyvny4gc8cr8ma2"
          },
          "renewal_mode": "renew",
          "period": { "unit": "y", "value": 1 }
        }
      }
    ]
  }'

Batch request fields

Field Required Default Description
commands Yes Array of command objects. Up to 50,000 per batch.
label No null Human-readable label to identify the batch.
paused No false If true, jobs are created in a paused state.
not_before No null UTC timestamp — jobs stay blocked until this time.

Batch response

{
  "batch_id": "batch_01h45ytscbebyvny4gc8cr8ma2",
  "total_commands": 2,
  "jobs_created": 2,
  "jobs_duplicated": 0,
  "jobs_failed": 0,
  "duplicates": [],
  "errors": [],
  "status_url": "/v1/jobs/batch_01h45ytscbebyvny4gc8cr8ma2"
}
Field Description
batch_id Unique identifier for the batch.
total_commands Total number of commands submitted.
jobs_created Number of jobs successfully created.
jobs_duplicated Commands skipped due to duplicate idempotency keys.
jobs_failed Commands that failed validation at submission time.
duplicates Array of duplicate command details (index, existing job/batch IDs).
errors Array of command errors (index, error message, error code).
status_url URL to poll for batch progress.

Job lifecycle

Each job transitions through a defined set of statuses:

blocked → queued → running → succeeded
                           → failed
                           → dead_letter

           paused

          canceled
Status Description
blocked Waiting for eligibility — either scheduled via not_before or awaiting capacity.
queued Eligible and waiting for a worker to pick it up.
paused Paused by user action. Must be explicitly resumed.
running Currently being executed.
succeeded Completed successfully.
failed Execution failed. Check error_class and error_message on the job.
canceled Canceled before execution started.
dead_letter Permanently failed after exhausting all retry attempts.

The batch has its own status:

Batch status Meaning
pending At least one job is still in a non-terminal state.
complete All jobs have reached a terminal state (succeeded, failed, canceled, or dead_letter).

Scheduling

Use not_before to schedule a batch for future execution:

{
  "label": "Scheduled renewal update",
  "not_before": "2026-06-01T00:00:00Z",
  "commands": [...]
}

Jobs remain blocked until the scheduled time, then move to queued for processing. This is useful for maintenance windows, coordinated rollouts, or time-sensitive operations.

Idempotency

Include an idempotency_key on any command to prevent duplicate processing:

{
  "type": "domain_create",
  "idempotency_key": "reg-example-com-2026-q1",
  "payload": {
    "name": "example.com",
    ...
  }
}

Always use idempotency keys for domain registrations and transfers — accidental duplicates have financial impact.

If a job with the same idempotency key has already been processed, the command is skipped. The batch response reports these in the duplicates array:

{
  "duplicates": [
    {
      "index": 0,
      "existing_job_id": "job_01h45ytscbebyvny4gc8cr8ma2",
      "existing_batch_id": "batch_01h35xrscbebyvny4gc8cr8ma2",
      "resource_key": "example.com"
    }
  ]
}

This is especially important for domain registrations and transfers where accidental duplicates would have financial impact.

Limits

Constraint Limit
Commands per batch 50,000
Instances per bulk command 1,000
Operations per DNS bulk patch instance 100

Available commands

Single-resource commands

Command Description
domain_create Register a domain.
domain_update Update domain settings (contacts, nameservers, statuses, renewal mode).
domain_transfer Initiate an inbound domain transfer.
dns_zone_create Create a DNS zone with optional records.
dns_zone_update Update an existing DNS zone.
contact_create Create a contact.

Bulk commands

Command Description
domain_create_bulk Register multiple domains.
domain_update_bulk Update multiple domains.
domain_transfer_bulk Transfer multiple domains.
dns_zone_create_bulk Create multiple DNS zones.
dns_zone_update_bulk Replace RRsets and zone attributes across zones.
dns_zone_patch_rrsets_bulk Upsert or remove entire RRsets across zones.
dns_zone_patch_records_bulk Upsert or remove individual records across zones.
contact_create_bulk Create multiple contacts.
parking_create_bulk Create parking pages for multiple domains.
parking_enable_bulk Enable parking on multiple domains.
parking_disable_bulk Disable parking on multiple domains.
parking_delete_bulk Delete parking pages for multiple domains.

See Domain commands and DNS & infrastructure commands for full payload details and examples.