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

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, 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/..."}'
alerts app
  1. Monitor nightly-backup has not pinged for 99s (expected every 30s + 30s grace). 02:06
  2. Schedule nightly-report failed: endpoint returned HTTP 500 (3 attempts). 02:07
  3. 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.

How to, in curl What this is