Skip to content

REST API

Complete reference for the Chronos developer-facing API.

Convention Value
Base URL https://api.chronos.sh
Authentication Authorization: Bearer chrns_your_api_key
Content type application/json
Field casing snake_case
IDs UUID v4
Timestamps ISO 8601
Pagination page + size query params (defaults: page 1, size 20, max size 100)

All responses use a consistent envelope:

{
"success": true,
"message": "Human-readable message",
"data": { ... }
}

Paginated responses add:

{
"meta": {
"paging": { "page": 1, "pages": 5, "size": 20, "total": 100 }
}
}

Error responses:

{
"success": false,
"message": "What went wrong",
"code": "error_code",
"errors": [{ "field": "name", "message": "is required" }]
}

Approximately 100 requests per 10 seconds per client IP. Every response includes rate-limit headers; treat them as the authoritative view of your budget:

Header Description
X-RateLimit-Limit Maximum requests allowed per window.
X-RateLimit-Remaining Requests remaining in the current window.
X-RateLimit-Reset Seconds until the current window resets.

When the limit is exceeded, the API returns 429 with code rate_limit_exceeded and a Retry-After header indicating how many seconds to wait before retrying.


POST /v1/schedules

Creates a recurring schedule. Exactly one of cron or interval is required.

Request body:

Field Type Required Default Description
name string Yes Display name. Max 255 chars.
description string No null Max 1000 chars.
handler string Required for pull delivery Routing key. Max 255 chars.
cron string XOR with interval Cron expression.
interval object XOR with cron { value: int, unit: string }
interval.value integer Yes (if interval) Positive integer.
interval.unit string Yes (if interval) second, minute, hour, day, week
timezone string No Account timezone IANA timezone (e.g., America/New_York).
runs integer No null (unlimited) Max jobs to create before completing.
stop_at string No null ISO 8601 date. Must be in the future.
delivery object No { type: "pull" } Delivery configuration.
delivery.type string Yes (if delivery) pull or push
delivery.http object Required if push HTTP delivery config.
delivery.http.url string Yes HTTPS URL. No private/localhost IPs.
delivery.http.method string Yes GET, POST, PUT, PATCH, DELETE
delivery.http.headers object No Custom headers (Record<string, string>).
payload object No null Job payload. Max 64KB serialized. Must be non-empty if provided.
timeout integer No 30 Seconds. Positive integer, capped by your plan.
max_retries integer No 3 Min 0.

cron and interval must not resolve below your plan’s minimum interval. See Pricing & Limits.

Response: 201 Created

{
"success": true,
"message": "Schedule created",
"data": {
"id": "uuid",
"account_id": "uuid",
"name": "string",
"description": "string | null",
"handler": "string | null",
"cron": "string | null",
"interval": "{ value, unit } | null",
"timezone": "string",
"runs": "number | null",
"run_count": 0,
"stop_at": "ISO 8601 | null",
"delivery": { "type": "pull | push", "http": "{ url, method, headers? } | undefined" },
"payload": "object | null",
"timeout": 30,
"max_retries": 3,
"status": "active",
"next_run_at": "ISO 8601 | null",
"last_run_at": "ISO 8601 | null",
"created_at": "ISO 8601",
"updated_at": "ISO 8601"
}
}

Errors:

  • validation_error (422): invalid or missing fields
  • plan_limit_exceeded (403): active-schedule limit reached, timeout over your plan’s cap, or cadence below your plan’s minimum interval
  • rate_limit_exceeded (429)

GET /v1/schedules

Query params:

Param Type Default Description
page integer 1 Page number.
size integer 20 Items per page. Max 100.
status string Filter: active, paused, completed, archived

Returns all schedules including archived unless filtered by status.

Response: 200 OK. paginated array of schedule objects.


GET /v1/schedules/:id

Response: 200 OK. single schedule object.

Errors:

  • schedule_not_found (404)

PATCH /v1/schedules/:id

All fields optional. At least one field required.

Field Type Description
name string Max 255 chars.
description string | null null clears. Max 1000 chars.
handler string Max 255 chars.
cron string Cannot combine with interval in same request.
interval object Cannot combine with cron in same request.
timezone string IANA timezone.
runs integer | null null removes run limit.
stop_at string | null null removes stop time.
delivery object Same shape as create.
payload object | null null clears. Max 64KB.
timeout integer Positive, capped by your plan.
max_retries integer Min 0.

If cron or interval changes, next_run_at is recomputed. If timezone changes, next_run_at is recomputed for cron schedules.

Response: 200 OK. updated schedule object.

Errors:

  • schedule_not_found (404)
  • schedule_archived (409): cannot update archived schedules
  • schedule_completed (409): cannot update completed schedules
  • handler_required_for_pull (400): pull delivery requires a handler
  • schedule_status_changed (409): optimistic concurrency conflict
  • plan_limit_exceeded (403): timeout over your plan’s cap, or cadence below your plan’s minimum interval
  • validation_error (422)

