Skip to main content

Jobs API

The Jobs API lets you create background jobs, query their status, cancel pending work, and manually retry failures. These endpoints are called by the SDK's IJobClient and can also be used directly via HTTP.

Base URL: https://api.zeridion.com

All endpoints require Bearer token authentication and are subject to rate limits.


POST /v1/jobs

Create a new background job. The job is persisted and will be picked up by a worker for execution.

Request

POST /v1/jobs
Authorization: Bearer <api_key>
Content-Type: application/json

Body

FieldTypeRequiredDescription
job_typestringYesJob type identifier, typically the fully qualified class name. Max 500 characters.
payloadobjectYesJSON payload passed to the job at execution time.
queuestringNoTarget queue name. Max 100 characters. Default: "default".
run_atstring (ISO 8601)NoSchedule the job for future execution. Omit for immediate.
max_attemptsintegerNoMaximum execution attempts (1–100). Default: 3.
timeout_secondsintegerNoPer-attempt timeout (1–86,400). Default: 1800 (30 minutes).
idempotency_keystringNoUnique key for deduplication. Max 200 characters.
tagsobjectNoKey-value string pairs (Dictionary<string, string>) visible in the dashboard. Both keys and values must be strings.
parent_job_idstringNoCreate as a continuation of this parent job. Max 36 characters.

Full example

{
"job_type": "email.send",
"payload": {
"to": "user@example.com",
"subject": "Welcome!",
"body": "Thanks for signing up."
},
"queue": "email",
"max_attempts": 5,
"timeout_seconds": 60,
"idempotency_key": "welcome-email-user-42",
"tags": {
"env": "dev",
"priority": "high"
}
}

Minimal example

{
"job_type": "report.generate",
"payload": { "report_id": 1 }
}

Response

201 Created

Returns a Location header with the job URL: Location: /v1/jobs/\{id\}

{
"id": "job_01HYX3K7M8N9P2Q4R5S6T7U8V9",
"state": "pending",
"job_type": "email.send",
"queue": "email",
"created_at": "2026-03-18T15:30:00Z",
"run_at": null,
"attempt": 0,
"max_attempts": 5
}
FieldTypeDescription
idstringUnique job identifier
statestringInitial state: pending (immediate) or scheduled (has run_at or parent_job_id)
job_typestringEchoed job type
queuestringResolved queue name
created_atstring (ISO 8601)Timestamp of creation
run_atstring (ISO 8601)Scheduled execution time, or null for immediate
attemptintegerCurrent attempt number (starts at 0)
max_attemptsintegerMaximum attempts allowed

Errors

StatusCodeCondition
400invalid_requestValidation failed (see validation rules)
409idempotency_conflictA job with the same idempotency_key already exists
409parent_terminalParent job is cancelled or dead_letter
422parent_not_foundparent_job_id does not reference an existing job

GET /v1/jobs/{job_id}

Retrieve full details for a single job, including payload, timing, error information, and tags.

Request

GET /v1/jobs/{job_id}
Authorization: Bearer <api_key>

Response

200 OK

{
"id": "job_01HYX3K7M8N9P2Q4R5S6T7U8V9",
"state": "succeeded",
"job_type": "email.send",
"queue": "email",
"payload": { "to": "user@example.com", "subject": "Welcome!" },
"created_at": "2026-03-18T15:30:00Z",
"started_at": "2026-03-18T15:30:01Z",
"completed_at": "2026-03-18T15:30:02Z",
"attempt": 1,
"max_attempts": 5,
"progress": 1.0,
"duration_ms": 1042,
"error": null,
"tags": { "env": "dev", "priority": "high" }
}
FieldTypeDescription
idstringUnique job identifier
statestringCurrent job state: pending, scheduled, processing, succeeded, failed, cancelled, dead_letter
job_typestringJob type identifier
queuestringQueue the job belongs to
payloadobjectThe job's JSON payload
created_atstring (ISO 8601)When the job was created
started_atstring (ISO 8601)When execution began, or null
completed_atstring (ISO 8601)When execution finished, or null
attemptintegerCurrent attempt number
max_attemptsintegerMaximum attempts allowed
progressnumberProgress value (0.0–1.0) reported by the job, or null
duration_msintegerExecution duration in milliseconds, or null
errorobjectError details if the job failed (see below), or null
tagsobjectKey-value string pairs (Dictionary<string, string>), or null

Error detail object

When a job fails, the error field contains:

FieldTypeDescription
typestringException type name
messagestringError message
stack_tracestringStack trace from the failed attempt

Errors

StatusCodeCondition
404job_not_foundJob does not exist or belongs to a different project

GET /v1/jobs

List jobs with optional filtering and cursor-based pagination.

Request

GET /v1/jobs?state=failed&queue=email&limit=20
Authorization: Bearer <api_key>

Query Parameters

