Skip to content

24 API Design

Anubha Parashar edited this page Oct 10, 2026 · 1 revision

The HealthBook AI API (internal code name: BabyCare) is a JSON-over-HTTPS REST API served by one FastAPI application. The web app, the Android app, the home camera worker, the external scheduler and the public doctor-share page all use it. The route decorators define 187 handlers: 34 in api/main.py and 153 across twelve routers. This page describes the conventions they share and catalogues the endpoints by domain.

Responsibilities

  • Give every family profile a predictable, scoped address space: /api/patients/{pid}/....
  • Make writes safe to retry (idempotency keys, client keys) and safe under concurrent caregivers (version checks).
  • Use status codes consistently, so the clients can tell validation errors, conflicts and throttling apart.
  • Never return secrets or storage internals. as_json strips password and token hashes, storage_name, sha256 and extracted_cipher.

Conventions

Topic Rule
Prefix Everything is under /api. Password reset lives under /api/auth/password-reset. The static web app is served from /.
Profile-scoped collections /api/patients/{pid}/<collection> for create and list. The handler calls own_patient(db, user, pid) first.
Resource paths /api/<resource>/{id} for read, update and actions (/api/medicines/{mid}/confirm, /api/hospital-visits/{vid}/reschedule). own_resource derives the profile from the row's patient_id.
Actions State changes are POST .../<verb>: confirm, stop, verify, withdraw, reschedule, disable, action. Entries are withdrawn, not DELETEd, wherever history matters.
Auth: mobile Authorization: Bearer <token>, returned by /api/auth/login with client: "mobile".
Auth: web client: "web" sets the babycare_session cookie (HttpOnly, SameSite=Strict, Secure in production, 14 days). Every non-GET cookie request must send X-Requested-With: BabyCare, or it gets 403 CSRF check failed.
Other credentials X-Scheduler-Key (internal scheduler), X-Camera-Worker-Key (camera worker), X-Share-Pin (doctor link PIN).
Local clock times Appointment and administration times are naive local times in the profile's timezone. A UTC suffix gets 422, and nonexistent or ambiguous DST times are rejected.
Idempotency medication_events.idempotency_key is unique per medicine, and replaying the key returns the existing event. treatment_administrations.idempotency_key and antibiotic_administrations.idempotency_key are globally unique, and reusing a key on another visit gets 409. Daily Care and vitals entries accept a client_key, and a duplicate returns the existing row with existing: true.
Optimistic concurrency PUT /api/documents/{did}/review and POST .../review/confirm carry version. The update runs WHERE version = :v AND status = 'needs_review', and a lost race gets 409 "Another caregiver changed this review. Reload it." Other mutable rows increment version on every change.
Downloads Binary responses set Content-Disposition. X-Document-Count is exposed for share ZIPs. Mobile clients can use GET variants that take a base64url spec.

Status code semantics

Code Meaning in this API
400 Malformed input, a damaged or password-protected file, or a source document from another profile
401 No session, invalid or expired session, wrong camera worker key, missing or incorrect share PIN
403 CSRF header missing, origin not allowed, read-only caregiver writing, non-guardian action, scheduler key rejected
404 Not found, including profiles the caller cannot access (existence is not revealed)
409 Conflict: duplicate upload (sha256 or source_ref), possible duplicate vaccine dose (the response lists the candidates; resend with duplicate_confirmed), review already confirmed or changed, event against an unverified medicine, idempotency key reuse, device registered to another account
410 Doctor link expired or revoked
413 / 415 File or body too large; unsupported file type
422 Validation failed, including domain rules (source document required before confirmation, dates out of range or in the future). Review confirmation returns {message, errors:[{row, page, field, reason}]}.
429 Rate limit (Retry-After: 60), or 8 failed PIN attempts on a doctor link within 15 minutes
502 / 503 Upstream vision provider failed; storage, OCR, push or email unavailable. Nothing is saved partially.

Request lifecycle