POST /v1/schedules/:id/trigger

No request body. Creates a job from the schedule immediately, bypassing its timing. Increments run_count: a manual trigger consumes a run, and completes the schedule if it reaches the runs limit.

Response: 201 Created. the created job object.

Errors:

  • schedule_not_found (404)
  • schedule_archived (409): cannot trigger archived schedules
  • schedule_completed (409): cannot trigger completed schedules

POST /v1/schedules/:id/pause

No request body. No new jobs are spawned while paused. Jobs already spawned are unaffected.

Response: 200 OK. schedule object with status: "paused".

Errors:

  • schedule_not_found (404)
  • schedule_already_paused (409)
  • schedule_archived (409)
  • schedule_completed (409)

POST /v1/schedules/:id/resume

No request body. Recomputes next_run_at from the current time; interval schedules re-anchor to the resume time, cron schedules keep their alignment. If the schedule’s runs limit is reached or stop_at falls before the next run, the request fails with schedule_completed.

Response: 200 OK. schedule object with status: "active".

Errors:

  • schedule_not_found (404)
  • schedule_already_active (409)
  • schedule_archived (409)
  • schedule_completed (409)
  • schedule_cadence_invalid (422): the stored cron, interval, or timezone can no longer be computed; update the schedule before resuming
  • plan_limit_exceeded (403): resuming would exceed your plan’s active-schedule limit, or the stored timeout or cadence no longer fits your plan (after a downgrade)

POST /v1/schedules/:id/archive

No request body. Cancels all pending/queued/ready/retrying jobs for this schedule.

Response: 200 OK. schedule object with status: "archived".

Errors:

  • schedule_not_found (404)
  • schedule_archived (409): already archived

DELETE /v1/schedules/:id

Permanently deletes the schedule. Associated jobs have their schedule_id set to null.

Response: 204 No Content

Errors:

  • schedule_not_found (404)

POST /v1/jobs

Creates a one-off job. Runs immediately unless delay or scheduled_for is set.

Request body:

Field Type Required Default Description
name string Yes Display name. Max 255 chars.
handler string Required for pull Routing key. Max 255 chars.
delay object No Relative timing. XOR with scheduled_for.
delay.value integer Yes (if delay) Positive integer.
delay.unit string Yes (if delay) second, minute, hour, day, week
scheduled_for string No Absolute ISO 8601 time. Must be in the future. XOR with delay.
delivery object No { type: "pull" } Same shape as schedules.
payload object No null Max 64KB. Must be non-empty if provided.
timeout integer No 30 Seconds. Positive integer, capped by your plan.
max_retries integer No 3 Min 0.
idempotency_key string No null Dedup key. Max 255 chars. Scoped to your account.

Timing options:

  • Neither delay nor scheduled_for → runs immediately
  • delay → runs after the specified duration
  • scheduled_for → runs at the specified time

Response: 201 Created

{
"success": true,
"message": "Job created",
"data": {
"id": "uuid",
"account_id": "uuid",
"schedule_id": null,
"name": "string",
"handler": "string | null",
"idempotency_key": "string | null",
"scheduled_for": "ISO 8601",
"run_at": "ISO 8601",
"delivery": { "type": "pull | push", "http": "..." },
"payload": "object | null",
"timeout": 30,
"max_retries": 3,
"attempt_count": 0,
"status": "pending",
"last_error": "string | null",
"started_at": "ISO 8601 | null",
"completed_at": "ISO 8601 | null",
"created_at": "ISO 8601",
"updated_at": "ISO 8601"
}
}

Errors:

  • idempotency_key_conflict (409): duplicate key on same account
  • plan_limit_exceeded (403): timeout over your plan’s cap
  • validation_error (422)

GET /v1/jobs

Query params:

Param Type Default Description
page integer 1 Page number.
size integer 20 Max 100.
schedule_id string UUID, or literal "null" for one-off jobs.
handler string Filter by handler name.
status string pending, admitting, queued, ready, running, retrying, completed, failed, cancelled, skipped
scheduled_before string ISO 8601 upper bound.
scheduled_after string ISO 8601 lower bound. Must be ≤ scheduled_before.

Response: 200 OK. paginated array of job objects.


GET /v1/jobs/:id

Response: 200 OK. single job object.

Errors:

  • job_not_found (404)

POST /v1/jobs/:id/cancel

No request body. The job record is preserved for audit.

Response: 200 OK. job object with status: "cancelled".

Errors:

  • job_not_found (404)
  • job_not_cancellable (409): job must be pending, admitting, queued, ready, or retrying
  • job_status_changed (409): concurrent update detected; retry the operation

