The API

Everything the app does goes through here, so everything the app does you can do yourself. There is no cut-down version for outsiders: it is the same door.

The base

https://napnap.es/api/v1

The key

It is created in Settings → This device → Shortcuts, and it is shown once: all that is kept here is its hash. It travels in the header, never in the address — a key in a URL ends up in a log, in a history and in somebody's address bar.

Authorization: Bearer nap_…

A key belongs to one home. A request never has to say which home it is for: that follows from the key, and it is why somebody else's baby cannot be asked for by typing their id.

With Siri, in two steps

An iPhone shortcut knows how to ask for an address, send a header and read what comes back. That is all it takes: «Hey Siri, how is the little one doing» is these two lines.

curl -H "Authorization: Bearer $NAP" \ https://napnap.es/api/v1/say Aurora lleva 1:52 despierta. Le toca siesta sobre las 19:30.

The voice door answers in plain text, which is what a shortcut speaks. Add «?format=json» if you would rather read it yourself.

When something goes wrong

The HTTP code says what happened and the body always has the same shape: a key, not a sentence. The server says what failed and whoever calls it says so in whatever language they speak.

{ "error": "baby.unknown" }

400
what you sent does not hold up
401
no key, or the key no longer works
403
the key works but not for this
404
that does not exist, or it is not your home's
409
the screen was behind: somebody got there first

The doors

They all hang off /api/v1. The marked ones are the ones really used from outside; the rest are here because the app uses them and there is no reason to hide them from you.

79 doors in 10 groups.

Getting in

POST/auth/link
Sends a sign-in link and an eight-character code to an inbox. Five per address per hour.
POST/auth/session
Trades that code for a session. It is the only way into the installed app, which has a cookie jar of its own.
DELETE/auth/session
Closes the session on this device and only this one.
POST/auth/handoff
Mints a one-time code for handing the session to the installed app without going back to your inbox. Only from a browser session: an API key that handed out sessions would stop being bounded.
GET/me
Who you are, which homes are yours and which babies are in them. It is the first call the app makes.
PATCH/me
Changes this person’s language: `es` or `en`. It is what decides which language their emails and alerts arrive in, and which half of the forum they see — not the address they happen to be calling from.

The baby and their day

GET/babies
The babies in your homes.
POST/babies
Registers a baby: name and date of birth.
GET/babies/{baby}
One baby and their settings.
PATCH/babies/{baby}
Changes name, birth, bedtime, early warning, alerts, night silence or what gets recorded about each feed.
DELETE/babies/{baby}
Archives them. It does not delete them: a year of somebody's nights does not vanish because a button got tapped at four in the morning.
GET/babies/{baby}/statethe one you want
The whole day exactly as the app draws it: the forecast, what has been slept, this household's night and the notes. If you are only going to call one thing, call this.
GET/babies/{baby}/forecast
Up to two weeks ahead, each day with its margin and how much confidence is behind it.
GET/babies/{baby}/pulse
A short string that changes whenever anything about this baby changes. It is what the other screen watches to find out, every ten seconds and only while somebody is looking at it.
GET/babies/{baby}/week
The seven finished days, summed up: how much they slept on average, how many naps, how the window moved and which foods were tried for the first time.
GET/babies/{baby}/export
Everything recorded, for taking with you: `format=json` gives the lot, `format=csv&what=sleeps|feeds|food|measurements` gives one table.
GET/babies/{baby}/report
A page ready to print with what a check-up asks about: two weeks of sleep, measurements with their centile, how solids are going and the reactions. With `format=pdf` it downloads as a PDF.
GET/babies/{baby}/alerts
Which alerts this home wants: one per kind, with who it belongs to (the baby or you) and whether it is on. The baby's are shared by both phones in the house; yours are yours.
PUT/babies/{baby}/alerts
Turns alerts on or off. Send only the ones you want to change —`{"alerts":{"week":false}}`— and the rest stay as they were. «notify» is still the master switch and outranks all of them.

The button and sleep

POST/babies/{baby}/togglethe one you want
The button. One tap puts them down, another wakes them, and which of the two it is the server decides by looking at whether a sleep is open. Send «expect» with what you thought and it answers 409 instead of rewriting the night if somebody got there first. Two taps in the same minute are an undo, not a waking.
GET/babies/{baby}/sleeps
The sleeps recorded.
POST/babies/{baby}/sleeps
Records a whole sleep, for when nobody had a hand free.
PATCH/babies/{baby}/sleeps/{sleep}
Corrects the times, the kind or the note of a sleep.
DELETE/babies/{baby}/sleeps/{sleep}
Deletes a sleep.

Feeds

GET/babies/{baby}/feeds
The whole feeds screen: the averages, the chart and what has been recorded.
POST/babies/{baby}/feeds
Records a feed that has already happened.
POST/babies/{baby}/feeds/startthe one you want
Starts a feed on whichever side you say. In «side only» mode this same door opens and closes it at once.
POST/babies/{baby}/feeds/switch
Switches sides: closes what was running on one and opens the other.
POST/babies/{baby}/feeds/stopthe one you want
Ends the feed and squares the split against the clock.
PATCH/babies/{baby}/feeds/{feed}
Corrects a feed.
DELETE/babies/{baby}/feeds/{feed}
Deletes a feed.

