Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.
Get an API key
Free tier, no form to fill in. Signing in shares your email address with us — we
store it to create your key and to recognise you if you sign in with another
provider. See our Privacy Policy and
Terms.
openapi: 3.2.0
info:
title: Luna Discovery API
description: 'Luna is a baby tracker for feeds, sleep, nappies, solids and routines, shared between parents and invited caregivers.
This REST API is the same one the Luna web app uses. Every request is scoped to **one family**: the family is resolved from the bearer token (or session cookie) and there is no way to address another family''s data.
## Authentication
* **Bearer token** (`Authorization: Bearer `), the way agents and scripts should call the API. Create one in the app (Settings → Connect an assistant) or `POST /api/vega/token` from a signed-in session. Tokens are stored hashed and can carry `read` or `read`+`write` scopes. A `read` token may call every `GET` (and `HEAD`) route plus `POST /api/ask` (asking only; a `remember:` question saves a note and needs `write`). Any other `POST`, `PUT`, `PATCH` or `DELETE` with a token that lacks `write` returns `403 {"error": "insufficient_scope", "required_scope": "write"}`. Each operation''s `x-required-scope` says which it needs.
* **Session cookie** (`luna_session`), what the browser uses after `POST /login` or `POST /api/vega/onboard`.
Only `GET /api/health` and `POST /api/vega/onboard` are reachable without credentials. Unauthenticated calls to anything else return `401 {"error": "unauthorized"}`.
## Conventions
* Timestamps are ISO 8601 in the family''s local time (`YYYY-MM-DDTHH:MM:SS`); omit `ts` to log "now". Future timestamps are rejected.
* Volumes are millilitres, weights kilograms, lengths centimetres. Families with `units: imperial` still store metric.
* Errors are JSON `{"error": ""}` with a 4xx status.
* Luna is not a medical device: nothing here diagnoses, assesses symptoms or advises on medication.
## Other ways in
* **MCP connector** at `https://getmyluna.app/mcp` (streamable HTTP; OAuth sign-in, or the same bearer token): 23 tools, resources and prompts for Meta Muse, Claude Code and any MCP client. Manifest: `/.well-known/luna-connector.json`.
* **Agent instructions**: `/llms.txt`. **Developer portal**: `/developers`. **CLI**: `/cli/luna.py`.'
termsOfService: https://getmyluna.app/terms
contact:
name: Luna support
url: https://getmyluna.app/contact
email: hello@getmyluna.app
version: 1.1.0
servers:
- url: https://getmyluna.app
description: Production
tags:
- name: Discovery
description: Health, identity and machine-readable descriptions of Luna.
paths:
/.well-known/luna-connector.json:
get:
tags:
- Discovery
summary: MCP connector manifest
description: 'Machine-readable description of the MCP server: URL, auth, tools, resources, prompts.'
operationId: connector_manifest
responses:
'200':
description: Success
content:
application/json:
schema:
type: object
description: 'Connector manifest: name, version, mcp_url, auth, tools[], resources[], prompts[], privacy_url, terms_url.'
required:
- name
- version
- mcp_url
- auth
- tools
additionalProperties: true
security: []
/llms.txt:
get:
tags:
- Discovery
summary: Agent instructions (llms.txt)
description: When to use Luna and how to call it, in the llms.txt format. Also at `/.well-known/agent-instructions.md`.
operationId: llms_txt
responses:
'200':
description: Success
content:
text/plain:
schema:
type: string
security: []
/api/health:
get:
tags:
- Discovery
summary: Health check
description: 'Always `{"ok": true}` when the app is serving. No auth.'
operationId: health
responses:
'200':
description: Success
content:
application/json:
schema:
$ref: '#/components/schemas/OkResponse'
security: []
/api/me:
get:
tags:
- Discovery
summary: Who am I
description: The username, family id and role the current credentials resolve to. Useful for confirming a bearer token works.
operationId: whoami
responses:
'200':
description: Success
content:
application/json:
schema:
$ref: '#/components/schemas/MeResponse'
'401':
description: Missing or invalid credentials
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
security:
- bearerAuth: []
- sessionCookie: []
x-required-scope: read
components:
schemas:
MeResponse:
properties:
user:
type: string
title: User
description: Username (internal login alias; not shown to the family).
user_id:
type: string
title: User Id
description: Opaque id of this login. The app's offline queue tags each unsynced log with it, so a log is only ever sent from the session of the caregiver who made it.
family_id:
type: string
title: Family Id
role:
type: string
enum:
- admin
- member
title: Role
name:
type: string
title: Name
description: 'What the family sees: your first name, or `Family admin` / `Partner` until you set one.'
display_name:
anyOf:
- type: string
- type: 'null'
title: Display Name
description: Your first name, or null if not set yet.
needs_name:
type: boolean
title: Needs Name
description: True until you've set a first name (the app asks once).
type: object
required:
- user
- user_id
- family_id
- role
- name
- needs_name
title: MeResponse
ErrorResponse:
properties:
error:
type: string
title: Error
description: Machine-readable code (e.g. `unauthorized`, `not_found`) or a short message.
examples:
- unauthorized
message:
anyOf:
- type: string
- type: 'null'
title: Message
description: Optional human-readable detail.
type: object
required:
- error
title: ErrorResponse
description: Every error is a JSON object with an `error` code or message.
OkResponse:
properties:
ok:
type: boolean
title: Ok
default: true
examples:
- true
type: object
title: OkResponse
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: opaque
description: 'Token from Settings → Connect an assistant or `POST /api/vega/token`. Scopes: `read`, `write`. A `read` token gets `403 insufficient_scope` on any operation whose `x-required-scope` is `write`.'
sessionCookie:
type: apiKey
in: cookie
name: luna_session
description: Browser session set by `POST /login` or `POST /api/vega/onboard`.
externalDocs:
description: Developer portal
url: https://getmyluna.app/developers