POST /v1/jobs/:id/skip

No request body. Only schedule-spawned jobs can be skipped; cancel one-off jobs instead.

Response: 200 OK. job object with status: "skipped".

Errors:

  • job_not_found (404)
  • job_not_scheduled (409): job has no schedule_id
  • job_not_skippable (409): job must be pending or queued
  • job_status_changed (409): concurrent update detected; retry the operation

POST /v1/jobs/:id/retry

No request body. Re-queues a failed job to run immediately; a new execution is created when it runs. The retry budget is not reset: attempt_count carries over, so a job that exhausted max_retries gets one more attempt, not a fresh set.

Response: 200 OK. job object with status: "pending".

Errors:

  • job_not_found (404)
  • job_not_failed (409): only failed jobs can be retried
  • job_status_changed (409): concurrent update detected; retry the operation

GET /v1/executions

Query params:

Param Type Default Description
page integer 1 Page number.
size integer 20 Max 100.
job_id string UUID.
schedule_id string UUID, or "null" for one-off job executions.
handler string Filter by handler name.
status string pending, running, completed, failed, timeout
created_before string ISO 8601 upper bound.
created_after string ISO 8601 lower bound. Must be ≤ created_before.

Response: 200 OK

{
"success": true,
"message": "Executions fetched",
"data": [{
"id": "uuid",
"account_id": "uuid",
"job_id": "uuid",
"status": "pending | running | completed | failed | timeout",
"trigger": "system | system_retry | manual",
"started_at": "ISO 8601 | null",
"completed_at": "ISO 8601 | null",
"duration_ms": "number | null",
"result": "object | null",
"error": "string | null",
"response_code": "number | null",
"created_at": "ISO 8601"
}],
"meta": { "paging": { ... } }
}

GET /v1/executions/:id

Response: 200 OK. single execution object.

Errors:

  • execution_not_found (404)

GET /v1/workers

Returns registered workers for your account with derived online/offline status.

Query params:

Param Type Default Description
page integer 1 Page number.
size integer 20 Items per page. Max 100.
status string Filter: online, offline
handler string Filter by handler name.

Response: 200 OK

{
"success": true,
"message": "Workers fetched",
"data": [
{
"id": "uuid",
"worker_id": "w_a1b2c3",
"sdk_version": "0.0.2",
"runtime": "node/v22.1.0",
"handlers": ["echo", "slow-job"],
"poll_wait_seconds": 20,
"uptime_ms": 3600000,
"status": "online",
"last_seen_at": "2026-06-20T12:00:00.000Z",
"created_at": "2026-06-20T11:00:00.000Z"
}
],
"meta": {
"paging": { "page": 1, "pages": 1, "size": 20, "total": 1 }
}
}

GET /v1/workers/:id

Response: 200 OK. Single worker object with derived status.

Errors:

  • worker_not_found (404)

These endpoints are used by the SDK internally. You can also call them directly if building a custom worker.

POST /v1/workers/jobs/claim

Claims the next available job for your registered handlers.

Request body:

Field Type Required Default Description
wait_time_seconds integer No 0 Long-poll duration. 0–20.
handlers string[] No Filter by handler names. Min 1 item if provided.

When wait_time_seconds > 0, the request holds open until a job is available or the timeout expires. The SDK uses 20 seconds by default.

Response (job claimed): 200 OK

{
"success": true,
"message": "Job claimed",
"data": {
"job_id": "uuid",
"execution_id": "uuid",
"handler": "string",
"scheduled_for": "ISO 8601",
"attempt": 1,
"timeout": 30,
"payload": "object | null",
"schedule": "{ id: uuid, name: string } | null"
}
}

Response (no job available): 200 OK

{
"success": true,
"message": "No job available",
"data": null
}

POST /v1/workers/executions/:id/result

Reports the outcome of a claimed job’s execution.

Request body:

Field Type Required Description
status string Yes completed, failed, or timeout
result object No Execution result data. Allowed only when completed.
error string Required when failed Error message. Max 4096 chars. Forbidden for completed and timeout.

Business rules:

  • Same-status re-report is idempotent (returns 200, no-op)
  • On failed with retries remaining: job transitions to retrying, new execution scheduled with exponential backoff
  • On failed with retries exhausted: job transitions to failed

Response: 200 OK

{
"success": true,
"message": "Result recorded",
"data": null
}

Errors:

  • execution_not_found (404)
  • execution_not_running (409): execution is not in running status

Some of the API surface is session-authenticated and reserved for the dashboard; API keys cannot call it. This covers account and team management, billing, alert settings, signing key and API key management, the activity feed, and webhook URL testing.

Manage these through the dashboard. In particular, API-key clients cannot read, create, rotate, or revoke keys. See the Signature Verification guide for using your signing secret.