Solids

GET/babies/{baby}/food
The whole year's plan, the catalogue of 92 foods, what has been tried and how the texture is going.
PUT/babies/{baby}/food/settings
When they started and in what style: blended, pieces or both.
PUT/babies/{baby}/food/plan
Moves a food to another week. Everything can be moved except the waits that go by age.
PUT/babies/{baby}/food/avoid
Withdraws a food for good —a confirmed allergy— or puts it back. It comes out of the weeks still to come and out of the example meals.
POST/babies/{baby}/food/logs
Records a meal: what was offered, how much went in and how it went down.
PATCH/babies/{baby}/food/logs/{log}
Corrects a recorded meal.
DELETE/babies/{baby}/food/logs/{log}
Deletes a recorded meal.
GET/babies/{baby}/photos
The photos on a meal, with links that work and nothing about the store.
POST/babies/{baby}/photos
Uploads a photo and hangs it off whatever you say.
DELETE/babies/{baby}/photos/{photo}
Deletes a photo.

Weight, length and head

GET/babies/{baby}/measurements
The measurements recorded, each with its WHO centile and what was gained since the one before.
POST/babies/{baby}/measurements
Records a measurement. In whole grams and millimetres: `weightG`, `heightMm`, `headMm`.
PATCH/babies/{baby}/measurements/{measurement}
Corrects a measurement. Whatever you do not send stays as it was; send `null` to empty a number.
DELETE/babies/{baby}/measurements/{measurement}
Deletes a measurement.

Questions between homes

GET/community/presence
How many homes are awake right now, rounded and only in the small hours. A number: there is no list and nobody to write to.
GET/community/feed
The questions: `scope=near` for babies the age of yours, `all` for everything, `mine` for yours. It comes with your handle and with what would be attached to a question of yours.
POST/community/questions
Asks everybody else. Your context is attached unless you say `context: false`.
GET/community/questions/{question}
One question with its answers.
POST/community/questions/{question}/answers
Answers. `publish: true` gives permission for your answer to leave the app if it is marked as the one that helped.
POST/community/questions/{question}/metoo
«This happens to us too», once per person. Call it again to take it back.
POST/community/questions/{question}/close
Marks the answer that helped and closes the thread. `publish` is your permission to publish it outside; `reopen: true` opens it again.
POST/community/questions/{question}/withdraw
Withdraws your permission: if you are the one who asked, the whole public page goes; if you answered, your answer drops out of it.
DELETE/community/questions/{question}
Deletes your question with its answers and its photos. Only whoever asked, or whoever moderates.
DELETE/community/answers/{answer}
Deletes your answer. If it was the one that solved the thread, the thread reopens and stops being published.
POST/community/reports
Reports a question or an answer.
PUT/me/handle
Changes your handle.
GET/community/stats
What babies that age do according to what is recorded on napnap: the window and the naps. It does not answer unless there are at least twenty homes in the band.
GET/community/questions/{question}/photos
The photos on a question, with links that expire.
POST/community/questions/{question}/photos
Adds photos to your question, up to three. Only whoever asked, and they never appear on the thread's public page.
GET/community/answers/{answer}/photos
The photos on an answer.
POST/community/answers/{answer}/photos
Adds photos to your answer, up to three. Only whoever wrote it, and they do not appear on the public page either.
GET/notifications
The news that is about you: who has answered your questions and who found your answer useful.
POST/notifications
Marks the news as seen. The app does this when the bell is opened.
GET/moderation/queue
The review queue: what is hidden after reports, what a rule flagged and what is waiting to be published. Only for whoever moderates.
POST/moderation/act
Hide, show again, publish or unpublish. Every decision is written down with who took it.

Alerts

GET/push
The public VAPID key, which is what a browser needs in order to subscribe.
GET/devices
The phones subscribed to this household's alerts.
POST/devices
Registers this subscription. If the same phone signs into another account it takes it along instead of sitting there receiving the previous account's alerts.
POST/devices/{device}/test
Sends a test alert to a phone and tells you what it actually answered. A button that says «sent» when Apple replied 403 is worse than no button.
DELETE/devices/{device}
Takes a phone off the alerts.

The home and the keys

GET/home/people
Who can open this home.
POST/home/people
Adds an address to the list. It is not a pending invitation: whoever asks for a link from it gets in, even months later and even on a different phone.
DELETE/home/people/{person}
Takes the address off and, with it, the access. A revoke that leaves the door open is not a revoke.
GET/tokens
Your keys, by their first few characters. The secret cannot be read again.
POST/tokens
Creates a key. The secret is shown once and that is that.
DELETE/tokens/{token}
Revokes a key.

For shortcuts and for the curious

GET/saythe one you want
A sentence already written, in plain text, about how things are going. It is meant to be read out loud by a shortcut: the app decides what gets said, not the shortcut, so that changing the model does not mean going back to the iPhone.
GET/config
The model's constants. The one door with no session, because there is nothing of anybody's here.