REST API
Complete reference for the Chronos developer-facing API.
Conventions
Section titled “Conventions”| 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) |
Response envelope
Section titled “Response envelope”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" }]}Rate limiting
Section titled “Rate limiting”100 requests per 10 seconds per API key. Exceeding returns 429 with code rate_limit_exceeded.
Schedules
Section titled “Schedules”Create Schedule
Section titled “Create Schedule”POST /v1/schedulesCreates 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. |
max_retries | integer | No | 3 | Min 0. |
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 fieldsrate_limit_exceeded(429)
List Schedules
Section titled “List Schedules”GET /v1/schedulesQuery 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 Schedule
Section titled “Get Schedule”GET /v1/schedules/:idResponse: 200 OK. single schedule object.
Errors:
schedule_not_found(404)
Update Schedule
Section titled “Update Schedule”PATCH /v1/schedules/:idAll 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. |
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 schedulesschedule_completed(409): cannot update completed scheduleshandler_required_for_pull(400): pull delivery requires a handlerschedule_status_changed(409): optimistic concurrency conflictvalidation_error(422)
Archive Schedule
Section titled “Archive Schedule”POST /v1/schedules/:id/archiveNo 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)
Delete Schedule
Section titled “Delete Schedule”DELETE /v1/schedules/:idPermanently deletes the schedule. Associated jobs have their schedule_id set to null.
Response: 204 No Content
Errors:
schedule_not_found(404)
Create Job
Section titled “Create Job”POST /v1/jobsCreates 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. |
max_retries | integer | No | 3 | Min 0. |
idempotency_key | string | No | null | Dedup key. Max 255 chars. Scoped to your account. |
Timing options:
- Neither
delaynorscheduled_for→ runs immediately delay→ runs after the specified durationscheduled_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 accountvalidation_error(422)
List Jobs
Section titled “List Jobs”GET /v1/jobsQuery 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 Job
Section titled “Get Job”GET /v1/jobs/:idResponse: 200 OK. single job object.
Errors:
job_not_found(404)
Executions
Section titled “Executions”List Executions
Section titled “List Executions”GET /v1/executionsQuery 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 Execution
Section titled “Get Execution”GET /v1/executions/:idResponse: 200 OK. single execution object.
Errors:
execution_not_found(404)
Worker
Section titled “Worker”These endpoints are used by the SDK internally. You can also call them directly if building a custom worker.
Claim Job
Section titled “Claim Job”POST /v1/worker/jobs/claimClaims 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}Report Result
Section titled “Report Result”POST /v1/worker/executions/:id/resultReports the outcome of a claimed job’s execution.
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
status | string | Yes | completed or failed |
result | object | No | Execution result data. Allowed only when completed; forbidden when failed. |
error | string | Required when failed | Error message. Max 4096 chars. |
Business rules:
- Same-status re-report is idempotent (returns 200, no-op)
- On
failedwith retries remaining: job transitions toretrying, new execution scheduled with exponential backoff - On
failedwith retries exhausted: job transitions tofailed
Response: 200 OK
{ "success": true, "message": "Result recorded", "data": null}Errors:
execution_not_found(404)execution_not_running(409): execution is not inrunningstatus
Signing Key and API Keys
Section titled “Signing Key and API Keys”Signing key and API key management are session-authenticated dashboard operations. API-key clients cannot read, create, rotate, or revoke keys through these endpoints.
See the Signature Verification guide for using your signing secret.