nano-api
Things I kept building from scratch
One thing each, done well. The old unix rule, as HTTP endpoints.
A heartbeat that shouts in Slack when a cron job goes quiet. Scheduled calls that respect a timezone. A lock with a lease. Config I can change without a deploy. A counter. I have written all of these more than once, in a hurry, and got the concurrency or the timezone wrong, or simply never noticed the job had stopped. Help yourself.
Start in curl See it running Source
curl -X POST https://pulse.nano-api.com/v1/signup \
-H 'content-type: application/json' -d '{"email":"you@example.com"}' The key is in the response body. That is the whole signup.
No client
HTTP and an Authorization header. No SDK to pin, no agent to run alongside your job.
One key
The same key works on every host. POST /v1/signup returns it. The key is the account, so there is no password anywhere.
Nothing of mine to fail
Cloudflare Workers and D1. No VM in the path, so there is no VM of mine to fall over.
Free
No card. It costs me about five dollars a month whether anyone uses it or not.
What is here now
Each has its own page: the guarantee, the cases where it does not help, and the curl.
pulse.nano-api.com NanoPulse
Your job pings on success. Miss the deadline and it posts to your webhook once, then once more when the pings come back.
Read more →relay.nano-api.com NanoRelay
Cron expressions evaluated in the timezone you name, not UTC. Three attempts with backoff, run history kept.
Read more →configmaps.nano-api.com NanoConfig
A versioned JSON document. ETag on reads, If-Match on writes, last 20 revisions kept with a note.
Read more →count.nano-api.com NanoCount
A named counter incremented in one statement, so two callers are never handed the same number. Which is exactly what an invoice sequence needs, so it does that too.
Read more →uniq.nano-api.com NanoUniq
You hand it a key you already have; it says whether that key has arrived before. Duplicate webhook deliveries stop being a problem you solve with a table.
Read more →lock.nano-api.com NanoLock
A lease with a TTL and a monotonic fence counter. Expires on its own if the holder dies mid-job.
Read more →Pulse, as the short example
One line at the end of a job you already have
The && does the work. A failed script never reaches the ping, the deadline
passes, and the sweep notices the silence within a minute.
# at the end of the job you already have
0 3 * * * backup.sh && curl -fsS -X POST \
-H "Authorization: Bearer $NANO_API_KEY" \
https://pulse.nano-api.com/v1/ping/nightly-backup One message down, one message back up
Any HTTPS webhook. The body is Slack-shaped, so a Slack hook needs no mapping. It fires on transitions, not per missed deadline, so three quiet hours is one message.
curl -X PATCH $PULSE/v1/monitors/nightly-backup \
-d '{"alert_webhook_url": "https://hooks.slack.com/services/..."}' - Monitor nightly-backup has not pinged for 99s (expected every 30s + 30s grace). 02:06
- Schedule nightly-report failed: endpoint returned HTTP 500 (3 attempts). 02:07
- Monitor nightly-backup is reporting again. 02:14
The others are the same shape: one host, one key, one job. Pulse in full, or the how-to, which runs through all of them in curl.
A screen, if you want one
Paste a key at dash.nano-api.com and you get every heartbeat, schedule, lock, config and counter on it, refreshing every 30 seconds. There is no login, because the key is already the account.
It only reads, and it insists on a key that can only read. Paste one that can write and it refuses without storing it, which is the whole reason scoped keys exist:
curl -X POST $PULSE/v1/keys \
-H "Authorization: Bearer $NANO_API_KEY" \
-d '{"name":"dashboard","scope":"read"}'
One HTML file. No framework, no analytics, nothing loaded from anywhere else, not even a
font. The key lives in sessionStorage and dies with the tab.
Something using all of them at once
A stock ticker on a small Linode runs on the whole set: Relay calls it every 15 minutes, Lock keeps that to one copy, Config holds the tickers and the threshold that decides when it wakes someone, Count tallies renders and failures, Pulse watches for it going quiet. The panel at the bottom of the page reports what each one did last cycle.
The source is readable in one sitting, with no dependencies. The shell pattern for taking a lock without a race is in there, and so is the reason it alerts from three places instead of one.
Take a key and use it
One person, evenings and weekends, in Norway. It is free because charging would commit me to a response time I cannot hold down alongside a day job. Bugs and questions reach the person who wrote the code: hello@nano-api.com or @gautes.