Skip to main content

Recurring Jobs API

Recurring jobs execute automatically on a cron schedule. You can manage schedules through this API or declaratively using the SDK's [JobConfig(CronSchedule = "...")] attribute on IRecurringJob implementations.

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

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


PUT /v1/recurring/{id}

Create or update a recurring job schedule (upsert). The id is a stable identifier you provide (e.g., rjob_daily_cleanup). If a schedule with this ID exists, it is updated; otherwise a new one is created.

Request

PUT /v1/recurring/{id}
Authorization: Bearer <api_key>
Content-Type: application/json

Body

FieldTypeRequiredDescription
job_typestringYesJob type to execute on each trigger
cron_expressionstringYesCron expression defining the schedule
queuestringNoTarget queue. Default: "default"
payloadobjectNoFixed JSON payload passed to each execution
timezonestringNoIANA timezone for cron evaluation. Default: UTC
enabledbooleanNoWhether the schedule is active. Default: true
max_attemptsintegerNoPer-execution retry limit. Default: 3. On update, omitting this field keeps the existing value.
timeout_secondsintegerNoPer-execution timeout in seconds. Default: 1800. On update, omitting this field keeps the existing value.

Example

{
"job_type": "MyApp.Jobs.CleanupExpiredSessions",
"cron_expression": "0 3 * * *",
"queue": "maintenance",
"timezone": "America/New_York",
"max_attempts": 3,
"timeout_seconds": 600,
"payload": { "retention_days": 30 }
}

Response

200 OK

{
"id": "rjob_daily_cleanup",
"job_type": "MyApp.Jobs.CleanupExpiredSessions",
"queue": "maintenance",
"cron_expression": "0 3 * * *",
"timezone": "America/New_York",
"enabled": true,
"last_run_at": null,
"next_run_at": "2026-03-25T07:00:00Z",
"max_attempts": 3,
"timeout_seconds": 600,
"created_at": "2026-03-24T15:00:00Z",
"updated_at": null
}
FieldTypeDescription
idstringThe schedule identifier you provided in the URL
job_typestringJob type to execute
queuestringTarget queue
cron_expressionstringCron schedule
timezonestringIANA timezone
enabledbooleanWhether the schedule is active
last_run_atstring (ISO 8601)When the schedule last triggered, or null
next_run_atstring (ISO 8601)Next scheduled trigger time, or null if disabled
max_attemptsintegerPer-execution retry limit
timeout_secondsintegerPer-execution timeout
created_atstring (ISO 8601)When the schedule was first created
updated_atstring (ISO 8601)When the schedule was last modified, or null

Errors

StatusCodeCondition
400invalid_cron_expressionThe cron_expression could not be parsed. E.g., "not a cron".
400invalid_timezoneThe timezone is not a recognized IANA timezone. E.g., "Mars/Olympus_Mons".
409recurring_job_type_conflictA schedule with the same job_type already exists under a different ID.

GET /v1/recurring

List all recurring job schedules for the authenticated project, ordered by creation time (ascending).

Request

GET /v1/recurring
Authorization: Bearer <api_key>

Response

200 OK

{
"data": [
{
"id": "rjob_daily_cleanup",
"job_type": "MyApp.Jobs.CleanupExpiredSessions",
"queue": "maintenance",
"cron_expression": "0 3 * * *",
"timezone": "America/New_York",
"enabled": true,
"last_run_at": "2026-03-24T07:00:00Z",
"next_run_at": "2026-03-25T07:00:00Z",
"max_attempts": 3,
"timeout_seconds": 600,
"created_at": "2026-03-24T15:00:00Z",
"updated_at": null
}
]
}

Returns an empty data array if no recurring jobs are configured.


DELETE /v1/recurring/{id}

Permanently delete a recurring job schedule. This is a hard delete — the schedule is removed entirely. To temporarily pause a schedule without deleting it, use PUT with enabled: false instead.

Request

DELETE /v1/recurring/{id}
Authorization: Bearer <api_key>

Response

200 OK

{
"deleted": true
}

Errors

StatusCodeCondition
404recurring_job_not_foundNo schedule with this ID exists

Cron Expression Format

Cron expressions use the standard 5-field format parsed by the Cronos library:

┌───────────── minute (0–59)
│ ┌───────────── hour (0–23)
│ │ ┌───────────── day of month (1–31)
│ │ │ ┌───────────── month (1–12)
│ │ │ │ ┌───────────── day of week (0–6, Sun=0)
│ │ │ │ │
* * * * *

Common examples

ExpressionSchedule
* * * * *Every minute
0 * * * *Every hour
0 0 * * *Daily at midnight
0 9 * * 1-5Weekdays at 9:00 AM
*/15 * * * *Every 15 minutes
0 0 1 * *First day of month
30 2 * * 0Sundays at 2:30 AM

Timezone handling

By default, cron expressions are evaluated in UTC. Set the timezone field to an IANA timezone to evaluate in a local timezone (e.g., "America/New_York", "Europe/London"). This correctly handles daylight saving time transitions.


Disabling and Re-enabling

To pause a recurring schedule without deleting it, update it with enabled: false:

{
"job_type": "MyApp.Jobs.CleanupExpiredSessions",
"cron_expression": "0 3 * * *",
"queue": "maintenance",
"enabled": false
}

When disabled, next_run_at is set to null and the CronScheduler service skips this schedule. To resume, send another PUT with enabled: true.


SDK Auto-Registration

When the SDK starts, it calls POST /v1/workers/register with any recurring schedules discovered from [JobConfig(CronSchedule)] attributes. Each schedule is upserted with an ID derived from the job type (e.g., rjob_CleanupExpiredSessions). See the Recurring Jobs guide for more details.