nano-api / relay
Cron, without a machine
to keep alive
A cron expression, a timezone and a URL. It retries, keeps the run history, and posts to your webhook when the endpoint starts failing. The timezone is the part I got tired of getting wrong by hand.
Free. Signup is one curl and the key comes back in the response. No form, no
card, nobody to ask.
0 * * * * · Europe/Oslo POST /jobs/sync - 03:00 → 200 412ms
- 04:00 → 200 388ms
- 05:00 → 500 attempt 1/3
- 05:00 → 500 attempt 2/3
- 05:00 → 500 attempt 3/3
Creating a schedule
curl -X POST https://relay.nano-api.com/v1/schedules \
-H "Authorization: Bearer $NANO_API_KEY" \
-H 'content-type: application/json' \
-d '{
"slug": "nightly-report",
"cron": "0 3 * * *",
"timezone": "Europe/Oslo",
"url": "https://api.example.com/jobs/nightly-report"
}'
Optional: body, headers, timeout_seconds,
max_attempts, alert_webhook_url. Test it with
POST /v1/schedules/:slug/run.
03:00 means 03:00, in March and in November
Platform crons run in UTC, so a 03:00 job quietly moves twice a year. Relay evaluates the expression in the zone you name.
UTC-only cron
- Drifts an hour twice a year
- Skips the run when the local hour does not exist
- Can run twice on the ambiguous hour
NanoRelay
0 3 * * *inEurope/Oslostays at 03:00- A missing hour runs just after the gap
- An ambiguous hour runs once, on its first instant
All three are pinned by tests in the repo.
When the call fails
- 1
Retry
Three attempts, 2s and 6s backoff, each bounded by your timeout.
- 2
Alert on the change
Once when it breaks, once when it recovers. Never one per failed run.
- 3
Keep the evidence
Status code, duration, attempts, and the start of the response body.
Delivery is at-least-once, so make the endpoint idempotent. Every request carries
X-NanoRelay-Run-Id. Missed slots are skipped, not replayed: no catch-up
stampede after an outage.
Using it with the others
Take a Lock at the top of the job and ping Pulse at the end. Then a scheduler that dies quietly is still an alert.