← Blog

Baby Tracker API: Log Sleep and Feeds From Your Own Code

The bottle is warm and the baby has finally settled on your shoulder. The phone with the tracking app is, of course, charging in the other room. Meanwhile there's a Raspberry Pi humming in the hall closet, and some stubborn part of your brain is already thinking: I could just send a POST request.

You can. nappi has a public REST API that any parent with nappi Premium can use with their own family's data. You make a personal key, send it with each request, and your scripts can log diapers, bottles, nursing, pumping, sleep, activities and growth, start and stop timers, and read the latest entries. The full spec is public at https://api.nappi.app/v1/openapi.json.

Does nappi have an API?

Yes. The base URL is https://api.nappi.app/v1, and every call is plain HTTPS with JSON going in and coming out.

The API is described by an OpenAPI 3.1 document, the standard, language-agnostic format for describing HTTP APIs.1 Point a code generator or Postman at the spec and you get a working client without guessing field names.

If you'd rather click around than read JSON, the interactive API reference shows every endpoint with examples. Reading it doesn't require an account. Signing in only lists your keys in the try-it panel, so you can send real requests from the page.

The API is still marked beta, so request shapes may change as we learn how families use it. The reference is generated from the live API, which means it always matches what's deployed.

How do you get a nappi API key?

Keys are made on the web, not in the app:

  1. Sign in at nappi.app/app/connections, ideally on a computer.
  2. Give the key a name you'll recognize later ("nursery Pi", "kitchen dashboard") and pick how long it lasts: 30 days, 90 days or 1 year.
  3. Copy it. It starts with nappi_, and you'll only see it once.

Every request sends it in the Authorization header as Bearer nappi_YOUR_KEY, the bearer-token format defined in RFC 6750.2 Whoever holds a bearer token can use it, so treat yours like a password.

A few rules before you build anything:

  • The API is part of nappi Premium. One subscription covers the whole household, and keys stop working while the family doesn't have Premium.
  • Only caregivers can make keys. Viewers and guests can't.
  • You can hold up to 10 keys at a time.
  • We email you a week before a key you're using expires.

What can the nappi API do?

Eight endpoints, all limited to the babies in your household:

Method Path What it does
GET /v1/babies Lists your babies and their IDs
GET /v1/babies/{babyId}/entries/latest Latest entry of each type
GET /v1/babies/{babyId}/entries/latest/{type} Latest entry of one type
POST /v1/babies/{babyId}/entries Logs a finished entry
GET /v1/babies/{babyId}/timers Sleep, nursing and pumping timers running now
GET /v1/babies/{babyId}/status Timers and latest entries in one read
POST /v1/babies/{babyId}/timers/{timerType}/start Starts a timer
POST /v1/babies/{babyId}/timers/{timerType}/stop Stops a timer and saves the entry

What's missing matters too. You can't log medication or solids yet, though you can read the latest of each. And the API only returns the newest entry per type, not your whole history, with no way to edit or delete an entry.

Log your first entry with curl

Start by finding your baby's ID:

curl https://api.nappi.app/v1/babies \
  -H "Authorization: Bearer nappi_YOUR_KEY"

You get back an array:

[
  {
    "id": "BABY_ID",
    "name": "Phoebe",
    "birth_date": "2026-05-02",
    "timezone": "America/New_York"
  }
]

Then log a wet diaper:

curl -X POST https://api.nappi.app/v1/babies/BABY_ID/entries \
  -H "Authorization: Bearer nappi_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"type": "diaper", "diaper_type": "wet"}'

A 201 means it's logged, and the body tells you what was created:

{ "id": "ENTRY_ID", "type": "diaper", "duplicate": false }

The Idempotency-Key header is optional. We'd still never leave it out of an automation. If a dropped connection makes your script retry with the same key, the second request returns 200 with "duplicate": true and nothing new is written, so you don't end up with two diapers.

An entry from the API is an ordinary nappi entry. Everyone in your household sees it in the app, and it's attributed to you, the person who made the key.

