API reference · v1

Nine small endpoints. That's the whole API.

Everything lives under https://supercrontab.com/v1. Create a token on your account page (read-only tokens are available) and send it as Authorization: Bearer <token> on every call. Request and response bodies are JSON. Field names are snake_case, like status_code; camelCase works too. Each token can make 600 requests a minute, and the X-RateLimit-Remaining header tells you how many are left.

Errors always look the same: an HTTP status plus { "error": { "code": "...", "message": "..." } }, where the message says in plain words what to fix.

GET/jobs

List your jobs

Returns every cron job on your account, 100 at a time.

More about this call

Use it to check what is scheduled, or to find a job id for the other calls. If there are more than 100, the response includes a next_cursor; send it back as ?cursor= to get the next page.

FieldTypeNotes
cursorstringOptional. The next_cursor value from the previous page.
statusenumOptional. Show only active or only paused jobs.
Request
curl https://supercrontab.com/v1/jobs \
  -H "Authorization: Bearer tk_live_..."
Response 200
{
  "data": [{
    "id": "job_8f2k1abcd0ef",
    "name": "Warm homepage cache",
    "url": "https://shop.example.com/cron/warm",
    "method": "GET",
    "schedule": "*/5 * * * *",
    "timezone": "UTC",
    "status": "active",
    "next_run_at": "2026-09-16T09:05:00Z"
  }],
  "next_cursor": null
}
POST/jobs

Create a job

Tell us which URL to call and when, and we call it on schedule from then on.

More about this call

You get the new job back with its first next_run_at. If the schedule fires more often than your plan allows, the call fails with 422 and a message saying so.

FieldTypeNotes
namestringRequired. A label you will recognise in the dashboard and in alerts.
urlstringRequired. The URL we call. Must start with https://.
schedulestringRequired. Standard 5-field cron, for example 0 2 * * * for 02:00 every day.
timezonestringOptional. An IANA name like Europe/Berlin. Defaults to UTC.
methodenumOptional. GET, POST, PUT or DELETE. Defaults to GET.
headers, bodyobject, stringOptional. Extra request headers and a request body to send with each call.
notifyobjectOptional. Where to tell you about failures: { "email": "..." } and/or { "webhook": "https://..." }.
authobjectOptional. Credentials we attach to each call. See "Authentication for jobs" below.
Request
curl -X POST https://supercrontab.com/v1/jobs \
  -H "Authorization: Bearer tk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Nightly invoice export",
    "url": "https://api.example.com/tasks/export",
    "method": "POST",
    "schedule": "0 2 * * *",
    "timezone": "Europe/Berlin",
    "auth": { "type": "bearer", "token": "tk_..." },
    "notify": { "webhook": "https://hooks.example.com/sc" }
  }'
Response 201
{
  "id": "job_9a1zzq7r2m4n",
  "status": "active",
  "next_run_at": "2026-09-17T00:00:00Z"
}
GET/jobs/{id}/runs

See what happened on each run

The history of one job, newest run first.

More about this call

Each entry tells you when the run started, how long it took, whether it succeeded, the HTTP status your server answered with, how many attempts we made, and the beginning of the response body. Filter with ?status=failed to see only the runs that went wrong.

FieldTypeNotes
sinceISO-8601Optional. Only runs that started after this time.
statusenumOptional. ok or failed.
Request
curl "https://supercrontab.com/v1/jobs/job_8f2k1abcd0ef/runs?status=failed" \
  -H "Authorization: Bearer tk_live_..."
Response 200
{
  "data": [{
    "id": "run_01j8xk3m9p2q",
    "started_at": "2026-09-16T08:55:00Z",
    "duration_ms": 30000,
    "status": "failed",
    "http_status": null,
    "error": "timeout",
    "attempts": 3,
    "response_body": ""
  }],
  "next_cursor": null
}
POST/jobs/{id}/run

Run a job right now

Triggers one extra run straight away without touching the schedule.

More about this call

Handy after a deploy, or to check a new job works before its first scheduled time. The run is queued and usually starts within a few seconds; watch it arrive in the run history. Calling this twice within 5 seconds only queues one run.

FieldTypeNotes
noneNo request body needed.
Request
curl -X POST https://supercrontab.com/v1/jobs/job_8f2k1abcd0ef/run \
  -H "Authorization: Bearer tk_live_..."
Response 202
{ "run_id": "run_01j8yq2w8c5d", "status": "queued" }

Authentication for jobs

If the URL you want us to call needs credentials, put them in auth when you create or update the job, and we attach them on every call. Secrets are encrypted at rest and never shown again: when you read the job back you see ••••••••. When you update a job, send that masked value back (or leave auth out) to keep the existing secret; send a new value to replace it. The same auth shapes work on mock endpoints, where they say what callers must present.

