Appearance
Jobs
Create, manage, and control scheduled cron jobs. Each job defines an HTTP request that Krafter executes on a recurring schedule.
Base URL: https://app.krafter.dev/api/v1
List Jobs
Retrieve all cron jobs.
GET /cron/jobsRequired scope: cron:read
A page carries at most 1,000 jobs — which covers every plan with a finite job limit, so most teams get everything in one call. When more remain, the response carries a next_cursor; pass it back as cursor for the following page.
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
limit | integer | 1000 | Jobs per page. Clamped to 1--1000. |
cursor | string | — | The next_cursor from a previous response. Pass it back unchanged. |
The response's meta.total is how many jobs the team has in total, not how many this page carries. next_cursor is absent on the last page rather than null, so if (body.next_cursor) is the whole loop condition.
TIP
A cursor belongs to this endpoint. One minted by the cron_list_jobs MCP tool is refused here, and a malformed cursor is answered with 422, not 500.
bash
# Walk every job, whatever the team's plan allows.
cursor=""
while :; do
page=$(curl -s "https://app.krafter.dev/api/v1/cron/jobs?limit=100&cursor=$cursor" \
-H "Authorization: Bearer kr_live_abc123def456")
echo "$page" | jq -r '.data[].name'
cursor=$(echo "$page" | jq -r '.next_cursor // empty')
[ -z "$cursor" ] && break
doneExample Request
bash
curl https://app.krafter.dev/api/v1/cron/jobs \
-H "Authorization: Bearer kr_live_abc123def456"Example Response
json
{
"data": [
{
"id": "a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d",
"name": "Health Check",
"schedule_type": "interval",
"schedule": "every_5m",
"timezone": "UTC",
"url": "https://example.com/api/health",
"method": "GET",
"headers": {},
"timeout_ms": 30000,
"max_retries": 3,
"enabled": true,
"failure_notify": false,
"last_status": "success",
"last_run_at": "2025-01-15T10:05:00Z",
"next_run_at": "2025-01-15T10:10:00Z",
"created_at": "2025-01-15T10:00:00Z",
"updated_at": "2025-01-15T10:00:00Z"
},
{
"id": "b2c3d4e5-6f7a-8b9c-0d1e-2f3a4b5c6d7e",
"name": "Nightly Report",
"schedule_type": "cron",
"schedule": "0 0 * * *",
"timezone": "Europe/Berlin",
"url": "https://example.com/api/reports/generate",
"method": "POST",
"headers": {"X-Api-Key": "secret"},
"timeout_ms": 60000,
"max_retries": 3,
"enabled": true,
"failure_notify": false,
"last_status": "success",
"last_run_at": "2025-01-15T23:00:00Z",
"next_run_at": "2025-01-16T23:00:00Z",
"created_at": "2025-01-10T08:00:00Z",
"updated_at": "2025-01-10T08:00:00Z"
}
]
}Create Job
Create a new cron job.
POST /cron/jobsRequired scope: cron:write
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Display name for the job. |
schedule_type | string | Yes | "cron", "interval", or "once". |
schedule | string | Yes | Cron expression (5-field), interval preset, or ISO-8601 datetime (when schedule_type is "once"). |
url | string | Yes | HTTP endpoint to call on each execution. |
timezone | string | No | IANA timezone identifier. Defaults to "UTC". |
method | string | No | HTTP method: "GET", "POST", "PUT", "PATCH", or "DELETE". Defaults to "POST". |
headers | object | No | Custom HTTP headers to include with each request. |
body | string | No | Request body sent verbatim with each execution. Useful for POST/PUT/PATCH endpoints. |
timeout_ms | integer | No | Request timeout in milliseconds. Defaults to 30000. Maximum 300000 (5 minutes). |
max_retries | integer | No | Retries after a failed attempt, 0--10. Total attempts are max_retries + 1, with 15s/30s/45s linear backoff. Defaults to 3 (four attempts). |
enabled | boolean | No | Whether the job is active. Defaults to true. |
signing_secret | string | No | When set, outgoing requests are signed with HMAC-SHA256. The value is encrypted at rest. See the Signing guide for verification. |
failure_notify | boolean | No | Email the team owner when the job fails and Krafter stops retrying. Sent once per outage, not per attempt — see Failure Notifications. Defaults to false. |
Example Request
bash
curl -X POST https://app.krafter.dev/api/v1/cron/jobs \
-H "Authorization: Bearer kr_live_abc123def456" \
-H "Content-Type: application/json" \
-d '{
"name": "Nightly Report",
"schedule_type": "cron",
"schedule": "0 0 * * *",
"timezone": "Europe/Berlin",
"url": "https://example.com/api/reports/generate",
"method": "POST",
"headers": {"X-Api-Key": "secret"},
"timeout_ms": 60000,
"max_retries": 3
}'Example Request with Body
The body field is sent verbatim with each execution. Combine with headers to control the content type.
bash
curl -X POST https://app.krafter.dev/api/v1/cron/jobs \
-H "Authorization: Bearer kr_live_abc123def456" \
-H "Content-Type: application/json" \
-d '{
"name": "Webhook Pinger",
"schedule_type": "interval",
"schedule": "every_5m",
"url": "https://example.com/api/webhook",
"method": "POST",
"headers": {"Content-Type": "application/json"},
"body": "{\"source\":\"krafter-cron\",\"event\":\"heartbeat\"}"
}'Example Response
json
// 201 Created
{
"data": {
"id": "b2c3d4e5-6f7a-8b9c-0d1e-2f3a4b5c6d7e",
"name": "Nightly Report",
"schedule_type": "cron",
"schedule": "0 0 * * *",
"timezone": "Europe/Berlin",
"url": "https://example.com/api/reports/generate",
"method": "POST",
"headers": {"X-Api-Key": "secret"},
"timeout_ms": 60000,
"max_retries": 3,
"enabled": true,
"failure_notify": false,
"last_status": null,
"last_run_at": null,
"next_run_at": "2025-01-15T23:00:00Z",
"created_at": "2025-01-15T10:00:00Z",
"updated_at": "2025-01-15T10:00:00Z"
}
}Get Job
Retrieve details of a specific job.
GET /cron/jobs/:idRequired scope: cron:read
Example Request
bash
curl https://app.krafter.dev/api/v1/cron/jobs/b2c3d4e5-6f7a-8b9c-0d1e-2f3a4b5c6d7e \
-H "Authorization: Bearer kr_live_abc123def456"Example Response
json
{
"data": {
"id": "b2c3d4e5-6f7a-8b9c-0d1e-2f3a4b5c6d7e",
"name": "Nightly Report",
"schedule_type": "cron",
"schedule": "0 0 * * *",
"timezone": "Europe/Berlin",
"url": "https://example.com/api/reports/generate",
"method": "POST",
"headers": {"X-Api-Key": "secret"},
"timeout_ms": 60000,
"max_retries": 3,
"enabled": true,
"failure_notify": false,
"last_status": "success",
"last_run_at": "2025-01-15T23:00:00Z",
"next_run_at": "2025-01-16T23:00:00Z",
"created_at": "2025-01-10T08:00:00Z",
"updated_at": "2025-01-10T08:00:00Z"
}
}Update Job
Update an existing job. Only provided fields are changed.
PUT /cron/jobs/:idRequired scope: cron:write
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
name | string | No | Display name for the job. |
schedule_type | string | No | "cron", "interval", or "once". |
schedule | string | No | Cron expression, interval preset, or ISO-8601 datetime. |
url | string | No | HTTP endpoint to call. |
timezone | string | No | IANA timezone identifier. |
method | string | No | HTTP method: "GET", "POST", "PUT", "PATCH", or "DELETE". |
headers | object | No | Custom HTTP headers. |
body | string | No | Request body sent verbatim with each execution. |
timeout_ms | integer | No | Request timeout in milliseconds. Maximum 300000 (5 minutes). |
max_retries | integer | No | Retries after a failed attempt, 0--10. Total attempts are max_retries + 1, with 15s/30s/45s linear backoff. |
enabled | boolean | No | Whether the job is active. |
signing_secret | string | No | When set, outgoing requests are signed with HMAC-SHA256. The value is encrypted at rest. See the Signing guide. |
failure_notify | boolean | No | Email the team owner when the job fails and Krafter stops retrying. Sent once per outage, not per attempt — see Failure Notifications. |
Example Request
bash
curl -X PUT https://app.krafter.dev/api/v1/cron/jobs/b2c3d4e5-6f7a-8b9c-0d1e-2f3a4b5c6d7e \
-H "Authorization: Bearer kr_live_abc123def456" \
-H "Content-Type: application/json" \
-d '{
"schedule": "0 2 * * *",
"timeout_ms": 120000
}'Example Response
json
{
"data": {
"id": "b2c3d4e5-6f7a-8b9c-0d1e-2f3a4b5c6d7e",
"name": "Nightly Report",
"schedule_type": "cron",
"schedule": "0 2 * * *",
"timezone": "Europe/Berlin",
"url": "https://example.com/api/reports/generate",
"method": "POST",
"headers": {"X-Api-Key": "secret"},
"timeout_ms": 120000,
"max_retries": 3,
"enabled": true,
"failure_notify": false,
"last_status": "success",
"last_run_at": "2025-01-15T23:00:00Z",
"next_run_at": "2025-01-17T01:00:00Z",
"created_at": "2025-01-10T08:00:00Z",
"updated_at": "2025-01-16T09:30:00Z"
}
}Delete Job
Permanently delete a job and all its execution history.
DELETE /cron/jobs/:idRequired scope: cron:write
Example Request
bash
curl -X DELETE https://app.krafter.dev/api/v1/cron/jobs/b2c3d4e5-6f7a-8b9c-0d1e-2f3a4b5c6d7e \
-H "Authorization: Bearer kr_live_abc123def456"Example Response
// 204 No ContentTrigger Job
Manually trigger a job immediately, regardless of its schedule. The job must be enabled — triggering a paused job returns 200 but the execution is silently dropped by the worker. To trigger a paused job, resume it first.
POST /cron/jobs/:id/triggerRequired scope: cron:write
WARNING
The trigger endpoint enqueues an execution unconditionally, but the worker checks enabled at run time and skips paused jobs without recording an execution. The HTTP 200 response only confirms the job was enqueued, not that it ran.
Example Request
bash
curl -X POST https://app.krafter.dev/api/v1/cron/jobs/a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d/trigger \
-H "Authorization: Bearer kr_live_abc123def456"Example Response
json
{
"ok": true
}TIP
Manual triggers on enabled jobs create a normal execution entry in the job's history. Check the Executions API to see the result.
Pause Job
Pause a job by setting enabled to false. Prevents future scheduled runs until resumed.
POST /cron/jobs/:id/pauseRequired scope: cron:write
Example Request
bash
curl -X POST https://app.krafter.dev/api/v1/cron/jobs/a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d/pause \
-H "Authorization: Bearer kr_live_abc123def456"Example Response
json
{
"data": {
"id": "a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d",
"name": "Health Check",
"schedule_type": "interval",
"schedule": "every_5m",
"timezone": "UTC",
"url": "https://example.com/api/health",
"method": "GET",
"headers": {},
"timeout_ms": 30000,
"max_retries": 3,
"enabled": false,
"failure_notify": false,
"last_status": "success",
"last_run_at": "2025-01-15T10:05:00Z",
"next_run_at": "2025-01-15T10:10:00Z",
"created_at": "2025-01-15T10:00:00Z",
"updated_at": "2025-01-15T10:06:00Z"
}
}Resume Job
Resume a paused job by setting enabled to true. next_run_at is preserved from before the pause — for cron expressions this can mean an immediate first run if the job was paused past its scheduled time. The next scheduler tick (every minute) will fire the job if next_run_at <= now.
POST /cron/jobs/:id/resumeRequired scope: cron:write
Example Request
bash
curl -X POST https://app.krafter.dev/api/v1/cron/jobs/a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d/resume \
-H "Authorization: Bearer kr_live_abc123def456"Example Response
json
{
"data": {
"id": "a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d",
"name": "Health Check",
"schedule_type": "interval",
"schedule": "every_5m",
"timezone": "UTC",
"url": "https://example.com/api/health",
"method": "GET",
"headers": {},
"timeout_ms": 30000,
"max_retries": 3,
"enabled": true,
"failure_notify": false,
"last_status": "success",
"last_run_at": "2025-01-15T10:05:00Z",
"next_run_at": "2025-01-15T10:10:00Z",
"created_at": "2025-01-15T10:00:00Z",
"updated_at": "2025-01-15T10:11:00Z"
}
}