Exactly once
Requires fireAt. A successful occurrence completes the runtime.
Quickstart / first successful POST
jscheduler is an HTTP scheduler, not a job runtime. You give it a schedule and JSON payload; when the minute arrives, it POSTs an occurrence to an endpoint you control.
The CLI ships as a native macOS or Linux binary. Login verifies the key before saving it to ~/.jscheduler/config.json.
curl -fsSL https://cli.jscheduler.com/install.sh | bash
jscheduler auth login --api-key jsk_your_keyEvery organization needs one untagged endpoint. It is the fallback destination for every event that does not match a tag-specific route.
jscheduler endpoints create \
--url https://example.com/webhooks/jschedulerAll schedule timestamps must land exactly on a minute. Choose a future UTC minute, then create the event:
jscheduler events create \
--name trial.expiring \
--kind ONE_TIME \
--fire-at 2030-07-13T09:00:00Z \
--tags lifecycle \
--payload '{"accountId":"acct_42"}'Prefer raw HTTP? The API uses the same tenant key:
curl https://api.jscheduler.com/scheduled-events \
-H "Authorization: Bearer $JSCHEDULER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"eventName": "trial.expiring",
"externalId": "trial_acct_42",
"tags": ["lifecycle"],
"payload": {"accountId": "acct_42"},
"schedule": {
"kind": "ONE_TIME",
"fireAt": "2030-07-13T09:00:00Z"
}
}'02 / Schedules
Requires fireAt. A successful occurrence completes the runtime.
Requires intervalMinutes and startAt. The next time advances without drift.
Five structured cron fields. Month and weekday names are accepted; seconds are not.
jscheduler events create \
--name weekday.report \
--kind CRON \
--cron "0 9 * * MON-FRI" \
--payload '{"report":"daily"}'03 / Delivery contract
jscheduler sends an HTTP POST with Content-Type: application/json and an Idempotency-Key header equal to the occurrence id.
{
"occurrenceId": "8c9…:2026-07-13T09:00:00Z",
"scheduledEventId": "8c9…",
"scheduledFor": "2026-07-13T09:00:00Z",
"eventName": "trial.expiring",
"externalId": "trial_acct_42",
"tags": ["lifecycle"],
"payload": {"accountId": "acct_42"},
"attempt": 1
}Retries retryable failures automatically. Your receiver should store or otherwise deduplicate the idempotency key.
An ambiguous outcome becomes UNCERTAIN instead of risking another automatic send. You decide whether to redrive.
04 / Endpoint routing
Create one default endpoint, then optional routes for event tags. A tag-specific match wins; the default catches everything else.
jscheduler endpoints create --url https://example.com/hooks
jscheduler endpoints create --tag billing --url https://billing.example.com/hooks
jscheduler endpoints list05 / Recovery
Delivery history includes status, attempts, completion time, and the last receiver or network error.
jscheduler events deliveries <event-id>
jscheduler events redrive <event-id> <delivery-id>Only FAILED or UNCERTAIN deliveries can be redriven. The operation keeps the same occurrence id so receiver-side deduplication remains valid.
06 / Tenant API surface
/endpointsList endpoint routes
/endpointsCreate an endpoint route
/endpoints/{endpointId}Delete a route
/scheduled-eventsList and search events
/scheduled-eventsCreate an event
/scheduled-events/{id}Read event state
/scheduled-events/{id}/disablePause future occurrences
/scheduled-events/{id}/enableResume an event
/scheduled-events/{id}/executionsRead execution history
/scheduled-events/{id}/deliveriesRead delivery history
/scheduled-events/{id}/deliveries/{deliveryId}/redriveRetry terminal delivery
Ready for the clock?