basic: We send Authorization: Basic with the username and password encoded.
{ "type": "basic", "username": "u", "password": "p" }
bearer: We send Authorization: Bearer <token>.
{ "type": "bearer", "token": "..." }
api_key: We send the key in a header, or in the query string when in is "query".
{ "type": "api_key", "in": "header", "name": "X-Api-Key", "value": "..." }
oauth2_cc: We fetch a token with the client-credentials flow first, reuse it until it expires, then send it as a Bearer token.
{ "type": "oauth2_cc", "tokenUrl": "https://auth.example.com/token", "clientId": "...", "clientSecret": "...", "scope": "read" }
hmac: We sign the raw request body with HMAC-SHA256 and put the hex signature in the header you name.
{ "type": "hmac", "secret": "...", "header": "X-Signature", "prefix": "sha256=" }
POST/endpoints

Create a mock endpoint

Creates a URL that answers with exactly what you configure and logs everything it receives.

More about this call

Point a webhook or a cron job at it to see what your code sends, and to test how your code copes when the other side is slow or failing. The URL is https://{slug}.supercrontab.com/ and the slug is generated for you. Limits per account: Free 3 endpoints, 30 requests a minute, 500 a day; Pro 25, 300 a minute, 10,000 a day; Team 100, 1,000 a minute, 50,000 a day. Over the limit the endpoint answers 429 with a Retry-After header.

FieldTypeNotes
namestringRequired. A label for the dashboard.
methodsstringOptional. ANY (default) or a list like GET,POST. Other methods get 405.
status_codeintOptional. The status to answer with. Defaults to 200.
content_typestringOptional. Defaults to application/json.
bodystringOptional. The response body, up to 64 KB.
response_headersobjectOptional. Extra headers to add to every response.
delay_msintOptional. Wait this long before answering, up to 30000. Good for testing timeouts.
error_rate, error_statusintOptional. Answer error_status (default 500) on this percentage of requests, picked at random. Good for testing retries.
sequenceobjectOptional. A scripted list of steps per Idempotency-Key, for reproducing one exact failure. See "Fault sequences" below.
authobjectOptional. Require callers to authenticate: basic, bearer, api_key or hmac. Wrong or missing credentials get 401.
log_requestsboolOptional. Keep a log of incoming requests. Defaults to true.
Request
curl -X POST https://supercrontab.com/v1/endpoints \
  -H "Authorization: Bearer tk_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "name": "Order webhook", "status_code": 202, "body": "{\"received\":true}", "auth": { "type": "bearer", "token": "s3cret" } }'
Response 201
{
  "data": {
    "id": "ep_7hx2k9q4m1p3",
    "slug": "kq7mx2p9tz",
    "url": "https://kq7mx2p9tz.supercrontab.com/",
    "status_code": 202,
    "auth": { "type": "bearer", "token": "••••••••" }
  }
}
GET/endpoints

List your endpoints

Every mock endpoint on your account with its URL, current settings and hit count, 100 at a time.

More about this call

GET /endpoints/{id} returns a single one in the same shape.

FieldTypeNotes
cursorstringOptional. The next_cursor value from the previous page.
Request
curl https://supercrontab.com/v1/endpoints \
  -H "Authorization: Bearer tk_live_..."
Response 200
{
  "data": [{
    "id": "ep_7hx2k9q4m1p3",
    "slug": "kq7mx2p9tz",
    "url": "https://kq7mx2p9tz.supercrontab.com/",
    "name": "Order webhook",
    "methods": "ANY",
    "status_code": 202,
    "delay_ms": 0,
    "error_rate": 0,
    "sequence": null,
    "hits": 12,
    "last_hit_at": "2026-09-17T10:12:03Z"
  }],
  "next_cursor": null
}
PATCH/endpoints/{id}

Change or delete an endpoint

Send only the fields you want to change; everything else stays as it is.

More about this call

The URL never changes, so anything already pointing at the endpoint keeps working with the new behaviour from the next request. To remove an endpoint and its log for good, call DELETE /endpoints/{id}; its URL then answers 404.

FieldTypeNotes
any field from createOptional. Send auth as the masked value you received to keep the existing secret.
Request
curl -X PATCH https://supercrontab.com/v1/endpoints/ep_7hx2k9q4m1p3 \
  -H "Authorization: Bearer tk_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "delay_ms": 3000, "error_rate": 10 }'