ParamTypeDefaultDescription
statestringallFilter by state: pending, scheduled, processing, succeeded, failed, cancelled, dead_letter
queuestringallFilter by queue name
job_typestringallFilter by job type
created_afterstring (ISO 8601)Only return jobs created after this timestamp
created_beforestring (ISO 8601)Only return jobs created before this timestamp
limitinteger50Number of results per page (1–100)
cursorstringCursor from a previous response's next_cursor for the next page

Response

200 OK

{
"data": [
{
"id": "job_01HYX3K7M8N9P2Q4R5S6T7U8V9",
"state": "failed",
"job_type": "email.send",
"queue": "email",
"payload": { "to": "user@example.com" },
"created_at": "2026-03-18T15:30:00Z",
"started_at": "2026-03-18T15:30:01Z",
"completed_at": "2026-03-18T15:30:02Z",
"attempt": 3,
"max_attempts": 3,
"progress": null,
"duration_ms": 503,
"error": {
"type": "System.Net.Http.HttpRequestException",
"message": "Connection refused",
"stack_trace": " at System.Net.Http..."
},
"tags": null
}
],
"has_more": true,
"next_cursor": "eyJpZCI6ImpvYl8wMUhZWDNLN004TjlQMlE0UjVTNlQ3VThWOSJ9"
}
FieldTypeDescription
dataarrayArray of job detail objects
has_morebooleantrue if more results exist beyond this page
next_cursorstringPass as the cursor query parameter to fetch the next page. null when has_more is false.

Sort order

Results are sorted by created_at descending (newest first), with ties broken by id descending.

Pagination

The API uses cursor-based pagination to provide consistent results under concurrent writes. To paginate through all results:

  1. Make the initial request without a cursor
  2. If has_more is true, use the next_cursor value as the cursor parameter in the next request
  3. Repeat until has_more is false
# Page 1
curl "https://api.zeridion.com/v1/jobs?state=failed&limit=20" \
-H "Authorization: Bearer $API_KEY"

# Page 2 (using next_cursor from page 1)
curl "https://api.zeridion.com/v1/jobs?state=failed&limit=20&cursor=eyJ..." \
-H "Authorization: Bearer $API_KEY"

POST /v1/jobs/{job_id}/cancel

Cancel a job. Only jobs in pending or scheduled state can be cancelled.

Request

POST /v1/jobs/{job_id}/cancel
Authorization: Bearer <api_key>

No request body is required.

Response

200 OK

{
"id": "job_01HYX3K7M8N9P2Q4R5S6T7U8V9",
"state": "cancelled"
}

Behavior

  • Pending / Scheduled jobs are cancelled immediately.
  • Processing, succeeded, failed, cancelled, and dead-letter jobs cannot be cancelled — the endpoint returns 409 Conflict.
  • Parent cancellation cascades: cancelling a parent job also cancels any child continuation jobs that are still in scheduled state.

Errors

StatusCodeCondition
404job_not_foundJob does not exist
409invalid_stateJob is not in pending or scheduled state

POST /v1/jobs/{job_id}/retry

Manually retry a failed or dead-lettered job. Resets the job to pending state so it can be picked up by a worker again.

Request

POST /v1/jobs/{job_id}/retry
Authorization: Bearer <api_key>

No request body is required.

Response

200 OK

{
"id": "job_01HYX3K7M8N9P2Q4R5S6T7U8V9",
"state": "pending",
"attempt": 3
}
FieldTypeDescription
idstringJob identifier
statestringAlways pending after a successful retry
attemptintegerCurrent attempt number

Behavior

  • Only jobs in failed or dead_letter state can be retried.
  • If the job has exhausted all attempts (attempt >= max_attempts), the max_attempts is automatically bumped to attempt + 1 to allow the retry.
  • The job's error details, timing fields, and worker assignment are cleared.

Errors

StatusCodeCondition
404job_not_foundJob does not exist
409invalid_stateJob is not in failed or dead_letter state

Job Continuations

Continuations let you chain jobs together in a parent-child relationship. A child job waits for its parent to succeed before it runs.

Creating a continuation

Include parent_job_id when creating a job via POST /v1/jobs:

{
"job_type": "notification.send",
"payload": { "channel": "slack", "message": "Data sync complete" },
"queue": "default",
"parent_job_id": "job_01HYX3K7M8N9P2Q4R5S6T7U8V9"
}

State behavior

The child's initial state depends on the parent's current state:

Parent stateChild initial stateBehavior
pending / scheduled / processingscheduledChild waits for parent to complete
succeededpendingChild runs immediately (parent already done)
cancelled / dead_letterCreation rejected with 409 parent_terminal

Activation and cascading

  • Parent succeeds: all child jobs in scheduled state are activated (moved to pending). The parent's ack response includes children_activated with the count.
  • Parent dead-letters: all child jobs in scheduled state are cancelled.
  • Parent is cancelled: all child jobs in scheduled state are cancelled.

Errors

StatusCodeCondition
409parent_terminalParent is cancelled or dead_letter
422parent_not_foundThe parent_job_id does not reference an existing job