The napnap API: a baby sleep log with an open API

napnap was written API-first, and not as a selling point: the web app is a client of the same API you can use. If a screen needs something the API cannot answer, the fix goes in the API.

How you get in

From the browser, with the session cookie the emailed link leaves behind. From outside, with one key per home in the Authorization: Bearer header.

The home is always named by the session or the key, never by the request: there is no home id in any URL, because a number in a URL is a number somebody is going to swap for their neighbour's.

What can be read

GET /api/v1/me gives the account and its babies. GET /api/v1/babies/<id>/state returns the whole of today's screen in a single response: the prediction, the day's plan and the notes.

GET .../forecast?days=7 gives the days that have not arrived with their margin; .../feeds the feeds with their averages; .../food the solids plan. And GET /api/v1/config publishes the model's constants, which is what stops the documentation from falling behind.

What can be written

POST .../toggle is the button. POST, PATCH and DELETE over .../sleeps correct or add a sleep; .../feeds/start, /switch and /stop run the stopwatch for feeds.

The rules live on the server: only one sleep open at a time, the end after the start, and the waits by age for food are refused with the reason rather than with a plain «no».

And errors are keys, not sentences

An error arrives as {"error": "sleep.end.before_start"}. The server says what happened and the client says it in whatever language it speaks.

It is the same reason the model's notes travel as a key and its blanks rather than as text: a second language is one more file, not a second version of the server.

Questions

Is the API free?
Yes, and there is no paid plan. There is a cap on sign-in links per address per hour so the door cannot be used to send mail to anybody, and nothing else.
Can I get my data out?
Yes. The API returns all of it as JSON, and what you record is yours.