Response 200
{
  "data": {
    "id": "ep_7hx2k9q4m1p3",
    "url": "https://kq7mx2p9tz.supercrontab.com/",
    "status_code": 202,
    "delay_ms": 3000,
    "error_rate": 10,
    "error_status": 500
  }
}
GET/endpoints/{id}/requests

Read the request log

Everything the endpoint has received, newest first: method, path, query string, headers, the first 16 KB of the body, the caller IP and the status we answered with.

More about this call

Authorization, Cookie and API key headers are shown as [redacted] because we never store them. To empty the log, call DELETE on the same path.

FieldTypeNotes
cursorstringOptional. The next_cursor value from the previous page.
Request
curl https://supercrontab.com/v1/endpoints/ep_7hx2k9q4m1p3/requests \
  -H "Authorization: Bearer tk_live_..."
Response 200
{
  "data": [{
    "received_at": "2026-09-17T10:12:03Z",
    "method": "POST",
    "path": "/",
    "headers": { "content-type": "application/json", "authorization": "[redacted]" },
    "body": "{\"order\":42}",
    "status": 202
  }],
  "next_cursor": null
}
DELETE/endpoints/{id}/sequence

Restart a fault sequence

Forgets which step every key has reached, so the next request with any key starts again at step 1.

More about this call

Call it at the beginning of a test run to make sure the scenario plays out the same way every time. Saving the endpoint with a different sequence restarts it too, and keys that have not been seen for 7 days are forgotten automatically.

FieldTypeNotes
noneNo request body needed.
Request
curl -X DELETE https://supercrontab.com/v1/endpoints/ep_7hx2k9q4m1p3/sequence \
  -H "Authorization: Bearer tk_live_..."
Response 204
(empty)

Fault sequences

A fault sequence is a short script for what the endpoint does on the first delivery, the second, the third and so on, so you can reproduce one exact failure on purpose and put it in a test. Requests with the same Idempotency-Key header count as retries of the same delivery.

ActionWhat the caller sees
respondAnswer normally. You can set status, body and delay_ms for this step; anything you leave out uses the endpoint settings.
dropLog the request, then cut the connection before sending a body. Your code sees a network error instead of an HTTP status, like a server that crashed after it saved your data.
timeoutKeep the connection open for delay_ms (default and maximum 30 seconds), then cut it. Tests what your code does when the other side never answers.
How it works, step by step

A mock endpoint can answer in three ways. The simplest is a fixed answer: the same status and body every time. The second is a random error rate, good for finding out whether your code retries at all. The third is the sequence: deterministic, so the same test gives the same result every run.

You give the endpoint a list of steps. Each incoming request is matched to a delivery by the value of its Idempotency-Key header (or another header you choose). The first request with a given key gets step 1, the second request with the same key gets step 2, and so on. A request with a new key starts again at step 1, and requests without the header all share one counter.

The example on the right reproduces the classic duplicate-order bug: the first delivery is logged and then the connection is cut, so your code cannot tell whether it went through. If your code retries with the same key, it gets 200. If it retries with a new key, it gets cut again, and you have found a bug.

FieldTypeNotes
stepsarrayRequired. 1 to 20 steps, each with an action and optional status, body and delay_ms.
key_headerstringOptional. Which request header identifies a delivery. Defaults to Idempotency-Key. Authorization and Cookie are not allowed.
on_endenumOptional. What happens after the last step: repeat_last (default) keeps answering with the last step; loop starts again from step 1.

Good to know: while a sequence is set, the endpoint's error rate is ignored. Every response carries an X-Supercrontab-Sequence-Step header so you can see which step you hit, and dropped requests show as dropped in the request log. Key values are stored as hashes, never as the raw header. One limit of running at the edge: a drop cuts the connection after the status line, so most HTTP clients report it as an unexpected end of the response rather than a connection refused.

sequence
{
  "key_header": "Idempotency-Key",
  "on_end": "repeat_last",
  "steps": [
    { "action": "drop" },
    { "action": "respond", "status": 200, "body": "{\"received\":true}" }
  ]
}

Webhook on failure

Set notify.webhook on a job and we POST a message like this to your URL when a run has failed three times in a row, and once more when the job succeeds again. Check the X-Supercrontab-Signature header (HMAC-SHA256 of the body with your webhook secret) to be sure the message came from us.

POST https://hooks.example.com/sc
X-Supercrontab-Signature: sha256=3f1c...

{
  "event": "job.failed",
  "job": { "id": "job_8f2k1abcd0ef", "name": "Warm homepage cache" },
  "run": { "id": "run_01j8xk3m9p2q", "http_status": 504, "duration_ms": 30000, "attempts": 3 },
  "response_excerpt": "<html>504 Gateway Time-out</html>",
  "dashboard_url": "https://supercrontab.com/dashboard"
}