sequenceDiagram
    participant C as Client
    participant M as Middleware
    participant A as require_user
    participant H as Handler
    participant D as Database
    C->>M: POST with cookie and X-Requested-With
    M->>M: origin check, rate window, size limit
    M-->>C: 429 plus Retry-After when throttled
    M->>A: forward request
    A->>D: look up session by token hash
    A->>H: user with write flag
    H->>D: own_patient check then validation
    H->>D: UPDATE where version matches
    D-->>H: rowcount
    H-->>C: 200, or 409 when version changed
Loading

Endpoint catalogue

Paths are relative to /api. {pid} is a profile id. Methods are listed as they appear on the decorators.

Domain Endpoints
Auth POST auth/register, POST auth/login, POST auth/logout, GET me, POST auth/password-reset/request (202, generic answer), POST auth/password-reset/check, POST auth/password-reset/confirm, POST account/delete
Profiles and family POST/GET patients, PATCH patients/{pid}, GET profiles/options, GET/PATCH patients/{pid}/profile, PUT patients/{pid}/modules, POST patients/{pid}/invitations, POST invitations/accept, GET patients/{pid}/family, DELETE patients/{pid}/family/{access_id}
Documents POST/GET patients/{pid}/documents, PATCH documents/{id}, GET documents/{id}/download, GET documents/{did}/pages/{page}, GET documents/{did}/thumbnail, POST documents/{did}/signed-access, GET files/{ticket}, GET documents/{did}/links
OCR and review POST documents/{id}/extract, GET documents/{id}/extraction, GET/PUT documents/{did}/review, POST documents/{did}/review/confirm, GET ai/provider, POST documents/{did}/vision-extract (consent required)
Medicines POST/GET patients/{pid}/medicines, GET/PATCH medicines/{mid}, POST medicines/{mid}/confirm, GET medicines/{mid}/revisions, POST medicines/{mid}/events, POST medicines/{mid}/stop, GET patients/{pid}/medication-history
Vaccines GET/POST patients/{pid}/vaccines, PATCH vaccines/{vid}, GET patients/{pid}/vaccine-reference, POST patients/{pid}/vaccine-reference/import, GET patients/{pid}/vaccination-chart, GET patients/{pid}/vaccination-chart.csv
Labs POST/GET patients/{pid}/observations, GET patients/{pid}/lab-trends, GET patients/{pid}/lab-series, GET patients/{pid}/labs.csv
Admissions and visits POST/GET patients/{pid}/admissions, PATCH admissions/{aid}, POST/GET patients/{pid}/hospital-visits, PATCH hospital-visits/{vid}, POST patients/{pid}/hospital-visit-series, POST hospital-visits/{vid}/reschedule, POST hospital-visits/{vid}/administrations, GET patients/{pid}/administrations
Episodes POST/GET patients/{pid}/episodes, GET patients/{pid}/episode-comparison
Growth POST/GET patients/{pid}/growth
Vitals POST/GET patients/{pid}/vitals, GET patients/{pid}/vitals/summary, PATCH vitals/{eid}, POST vitals/{eid}/withdraw
History, timeline, Ask GET patients/{pid}/today, GET patients/{pid}/timeline, GET patients/{pid}/search, GET patients/{pid}/dashboard, GET patients/{pid}/history, POST patients/{pid}/ask, GET patients/{pid}/doctor-summary, GET patients/{pid}/record-revisions, GET patients/{pid}/audit (guardian)
Daily Care (generic) POST/GET patients/{pid}/care/{kind}, PATCH care/{kind}/{eid}, POST care/{kind}/{eid}/withdraw, GET care/{kind}/{eid}/history. Each kind is one of the typed journal schemas (fluid, diaper, stool, medicine, symptom, activity, sleep).
Daily Care (views) GET patients/{pid}/care/day, PUT patients/{pid}/care/day/{day}/note, GET .../care/timeline, GET .../care/calendar/month, GET .../care/calendar/week, GET .../care/analytics, GET .../care/illnesses, GET .../care/compare, GET .../care/export, GET/PUT .../care/settings, POST .../care/ask, POST .../care/medicine/quick, GET .../care/medicines/today
Stool photos POST care/stool/{eid}/photos, POST/GET patients/{pid}/care/stool/intake, GET patients/{pid}/care/stool/photos, GET care/stool-intake/{iid}/image, POST care/stool-intake/{iid}/confirm, DELETE care/stool-intake/{iid}, GET/DELETE care/stool-photos/{photo_id}, POST care/stool/{eid}/observation-review
Lifetime GET patients/{pid}/lifetime/{dashboard,fever,antibiotics,illnesses,ecoli,correlation,scan,review-tables,summary,evidence,parent-entries}, POST patients/{pid}/lifetime/{evidence,fever,antibiotics,parent-entries,import-transcription,ask}, PATCH lifetime/fever/{fid}, POST lifetime/fever/{fid}/verify, PATCH lifetime/antibiotics/{cid}, POST lifetime/antibiotics/{cid}/verify, POST lifetime/antibiotics/{cid}/administrations, PATCH lifetime/parent-entries/{eid}, POST lifetime/parent-entries/{eid}/withdraw, GET lifetime/drug-check
Export GET export/presets, POST patients/{pid}/export/preview, POST/GET patients/{pid}/export/download, GET patients/{pid}/export/debug.txt, GET patients/{pid}/export (guardian ZIP of all records and originals)
Share with Doctor GET share/presets, POST patients/{pid}/share/preview, POST/GET patients/{pid}/share/package.zip, POST/GET patients/{pid}/share/summary.pdf, POST/GET patients/{pid}/share/links, GET share/links/{sid}/log, DELETE share/links/{sid}
Public doctor link GET share/public/{token}, GET share/public/{token}/document/{n}, GET share/public/{token}/summary.pdf, GET share/public/{token}/package.zip. No session; token plus optional X-Share-Pin.
Reminders, notifications, devices GET patients/{pid}/reminders, GET patients/{pid}/notifications, POST notifications/{nid}/action (acknowledge or snooze), POST/DELETE devices, DELETE devices/{did}, GET push/web/config, POST/DELETE push/web/subscribe
Camera GET/POST patients/{pid}/cameras, PUT/PATCH/DELETE cameras/{cid}, POST cameras/{cid}/{disable,test,worker-key,purge-recordings}, GET cameras/{cid}/preview, GET cameras/{cid}/worker-config and POST cameras/{cid}/worker/ingest (worker key), GET patients/{pid}/camera-observations, POST camera-observations/{oid}/review, POST camera-observations/{oid}/add-to-journal, GET patients/{pid}/camera-analytics
Internal scheduler POST internal/scheduler/tick, GET internal/status. Both require an X-Scheduler-Key of at least 24 characters; the feature returns 404 when no key is configured.
Health GET health. It skips the rate limiter and the database and returns {ok, mode, medical_device: false}.

Clinical safety rules in the API shape

  • POST documents/{id}/extract only ever sets needs_review. OCR-extracted ≠ clinically verified, and OCR never activates reminders.
  • POST medicines/{mid}/confirm requires a linked source document and doctor-written instructions. Any PATCH returns the medicine to draft.
  • PATCH hospital-visits/{vid} changes appointment status only. A treatment administration is a separate endpoint that requires a source document.
  • Vaccine reference imports create unconfirmed rows only, and no reminders are generated until a row is confirmed against a card.
  • POST notifications/{nid}/action acknowledges or snoozes a notification; it never records a dose.

Implementation

api/main.py, api/workflows.py, api/care_api.py, api/lifetime_api.py, api/share.py, api/camera_api.py, api/history_api.py, api/export_api.py, api/vitals_api.py, api/profiles_api.py, api/providers.py, api/cloud.py, api/password_reset.py, api/security.py

Related pages

Backend Architecture · Authentication and Session Security · Family Profile Isolation · OCR and Human Verification Workflow · Share With Doctor Architecture · Security and Privacy Model

Clone this wiki locally