API Reference

Full reference for the Verne Clockwork HTTP API. All endpoints are served from https://api.vernesoft.com.


Authentication

Clockwork can be reached two ways. Both operate on the same jobs for your tenant — pick whichever fits the caller.

Browser/console calls use your Kratos session cookie against the /dashboard/clockwork/* routes. The ory_kratos_session cookie is set automatically when you log in to the Verne Console.

Cookie: ory_kratos_session=<your_session_token>

Requests without a valid session return 401 Unauthorized. Admin accounts cannot access tenant dashboard routes and receive 403 Forbidden.

2. API key — Programmatic

Server-to-server calls use a Bearer API key against the /v1/clockwork/* routes. Clockwork keys follow the format:

vrn_clockwork_<secret>

Example header:

Authorization: Bearer vrn_clockwork_9f8a7...

Create and rotate keys on the Dashboard → Keys page (choose the Clockwork engine). The key is scoped to a single tenant — the tenant is derived from the key itself, so a caller can only ever read or modify its own jobs. A key from another engine (e.g. vrn_relay_*) is rejected with 403 Forbidden.

Requests with a missing or revoked key return 401 Unauthorized.

Route mapping

The two access modes are 1:1 — identical request bodies, responses, and status codes. Only the base path and the auth header differ. The rest of this reference documents the /dashboard/clockwork/* (session) paths; to call the API-key equivalent, swap the prefix:

Session (cookie)API key (Bearer)
GET /dashboard/clockwork/jobsGET /v1/clockwork/jobs
POST /dashboard/clockwork/jobsPOST /v1/clockwork/jobs
PATCH /dashboard/clockwork/jobs/{job_id}PATCH /v1/clockwork/jobs/{job_id}
DELETE /dashboard/clockwork/jobs/{job_id}DELETE /v1/clockwork/jobs/{job_id}
GET /dashboard/clockwork/jobs/{job_id}/executionsGET /v1/clockwork/jobs/{job_id}/executions
GET /dashboard/clockwork/delayedGET /v1/clockwork/delayed
POST /dashboard/clockwork/delayedPOST /v1/clockwork/delayed
DELETE /dashboard/clockwork/delayed/{job_id}DELETE /v1/clockwork/delayed/{job_id}
GET /dashboard/clockwork/delayed/{job_id}/executionsGET /v1/clockwork/delayed/{job_id}/executions

Example — list jobs with an API key:

curl https://api.vernesoft.com/v1/clockwork/jobs \
  -H "Authorization: Bearer vrn_clockwork_9f8a7..."

Example — create a cron job with an API key:

curl -X POST https://api.vernesoft.com/v1/clockwork/jobs \
  -H "Authorization: Bearer vrn_clockwork_9f8a7..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Nightly report",
    "schedule": "0 2 * * *",
    "url": "https://yourapp.com/internal/reports/generate",
    "method": "POST"
  }'

Cron Jobs

Recurring jobs defined by a standard 5-field cron expression.

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

List Cron Jobs

GET /dashboard/clockwork/jobs

Returns all cron jobs for the authenticated tenant, ordered by creation date (newest first).

Example

curl https://api.vernesoft.com/dashboard/clockwork/jobs \
  -H "Cookie: ory_kratos_session=<session>"

Response (200 OK)

[
  {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "tenant_id": "tenant_001",
    "name": "Health ping",
    "schedule": "*/5 * * * *",
    "url": "https://yourapp.com/health",
    "method": "GET",
    "headers": {},
    "body": null,
    "is_active": true,
    "last_run_at": "2026-04-09T12:00:00Z",
    "next_run_at": "2026-04-09T12:05:00Z",
    "created_at": "2026-04-01T10:00:00Z",
    "updated_at": "2026-04-09T12:00:00Z"
  }
]

Create Cron Job

POST /dashboard/clockwork/jobs

Request Body

FieldTypeRequiredDescription
namestringYesHuman-readable name for the job.
schedulestringYes5-field cron expression (e.g. 0 * * * *).
urlstringYesTarget URL to call on each execution.
methodstringNoHTTP method. Default: POST. Allowed: GET, POST, PUT, PATCH, DELETE.
headersobjectNoKey-value map of custom request headers.
bodystringNoRaw request body (sent as-is).

Example

curl -X POST https://api.vernesoft.com/dashboard/clockwork/jobs \
  -H "Cookie: ory_kratos_session=<session>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Nightly report",
    "schedule": "0 2 * * *",
    "url": "https://yourapp.com/internal/reports/generate",
    "method": "POST",
    "headers": { "X-Internal-Token": "secret" },
    "body": "{\"type\": \"daily\"}"
  }'

Response (201 Created)

Returns the created CronJob object.

Status CodeMeaning
201 CreatedJob created successfully.
400 Bad RequestInvalid cron expression or unsupported HTTP method.
401 UnauthorizedMissing or invalid session.

Update Cron Job

PATCH /dashboard/clockwork/jobs/{job_id}

All fields are optional — only provided fields are updated.

Request Body

FieldTypeDescription
namestringNew job name.
schedulestringNew 5-field cron expression.
urlstringNew target URL.
methodstringNew HTTP method.
headersobjectNew headers map (replaces existing).
bodystringNew body (replaces existing).
is_activebooleanSet to false to pause the job without deleting it.

Example