Times are ISO 8601 with a UTC offset, like 2026-10-21T14:30:00-04:00, and default to now. Amounts are in milliliters unless you send "unit": "oz".

Which entry types can you log?

POST /entries takes a type plus whatever fields that type needs:

type Required Optional
diaper diaper_type: wet, poo, mixed or dry time
potty outcome: potty, accident or sat_dry time
bottle nothing else amount, unit (ml or oz), bottle_type (such as breast_milk or formula), time
nursing nothing else side, left_minutes, right_minutes, duration_minutes, time
pumping nothing else amount, left_amount, right_amount, unit, duration_minutes, time
sleep start_time, end_time sleep_type (nap or night)
activity activity_type (such as bath or tummy_time) duration_minutes, time
growth nothing else weight, weight_unit (kg or lb), length, head, length_unit (cm or in), time

A 4-ounce bottle of formula looks like this:

{ "type": "bottle", "amount": 4, "unit": "oz", "bottle_type": "formula" }

Leave out sleep_type and nappi decides between nap and night from the baby's day hours, the same way the app does. For something that's still happening, like a nap in progress, use a timer.

Start and stop a sleep timer from a script

Timers are the shared ones your whole household sees in the app. To start a nap:

curl -X POST https://api.nappi.app/v1/babies/BABY_ID/timers/sleep/start \
  -H "Authorization: Bearer nappi_YOUR_KEY"

Stopping it saves the sleep entry, exactly as stopping it on the phone would:

curl -X POST https://api.nappi.app/v1/babies/BABY_ID/timers/sleep/stop \
  -H "Authorization: Bearer nappi_YOUR_KEY"

timerType can be sleep, nursing or pumping. Starting a timer that's already running changes nothing and returns it with "status": "already_running". Stopping when nothing is running returns 409 with the code timer_not_running, which makes a single toggle button easy to build.

It works in both directions. GET /timers also returns timers someone started on a phone, a watch or with Alexa. Nursing timers accept an optional side, and you can backdate a start by up to 48 hours with start_time.

A small script: time since the last feed

This Node script (Node 18 or newer, no packages) prints how long ago the baby last ate, counting bottles and nursing. Save it as last-feed.mjs and run node last-feed.mjs:

const KEY = "nappi_YOUR_KEY";
const BABY = "BABY_ID";

const res = await fetch(
  `https://api.nappi.app/v1/babies/${BABY}/status?types=bottle,nursing`,
  { headers: { Authorization: `Bearer ${KEY}` } },
);
if (!res.ok) throw new Error(`nappi returned ${res.status}`);
const { timers, latest } = await res.json();

const feeds = [latest.bottle, latest.nursing].filter(Boolean);
if (timers.some((t) => t.type === "nursing")) {
  console.log("Nursing right now");
} else if (feeds.length === 0) {
  console.log("No feeds logged yet");
} else {
  const last = Math.max(...feeds.map((f) => new Date(f.time).getTime()));
  const min = Math.round((Date.now() - last) / 60000);
  console.log(`Last feed ${Math.floor(min / 60)}h ${min % 60}m ago`);
}

Hook it up to a cron job and an e-ink screen on the fridge, and nobody has to unlock a phone at 3 AM to work out when the last bottle was.

Polling without hitting the rate limit

Each key gets 12 reads and 30 writes per minute. Go past that and you get 429 Too Many Requests, with a Retry-After header saying how many seconds to wait.34

For a dashboard, poll /status no more than once a minute. Its responses carry an ETag. Send it back as If-None-Match and you get 304 Not Modified, with no body, until something changes.4

There's one exception. While a timer is running, its elapsed time changes every second, so /status always returns a full 200.

iPhone Shortcuts: log a bottle in one tap

No computer needed for this one. In the Shortcuts app, add a Get Contents of URL action and set it up like this:

  • URL: https://api.nappi.app/v1/babies/BABY_ID/entries
  • Method: POST
  • Headers: Authorization set to Bearer nappi_YOUR_KEY
  • Request Body: JSON, with type set to bottle, amount to 120 (as a Number) and unit to ml