curl -X PATCH https://api.vernesoft.com/dashboard/clockwork/jobs/550e8400-e29b-41d4-a716-446655440000 \
  -H "Cookie: ory_kratos_session=<session>" \
  -H "Content-Type: application/json" \
  -d '{ "is_active": false }'

Response (200 OK)

Returns the updated CronJob object.

Status CodeMeaning
200 OKJob updated.
400 Bad RequestInvalid cron expression or HTTP method.
404 Not FoundJob not found (or belongs to another tenant).

Delete Cron Job

DELETE /dashboard/clockwork/jobs/{job_id}

Permanently deletes the cron job and all its execution history.

curl -X DELETE https://api.vernesoft.com/dashboard/clockwork/jobs/550e8400-e29b-41d4-a716-446655440000 \
  -H "Cookie: ory_kratos_session=<session>"
Status CodeMeaning
204 No ContentJob deleted.
404 Not FoundJob not found.

List Cron Job Executions

GET /dashboard/clockwork/jobs/{job_id}/executions

Returns the last 100 executions for a cron job, ordered newest first.

curl https://api.vernesoft.com/dashboard/clockwork/jobs/550e8400-e29b-41d4-a716-446655440000/executions \
  -H "Cookie: ory_kratos_session=<session>"

Response (200 OK)

[
  {
    "id": "exec_001",
    "job_id": "550e8400-e29b-41d4-a716-446655440000",
    "status": "success",
    "started_at": "2026-04-09T12:00:00Z",
    "completed_at": "2026-04-09T12:00:00.312Z",
    "duration_ms": 312,
    "response_status": 200,
    "response_body": "{\"ok\": true}",
    "error_message": null
  }
]
status valueMeaning
successTarget URL returned 2xx.
failedTarget URL returned non-2xx or network error.
runningExecution in progress.

Delayed Jobs

One-shot jobs that execute once at a specific future timestamp.


List Delayed Jobs

GET /dashboard/clockwork/delayed

Returns all delayed jobs for the authenticated tenant, ordered by run_at ascending.

curl https://api.vernesoft.com/dashboard/clockwork/delayed \
  -H "Cookie: ory_kratos_session=<session>"

Response (200 OK)

[
  {
    "id": "660f9511-f3ac-52e5-b827-557766551111",
    "tenant_id": "tenant_001",
    "name": "Send welcome email",
    "run_at": "2026-04-10T09:00:00Z",
    "url": "https://yourapp.com/internal/send-welcome",
    "method": "POST",
    "headers": {},
    "body": "{\"user_id\": \"usr_001\"}",
    "status": "pending",
    "created_at": "2026-04-09T10:00:00Z",
    "updated_at": "2026-04-09T10:00:00Z"
  }
]
status valueMeaning
pendingWaiting for run_at.
runningCurrently being executed.
completedExecution finished.
cancelledCancelled before execution.

Create Delayed Job

POST /dashboard/clockwork/delayed

Request Body

FieldTypeRequiredDescription
namestringYesHuman-readable name for the job.
run_atstringYesISO 8601 UTC timestamp. Must be in the future.
urlstringYesTarget URL to call at execution time.
methodstringNoHTTP method. Default: POST. Allowed: GET, POST, PUT, PATCH, DELETE.
headersobjectNoKey-value map of custom request headers.
bodystringNoRaw request body (sent as-is).

Example

curl -X POST https://api.vernesoft.com/dashboard/clockwork/delayed \
  -H "Cookie: ory_kratos_session=<session>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Send invoice reminder",
    "run_at": "2026-04-15T08:00:00Z",
    "url": "https://yourapp.com/internal/invoices/remind",
    "method": "POST",
    "body": "{\"invoice_id\": \"inv_042\"}"
  }'

Response (201 Created)

Returns the created DelayedJob object.

Status CodeMeaning
201 CreatedJob scheduled.
400 Bad Requestrun_at is in the past, or unsupported HTTP method.
401 UnauthorizedMissing or invalid session.

Cancel Delayed Job

DELETE /dashboard/clockwork/delayed/{job_id}

Cancels a pending delayed job. Jobs that are already running or completed cannot be cancelled.

curl -X DELETE https://api.vernesoft.com/dashboard/clockwork/delayed/660f9511-f3ac-52e5-b827-557766551111 \
  -H "Cookie: ory_kratos_session=<session>"
Status CodeMeaning
204 No ContentJob cancelled.
404 Not FoundJob not found.
409 ConflictJob is not in pending status and cannot be cancelled.

List Delayed Job Executions

GET /dashboard/clockwork/delayed/{job_id}/executions

Returns the execution record(s) for a delayed job (at most one for one-shot jobs), ordered newest first.

curl https://api.vernesoft.com/dashboard/clockwork/delayed/660f9511-f3ac-52e5-b827-557766551111/executions \
  -H "Cookie: ory_kratos_session=<session>"

Response (200 OK)

[
  {
    "id": "exec_002",
    "job_id": "660f9511-f3ac-52e5-b827-557766551111",
    "status": "success",
    "started_at": "2026-04-10T09:00:01Z",
    "completed_at": "2026-04-10T09:00:01.874Z",
    "duration_ms": 874,
    "response_status": 200,
    "response_body": "{\"sent\": true}",
    "error_message": null
  }
]

Error Format

All errors follow a consistent structure:

{
  "error": "Invalid cron schedule. Expected 5-field expression (e.g. \"0 * * * *\")"
}

Include the request_id when contacting support for faster resolution.