Switching the method to POST is what adds the Request Body field, and JSON is one of its options.5 Put the shortcut on your Home Screen, or add an Ask for Input step first so you can type the amount each time.

The nappi app already handles voice logging with Siri. This route is for the custom stuff, like a one-tap "120 ml formula" button or an automation that runs when your phone touches an NFC sticker on the bottle drying rack.

Home Assistant: the integration or plain REST commands

If Home Assistant runs your house, start with the integration. It's open source under the MIT license (nappi-app/nappi-home-assistant on GitHub), and you'll find it in the HACS default store by searching for "nappi". It polls /status once every 2 minutes per baby and gives you log buttons, timer switches and last-entry sensors without touching YAML. Our Home Assistant setup guide covers the install step by step, along with a few automations worth copying.

Prefer YAML? Home Assistant's RESTful Command integration can call the API directly, with your own headers and JSON payload.6 These two commands start and stop a nap:

# secrets.yaml
nappi_auth: "Bearer nappi_YOUR_KEY"

# configuration.yaml
rest_command:
  nappi_sleep_start:
    url: "https://api.nappi.app/v1/babies/BABY_ID/timers/sleep/start"
    method: post
    headers:
      Authorization: !secret nappi_auth
  nappi_sleep_stop:
    url: "https://api.nappi.app/v1/babies/BABY_ID/timers/sleep/stop"
    method: post
    headers:
      Authorization: !secret nappi_auth

Call rest_command.nappi_sleep_start from a button by the crib, and the nap timer starts on every phone in the family. The smart home page lists the other ways to connect, including Alexa and Google Home.

Is it safe to give a script access to my baby's data?

Nothing can read your family's data through the API until you make a key. Each key belongs to one caregiver in one household, and nappi stores only a SHA-256 hash of it. That's why you see the key once and never again.

You can revoke a key anytime at nappi.app/app/connections, or in the app under Settings → Connections → Smart home. A key also stops working when it expires, or if you leave the household or become a viewer.

A key can log and read for your family the way you can in the app, timers included. It can't change your account or see your password. Keep it out of public Git repos and screenshots, and revoke it the moment it leaks.

Try it tonight: make a 30-day key, run the /babies curl, and log one test diaper. When it pops up on your partner's phone, delete it there, since the API can't.

Frequently asked questions

Does the nappi API cost extra?

There's no separate charge, but the API is part of nappi Premium. One subscription covers everyone in your household. Reading the docs and the OpenAPI spec is free for anyone.

Can I export my full history through the API?

No. The API returns the latest entry of each type and the running timers. For your complete history, use the CSV export in the nappi app.

Does it work with twins or siblings?

Yes. GET /v1/babies returns every baby in your household, and every other call names one baby by its ID. Run your script once per baby.

Can I log medication through the API?

Not yet. You can read the latest medication entry, but logging medication or solids isn't supported, so keep using the app for those.

References

1. OpenAPI Initiative. "OpenAPI Specification v3.1.0." 2021. spec.openapis.org

2. Jones M, Hardt D. "The OAuth 2.0 Authorization Framework: Bearer Token Usage." RFC 6750, IETF, 2012. RFC Editor

3. Nottingham M, Fielding R. "Additional HTTP Status Codes." RFC 6585, IETF, 2012. Section 4, 429 Too Many Requests. RFC Editor

4. Fielding R, Nottingham M, Reschke J, eds. "HTTP Semantics." RFC 9110, IETF, 2022. Sections 8.8.3 (ETag), 10.2.3 (Retry-After), 13.1.2 (If-None-Match) and 15.4.5 (304 Not Modified). RFC Editor

5. Apple. "Request your first API in Shortcuts on iPhone or iPad." Shortcuts User Guide. Apple Support

6. Home Assistant. "RESTful Command." Home Assistant integrations documentation. home-assistant.io

Try nappi free

Track sleep, feedings, diapers, and more, in seconds.