Build with Healify
Anna, our AI health coach, plus nutrition tracking, bloodwork analysis, DNA insights, and 150+ health metrics — all via a single REST API.
Authentication
JWT Bearer Token
All endpoints require a JWT in the Authorization header. Obtain a token via Apple Sign In or email auth. Tokens expire — use the refresh token to renew.
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
Base URLs
All endpoints are prefixed with /api. The dev environment is a full mirror of production — use it for integration testing.
Chat (Anna AI)
10 endpointsExchange a pending_confirmation nonce (issued by chat_agent when a destructive tool was first invoked) for a confirmed result. Used by the LangGraph chat_agent to complete destructive operations after explicit user consent in the mobile app.
Tracks user feedback on AI responses. Links to LangWatch traces via run_id for quality monitoring.
| Field | Type | Required | Description |
|---|---|---|---|
| message_id | string | required | Message ID the feedback is for |
| thread_id | string | optional | Thread ID of the conversation |
| rating | string | required | Thumbs up or down |
| run_id | string | optional | LangGraph run ID for trace linking |
| comment | string | optional | Optional user comment about the response |
Automatically routes to appropriate agent (chat, nutrition, goal, habit, metrics) based on message content.
| Field | Type | Required | Description |
|---|---|---|---|
| streaming | string | required | (in query) |
| message | string | required | The message content |
| type | string | optional | Message type |
| options | object | optional | |
| user_id | number | optional | Optional user ID for testing/debugging (should not be used in production) |
| agentType | string | optional | Optional agent type to route the message to a specific agent |
| language | string | optional | Override response language (e.g. "spanish"). Falls back to user profile language. |
| is_thread_end | boolean | optional | Signal that this is the last message in the session (e.g. user backgrounds app or closes chat). When true, LangWatch quality evaluators fire for this conversation turn. |
| threadId | string | optional | LangGraph thread ID for conversation continuity. Sent by the mobile client when resuming an existing thread. |
| posthog_session_id | string | optional | PostHog session recording ID for LLM trace session-replay linking |
| pillars | string[] | optional | Explicit pillar hints forwarded to Anna for deterministic routing. When set, Anna bypasses rule-based pillar classification and scopes tools/prompts to the listed pillars. |
Retrieve paginated chat history for the current user. Returns messages in reverse chronological order.
| Field | Type | Required | Description |
|---|---|---|---|
| limit | number | required | (in query) |
Clears User.threadId so the next chat message starts a fresh AgentCore session. Call this when the client wants to force a new conversation (e.g. "New chat" button).
Retrieve credible health sources for Anna's responses (App Store compliance). Returns 202 Accepted if sources are being generated in the background.
| Field | Type | Required | Description |
|---|---|---|---|
| threadId | string | required | (in query) |
Creates a new conversation thread for the user.
Retrieve paginated list of chat threads with their last message.
| Field | Type | Required | Description |
|---|---|---|---|
| limit | number | required | (in query) |
| before | string | required | (in query) |
Retrieve messages for a specific conversation thread.
| Field | Type | Required | Description |
|---|---|---|---|
| threadId | string | required | |
| limit | number | required | (in query) |
| before | string | required | (in query) |
Sends a warm sentinel to AgentCore with the real runtimeSessionId so the first real chat message skips the cold-start tax. Call on app open / login / chat-screen mount. Returns the threadId to use for the next send.
Nutrition
13 endpointsAnalyzes a food photo that was previously uploaded to S3 using a presigned URL from GET /nutrition/upload-url. Use this after the client has uploaded directly to S3. Provide the S3 object key, optional text context, and meal type hint for better accuracy.
| Field | Type | Required | Description |
|---|---|---|---|
| key | string | optional | S3 object key of the uploaded food photo |
| message | string | optional | Optional text context |
| mealType | string | optional | Meal type hint |
Upload a food photo for AI-powered nutritional analysis. Use when the user takes a photo of their meal and wants to know calories, macros, and food identification. Accepts multipart/form-data with a photo file up to 10MB. Returns identified foods with estimated nutritional breakdown.
| Field | Type | Required | Description |
|---|---|---|---|
| message | string | optional | Optional text context for the food photo |
| mealType | string | optional | Meal type hint |
Returns ranked candidate foods with per-serving nutrition for a food name or short description the user typed. Use to back a "search food by name" box — pick a candidate and log it via POST /nutrition/food. Read-only: no image, no S3, no DB write.
| Field | Type | Required | Description |
|---|---|---|---|
| query | string | required | Food name or short description typed by the user |
| mealType | string | optional | Meal type hint |
Records a food intake entry with nutritional data for the authenticated user. Use when the user reports eating a meal or snack and wants to track calories and macros. Provide food name, calories, and optionally protein, carbs, fat, and meal type.
| Field | Type | Required | Description |
|---|---|---|---|
| imageUrl | string | optional | |
| description | string | optional | |
| calories | number | required | |
| protein | number | required | |
| carbs | number | required | |
| fat | number | required | |
| fiber | number | optional | |
| items | string[] | optional | |
| mealType | string | optional | |
| foodSource | string | optional | |
| healthScore | number | optional | |
| confidence | string | optional | |
| userEdited | boolean | optional |
Returns all food log entries for today with nutritional breakdown per entry and daily totals. Use when the user asks what they've eaten today, wants to check remaining calories, or needs a nutrition summary for the day.
Permanently removes the user's own food log entry by ID. Owner-scoped: only the owning user may delete. Returns the deleted entry's id.
| Field | Type | Required | Description |
|---|---|---|---|
| id | number | required |
Creates a customized meal plan based on caloric needs, dietary preferences, and duration. Use when the user asks for a new meal plan from the nutrition module. For the dedicated meal plan service with queue-based generation, use the /mealplan endpoints instead. Requires an active subscription or available free-tier usage.
| Field | Type | Required | Description |
|---|---|---|---|
| calories | number | required | Target daily calories |
| dietType | string | required | Diet type preference |
| numberOfDays | number | required | Number of days to generate meal plan for |
Returns the current streak count for the specified tracking type (defaults to meal_logging). Use when the user asks about their logging streak or for gamification features showing consistency.
| Field | Type | Required | Description |
|---|---|---|---|
| type | string | optional | Streak type (default: meal_logging) (in query) |
Returns today's calorie intake, macro breakdown (protein/carbs/fat with goals), and a list of logged meals. Use when the user asks what they've eaten today, how many calories they've consumed, or wants to see their macro progress. Returns hasData: false with zero values when no food has been logged today — never interpret zeroes as dietary truth without checking hasData.
Generates a presigned S3 PUT URL for the client to upload a food photo directly to S3 without routing through the API. Use before calling analyze-food-key when the client prefers direct S3 upload over multipart form upload. Returns the presigned URL and the S3 key to use with analyze-food-key.
Records a water intake entry for the authenticated user. Use when the user reports drinking water or wants to track hydration. Accepts amount in milliliters.
| Field | Type | Required | Description |
|---|---|---|---|
| amountMl | number | required | Amount of water in milliliters |
| loggedAt | string | optional | When the water was consumed |
Returns the total water intake for today with individual entries and progress toward the daily goal. Use when the user asks how much water they've had today or wants to check hydration status.
Permanently removes the user's own water log entry by ID. Owner-scoped: only the owning user may delete. Returns the deleted entry's id.
| Field | Type | Required | Description |
|---|---|---|---|
| id | number | required |
Health Data
11 endpointsProvides comprehensive AI-powered analysis of bloodwork results with personalized recommendations and risk assessment. Use when the user uploads or asks about their blood test results (CBC, metabolic panel, lipid panel, thyroid, etc.). Returns detailed marker analysis, out-of-range flags, and health recommendations.
| Field | Type | Required | Description |
|---|---|---|---|
| glucose | number | required | Blood glucose level in mg/dL |
| cholesterol | number | required | Total cholesterol in mg/dL |
| hemoglobin | number | required | Hemoglobin in g/dL |
| testDate | string | required | Test date |
| hdl | number | optional | HDL cholesterol in mg/dL |
| ldl | number | optional | LDL cholesterol in mg/dL |
| triglycerides | number | optional | Triglycerides in mg/dL |
Unified endpoint for processing all HealthKit metrics with AI-powered analysis, anomaly detection, and personalized insights. Use when receiving a full health data sync from the mobile app with multiple metric types (steps, heart rate, HRV, sleep, blood oxygen, weight, BMI, and 140+ more). Returns processed results with anomaly flags and insights.
| Field | Type | Required | Description |
|---|---|---|---|
| metrics | object[] | required | Array of health metrics (supports 150+ HealthKit metrics) |
| syncedAt | string | optional | Sync timestamp |
| deviceInfo | object | optional | Client device info |
| skipAggregation | boolean | optional | Skip post-sync aggregation and scoring (use for historical backfill where latency matters). When true, processedCount is populated but healthScore/insights/anomalies are omitted. |
Handle real-time emergency health notifications with automatic escalation and emergency service coordination. Use when a critical health event is detected (e.g., fall detection, abnormal heart rhythm, dangerously low blood oxygen). Triggers escalation workflows and returns actions taken.
| Field | Type | Required | Description |
|---|---|---|---|
| alertType | string | required | |
| severity | string | required | |
| triggerMetric | string | required | Metric that triggered the alert |
| triggerValue | number | required | Value that triggered the alert |
| thresholdValue | number | required | Threshold value that was exceeded |
| location | object | optional | User location data for emergency services |
| context | object | optional | Additional context data |
Batch delete HealthKit data by Apple sample UUIDs. Removes data at health / healthkit / batch-delete. Authenticated endpoint — honours the caller's JWT for per-user scope.
| Field | Type | Required | Description |
|---|---|---|---|
| uuids | string[] | required | Array of HealthKit sample UUIDs to delete. These are the Apple-assigned UUIDs stored in metadata.hkSampleUuid during bulk sync. |
Bulk sync comprehensive HealthKit data with unit normalization. Accepts and processes data at health / healthkit / bulk-sync. Authenticated endpoint — honours the caller's JWT for per-user scope.
| Field | Type | Required | Description |
|---|---|---|---|
| healthData | object[] | required | Array of health data points (max 5000 per request — chunk larger syncs) |
| isBackgroundSync | boolean | optional | Background sync flag for historical data |
| batchId | string | optional | Sync batch identifier |
| totalBatches | number | optional | Total expected batches for this sync session |
| batchNumber | number | optional | Current batch number |
| workouts | object[] | optional | Native HKWorkout samples. Persisted to HealthkitWorkout for workout cohesion (activity type, events, routes, swim strokes). Orthogonal to healthData — decomposed quantity samples from the same workout still flow through healthData[] for backwards compat. |
Returns oldest/newest dates, row count, and distinct metric count for this user.
Returns a home briefing sentence, per-domain health insights (fitness, sleep, nutrition, mental, heart, bloodwork) with status levels and scores, and the overall health score. Use when the user opens the Home screen, asks "how is my health?", or wants a summary of their health state. Check overallScoreAvailable before interpreting overallScore: when false, overallScore is 0 (hasData false) or null (metric not ready) — not a poor health score. hasData: false means the user has not yet synced Apple Health data — do not interpret overallScore: 0 as a poor health score in that case. Insights are derived from the user's scored focuses and the latest AI-computed health metric. computedAt is the ISO-8601 timestamp of the snapshot — use it to inform the user if data is stale.
Create personalized health insights and recommendations based on comprehensive data analysis for a specific health profile category. Use when the user wants detailed analysis of a particular health domain (e.g., cardiovascular, sleep, nutrition). Returns AI-generated insights with confidence scores and actionable recommendations.
| Field | Type | Required | Description |
|---|---|---|---|
| profile | string | required | Health profile category to analyze |
Create AI-powered predictions for health metrics based on historical data, lifestyle patterns, and risk factors. Use when the user asks about future health trends, projected outcomes, or wants to understand where their health is heading. Returns predictions with confidence intervals and contributing factors.
| Field | Type | Required | Description |
|---|---|---|---|
| targetMetric | string | required | Metric to predict |
| timeHorizonDays | number | required | Prediction time horizon in days |
| targetDate | string | optional | Specific date to predict for |
| includeRiskFactors | boolean | optional | Include risk factors analysis |
| includeRecommendations | boolean | optional | Include preventative recommendations |
Receives and stores health data synced from the mobile HealthKit integration. Use when the user has new health data to upload from their device. This is the legacy sync endpoint; prefer POST /health/comprehensive for new integrations.
| Field | Type | Required | Description |
|---|---|---|---|
| steps | number | required | Number of steps taken |
| heartRate | number | required | Heart rate in beats per minute |
| calories | number | required | Calories burned |
| sleepHours | number | required | Sleep duration in hours |
| date | string | required | Date of the health data |
Returns the list of promoted HealthKit types including their Apple identifiers, categories, display names, and units. Use when the user asks what health metrics are tracked or available. Helpful for understanding which data types can be synced from wearables.
Health Profile
3 endpointsReturns the full Unified Health Profile (health score, data completeness, source breakdown, AI correlations) for the authenticated user. This is the starting point for personalized health advice. Use when you need a comprehensive view of the user's health status before giving recommendations. Returns null if the profile has not yet been computed.
Returns a lightweight summary (health score, data completeness percentage, last sync timestamp) suitable for dashboard cards and overview screens. Use this instead of the full profile when you only need high-level health status. Returns an empty object ({}) when no profile exists.
Returns time-bucketed metric trend data for charting and visualization. Supports querying one or multiple metrics (comma-separated). Use when the user asks about health trends over time, wants to see charts, or asks "how has my heart rate been this week?". Returns data points suitable for line/bar charts.
| Field | Type | Required | Description |
|---|---|---|---|
| userId | number | optional | Target user ID. Defaults to current authenticated user. (in query) |
| metricType | string | optional | Metric type, or comma-separated metric types (in query) |
| startDate | string | optional | Start date (ISO-8601) (in query) |
| endDate | string | optional | End date (ISO-8601) (in query) |
| resolution | string | optional | Bucket resolution override. If omitted or auto, resolution is chosen by date range. (in query) |
Metrics
7 endpointsAccepts either single-day metrics (date + metrics object) or batch metrics (dailyMetrics array). Use when syncing daily health data from the mobile app. Supports backward compatibility with the single-day format. Triggers health score calculation and AI analysis.
| Field | Type | Required | Description |
|---|---|---|---|
| date | string | optional | |
| metrics | object[] | optional | |
| healthScore | number | optional | |
| dailyMetrics | object[] | optional |
Uses AI chat to interactively fill in missing health metrics for the specified focus area. Use when the user has incomplete data and wants AI assistance to estimate or gather missing values through conversation.
Returns health score data points over a time period (7d, 30d, or 90d). Each entry includes the date, score, and optional pillar breakdown. Triggers backfill for rows with missing scores if insufficient data points exist. Not Anna-facing (x-anna-expose: false).
| Field | Type | Required | Description |
|---|---|---|---|
| period | string | optional | Time period for score history. Defaults to 7d. (in query) |
Re-runs AI analysis on the latest daily metric, rebuilds the rolling health summary, and updates the user record. Use when the user explicitly requests a health score refresh or after significant data updates. This is a heavier operation than normal metric submission.
Generates personalized health recommendations based on the provided daily metrics data. Use when the user asks for advice or recommendations after submitting health data. Returns AI-generated suggestions for improving health outcomes.
| Field | Type | Required | Description |
|---|---|---|---|
| metrics | object[] | required | |
| date | string | required | |
| healthScore | number | optional | Pre-computed health score from mobile |
| dailyMetrics | object | optional | Batch format only; ignored for single-day validation when present alongside date/metrics. |
Returns the user's most recent health survey answers (sleep quality, stress, diet, exercise self-assessments). Use when you need subjective health data that complements objective HealthKit metrics. Returns empty object for new users who have not completed a survey.
Processes user health survey answers (self-reported sleep, stress, diet, exercise ratings) and computes initial health metrics and scores. Use during onboarding or when the user completes a periodic health assessment survey.
Bloodwork
10 endpointsUpload, parse, and explain blood-test reports. To order new panels through an integrated lab and have results flow back here automatically, see Lab Partners.
Call after the client PUTs the file to the presigned URL. The key must match the authenticated user.
| Field | Type | Required | Description |
|---|---|---|---|
| key | string | required | S3 object key returned from presign (must be under bloodwork/<userId>/…) |
| mimetype | string | required |
Explain bloodwork. Returns data at bloodwork / explain / :bloodReportId. Authenticated endpoint — honours the caller's JWT for per-user scope.
| Field | Type | Required | Description |
|---|---|---|---|
| bloodReportId | number | required | |
| message | string | required | The message content |
| type | string | optional | Message type |
| options | object | optional | |
| user_id | number | optional | Optional user ID for testing/debugging (should not be used in production) |
| agentType | string | optional | Optional agent type to route the message to a specific agent |
| language | string | optional | Override response language (e.g. "spanish"). Falls back to user profile language. |
| is_thread_end | boolean | optional | Signal that this is the last message in the session (e.g. user backgrounds app or closes chat). When true, LangWatch quality evaluators fire for this conversation turn. |
| threadId | string | optional | LangGraph thread ID for conversation continuity. Sent by the mobile client when resuming an existing thread. |
| posthog_session_id | string | optional | PostHog session recording ID for LLM trace session-replay linking |
| pillars | string[] | optional | Explicit pillar hints forwarded to Anna for deterministic routing. When set, Anna bypasses rule-based pillar classification and scopes tools/prompts to the listed pillars. |
Save a blood report parsed from free text in chat. Accepts and processes data at bloodwork / from-text. Authenticated endpoint — honours the caller's JWT for per-user scope.
Get bloodwork list. Returns data at bloodwork / list. Authenticated endpoint — honours the caller's JWT for per-user scope.
Step 1 of 2: Returns a presigned S3 URL for direct bloodwork file upload. After uploading the file via PUT to the returned URL, call POST /bloodwork/confirm-upload with the returned key to finalize. Requires JWT authentication.
| Field | Type | Required | Description |
|---|---|---|---|
| fileName | string | required | |
| contentType | string | required | |
| fileSize | number | required | Declared file size in bytes (for client validation) |
Upload and analyze bloodwork files (sync). Accepts and processes data at bloodwork / upload. Authenticated endpoint — honours the caller's JWT for per-user scope.
Create bloodwork upload-async. Accepts and processes data at bloodwork / upload-async. Authenticated endpoint — honours the caller's JWT for per-user scope.
Get bloodwork. Returns data at bloodwork / :id. Authenticated endpoint — honours the caller's JWT for per-user scope.
| Field | Type | Required | Description |
|---|---|---|---|
| id | number | required |
Permanently deletes a bloodwork report owned by the authenticated user. Irreversible. Returns 404 when the report does not exist and 403 when it belongs to a different user. Destructive op — requires a confirmation_token from the MCP/app confirmation flow.
| Field | Type | Required | Description |
|---|---|---|---|
| id | number | required |
Get bloodwork marker. Returns data at bloodwork / :id / marker / :markerName. Authenticated endpoint — honours the caller's JWT for per-user scope.
| Field | Type | Required | Description |
|---|---|---|---|
| id | number | required | |
| markerName | string | required |
Lab Partners
4 endpointsOrder at-home and in-clinic blood panels through Healify's integrated lab partners (Probatix, Thriva, Homed-IQ, Terra) and receive results back as Bloodwork reports. The three order endpoints are JWT-authenticated and self-scoped (user_id) — a caller can only list panels and read or create their own orders. The fourth is the public, signature-verified webhook each partner calls to deliver finished results; it is not called by partner integrators directly but its contract is documented here for completeness.
Returns the purchasable lab panels for the requested partner and locale. Scoped to the authenticated user via JWT. Use the returned panelId when placing an order.
| Field | Type | Required | Description |
|---|---|---|---|
| partnerKey | string | optional | Query param. Lab partner to list panels for — one of PROBATIX, THRIVA, HOMEDIQ, TERRA. Omit to list across all configured partners. |
| locale | string | optional | Query param. Locale for panel names / pricing (e.g. en-GB). |
Returns 200 with an array of panel objects:
| Field | Type | Required | Description |
|---|---|---|---|
| panelId | string | required | Partner-scoped panel identifier (used when placing an order). |
| name | string | required | Human-readable panel name. |
| description | string | optional | Short description of what the panel measures. |
| priceMinorUnits | number | optional | Price in minor currency units (e.g. pence for GBP, cents for EUR). |
| currency | string | optional | ISO 4217 currency code (e.g. GBP, EUR). |
| biomarkers | string[] | optional | Biomarker names included in the panel. |
Creates a lab order with the selected partner and panel for the authenticated user. The user is always taken from the JWT — never the body — so a caller can only order for themselves. When invoked via the Anna MCP tool this is a destructive operation and requires a confirmation token.
| Field | Type | Required | Description |
|---|---|---|---|
| partnerKey | string | required | Lab partner key — one of PROBATIX, THRIVA, HOMEDIQ, TERRA. |
| panelCode | string | required | Panel code to order (the partner-scoped panelId from GET /api/lab/panels). |
| shippingAddr | object | optional | Shipping address for at-home kit dispatch / phlebotomy (free-form string or structured object). |
Returns 201 with the created lab order (including its id and initial PENDING status).
Returns a single lab order by id. Ownership is enforced — callers only see their own orders. Returns 404 when the order does not exist or belongs to another user.
| Field | Type | Required | Description |
|---|---|---|---|
| id | string | required | Path param. LabOrder id (cuid). |
The status field follows the lab-order lifecycle: PENDING → CONFIRMED → PROCESSING → COMPLETE, or CANCELLED / FAILED. When an order reaches COMPLETE the partner delivers results via the webhook below, which Healify ingests into a Bloodwork report.
Public, signature-verified callback that lab partners invoke to deliver finished results. No JWT — authenticity is proven by an HMAC-SHA256 signature over the raw request body. Healify verifies the signature, enqueues the event for asynchronous ingestion (normalisation → BloodReport → metrics), and returns immediately. This endpoint is implemented by Healify and consumed by the partner; integrators do not call it.
| Field | Type | Required | Description |
|---|---|---|---|
| partnerKey | string | required | Path param. Sending partner — one of probatix, thriva, homediq, terra (lowercase). Unknown keys return 400. |
| <body> | json | required | Raw partner result event. Must include a stable id field — Healify dedupes re-deliveries on {partnerKey}:{id}, so a repeated event is a safe no-op. |
Signature scheme (per partner) — all use HMAC-SHA256 with a per-partner shared secret, compared in constant time:
| Partner | Header | Signed payload | Replay window |
|---|---|---|---|
| probatix | X-Probatix-Signature: sha256=<hex> | rawBody | — |
| thriva | X-Thriva-Signature: t=<unix>,v1=<hex> | ${t}.${rawBody} | 5 min |
| homediq | X-HomedIQ-Signature: <hex> | rawBody | — |
| terra | terra-signature: t=<unix>,v1=<hex> | ${t}.${rawBody} | 5 min |
For the timestamp schemes (Thriva, Terra), Healify rejects any request whose t is more than 5 minutes old or in the future. Always compute the HMAC over the exact raw bytes received — re-serialising the JSON will break the signature.
import { createHmac, timingSafeEqual } from 'crypto';
// Probatix / Homed-IQ: HMAC over the raw body.
function verifyHmac(secret: string, rawBody: Buffer, providedHex: string): boolean {
const expected = createHmac('sha256', secret).update(rawBody).digest();
const provided = Buffer.from(providedHex, 'hex');
return expected.length === provided.length && timingSafeEqual(expected, provided);
}
// Thriva / Terra: header is "t=<unix>,v1=<hex>"; sign `${t}.${rawBody}`.
function verifyTimestamped(secret: string, rawBody: Buffer, header: string): boolean {
const parts = Object.fromEntries(header.split(',').map(s => s.split('=').map(x => x.trim())));
const t = parseInt(parts.t, 10);
if (!Number.isFinite(t) || Math.abs(Date.now() - t * 1000) > 5 * 60 * 1000) return false;
const signed = Buffer.from(`${t}.${rawBody.toString('utf8')}`);
const expected = createHmac('sha256', secret).update(signed).digest();
const provided = Buffer.from(parts.v1, 'hex');
return expected.length === provided.length && timingSafeEqual(expected, provided);
}
import hmac, hashlib, time
# Probatix / Homed-IQ: HMAC over the raw body.
def verify_hmac(secret: str, raw_body: bytes, provided_hex: str) -> bool:
expected = hmac.new(secret.encode(), raw_body, hashlib.sha256).digest()
try:
provided = bytes.fromhex(provided_hex)
except ValueError:
return False
return hmac.compare_digest(expected, provided)
# Thriva / Terra: header is "t=<unix>,v1=<hex>"; sign f"{t}.{raw_body}".
def verify_timestamped(secret: str, raw_body: bytes, header: str) -> bool:
parts = dict(p.strip().split('=', 1) for p in header.split(','))
t = int(parts['t'])
if abs(time.time() - t) > 5 * 60:
return False
signed = f"{t}.{raw_body.decode('utf-8')}".encode()
expected = hmac.new(secret.encode(), signed, hashlib.sha256).digest()
try:
provided = bytes.fromhex(parts['v1'])
except ValueError:
return False
return hmac.compare_digest(expected, provided)
Status codes
| Code | Meaning |
|---|---|
| 200 | Event accepted and enqueued for ingestion. Returns { "received": true }. |
| 400 | Unknown partnerKey, missing raw body, or malformed JSON payload. |
| 401 | Signature verification failed (bad signature, missing/expired timestamp, or no secret configured). |
Retry policy — Healify processes results on a background queue with 3 attempts and exponential backoff (2s base). Partners should treat any non-200 response as retryable; because ingestion is idempotent on {partnerKey}:{event.id}, re-delivering the same event is always safe.
DNA Analysis
13 endpointsQueue DNA analysis job for comprehensive AI-powered analysis. Analysis is processed asynchronously and user receives a push notification when complete. Results can be retrieved via GET /dna/reports/:reportId
| Field | Type | Required | Description |
|---|---|---|---|
| reportId | string | required | DNA report ID to analyze |
| focusAreas | string[] | optional | Specific traits to focus analysis on |
| includeRecommendations | boolean | optional | Include health recommendations |
Check if user can upload DNA data. Returns false if user already has a validated DNA profile (DNA is immutable once validated).
Step 2 of 2: Called after the client has PUT the file to S3. Triggers DNA parsing and queues AI analysis.
| Field | Type | Required | Description |
|---|---|---|---|
| key | string | required | S3 key returned from presign (must be dna-raw/<userId>/…) |
| contentType | string | required | |
| provider | string | required |
Step 1 of 2: Returns a presigned S3 PUT URL for direct client-side upload. Call POST /dna/confirm-upload after uploading.
| Field | Type | Required | Description |
|---|---|---|---|
| fileName | string | required | |
| contentType | string | required | |
| fileSize | number | required | File size in bytes |
Permanently deletes the user's uploaded DNA file + derived SNP analysis. Irreversible. Idempotent: returns success even when nothing exists. Phase 8 destructive op — requires confirmation_token from MCP confirmation flow.
Retrieve list of uploaded DNA reports
Retrieve detailed information about a specific DNA report
| Field | Type | Required | Description |
|---|---|---|---|
| reportId | string | required |
Upload 23andMe, AncestryDNA, or similar raw DNA data files
| Field | Type | Required | Description |
|---|---|---|---|
| file | string | required | DNA raw data file (.txt, .csv, .zip, .pdf, or image) |
| provider | string | optional | DNA provider (e.g., 23andme, ancestrydna) |
Returns annotated genomic variants from the user's DNA analysis. Query by gene symbol (e.g., BRCA1) or rsID (e.g., rs1801133). Use when the user asks about genetic risk factors, specific gene variants, or pharmacogenomics data. Returns variant details including clinical significance and allele frequencies.
| Field | Type | Required | Description |
|---|---|---|---|
| gene | string | optional | Gene symbol (e.g. BRCA1) (in query) |
| rsId | string | optional | Legacy rsID query param name (capital I); prefer rsid (in query) |
| rsid | string | optional | rsID (e.g. rs1801133) (in query) |
Confirms a VCF file upload and starts the AWS HealthOmics annotation workflow. Use after the user has successfully uploaded their VCF file via the presigned URL. Returns a workflow run ID to track progress.
Returns the current HealthOmics annotation workflow status for the given DNA report. Use to check if the genomic analysis is complete, in progress, or failed. Returns status, progress percentage, and any error details.
| Field | Type | Required | Description |
|---|---|---|---|
| dnaReportId | string | required |
Returns a presigned PUT URL that allows the client to upload a VCF (Variant Call Format) genomic file directly to S3 without routing through the API server. Valid for 15 minutes. Use when the user wants to upload their DNA/genomic data for analysis.
| Field | Type | Required | Description |
|---|---|---|---|
| filename | string | required | VCF filename (e.g. sample.vcf or sample.vcf.gz) |
Retrieve user DNA profile and genetic insights (alias for /dna/reports)
Goals
5 endpointsRetrieve all health goals for the current user including progress tracking, milestones, and target dates.
Create new health goals with target values, deadlines, and tracking milestones. Supports weight loss, fitness, nutrition, and other health objectives.
| Field | Type | Required | Description |
|---|---|---|---|
| mainGoal | string | optional | Main goal of the user |
| secondaryGoals | string[] | optional | Secondary goals |
| challenges | string[] | optional | Challenges the user faces |
| relatedMetrics | object | optional | Related metrics and measurements. Numeric values sent as strings (e.g. "70") are automatically coerced to numbers. |
| description | string | optional | Alternative field for main goal (deprecated, use mainGoal instead) |
| goalType | string | optional | Goal type: qualitative (text-based) or quantitative (tracked with target value) |
| targetValue | number | optional | Numeric target value for quantitative goals (e.g. 70 for 70 kg) |
| targetUnit | string | optional | Unit for the target value (e.g. kg, steps, hours) |
| deadline | string | optional | Goal deadline as ISO 8601 date string |
| status | string | optional | Goal lifecycle status |
| currentValue | number | optional | Current progress value for quantitative goals (updated automatically by wearable data) |
| milestones | string[] | optional | Milestone checkpoints for the goal |
Update or create health goals with target values, deadlines, and tracking milestones. Supports weight loss, fitness, nutrition, and other health objectives.
| Field | Type | Required | Description |
|---|---|---|---|
| mainGoal | string | optional | Main goal of the user |
| secondaryGoals | string[] | optional | Secondary goals |
| challenges | string[] | optional | Challenges the user faces |
| relatedMetrics | object | optional | Related metrics and measurements. Numeric values sent as strings (e.g. "70") are automatically coerced to numbers. |
| description | string | optional | Alternative field for main goal (deprecated, use mainGoal instead) |
| goalType | string | optional | Goal type: qualitative (text-based) or quantitative (tracked with target value) |
| targetValue | number | optional | Numeric target value for quantitative goals (e.g. 70 for 70 kg) |
| targetUnit | string | optional | Unit for the target value (e.g. kg, steps, hours) |
| deadline | string | optional | Goal deadline as ISO 8601 date string |
| status | string | optional | Goal lifecycle status |
| currentValue | number | optional | Current progress value for quantitative goals (updated automatically by wearable data) |
| milestones | string[] | optional | Milestone checkpoints for the goal |
Get goal progress with milestone evaluation. Returns data at goals / progress. Authenticated endpoint — honours the caller's JWT for per-user scope.
Permanently removes the goal with the given id. Only the owning user may delete their own goal. Returns 404 if the goal is not found or does not belong to the user.
| Field | Type | Required | Description |
|---|---|---|---|
| id | number | required |
Habits
9 endpointsGet active habits and progress for a date. Returns data at habits. Authenticated endpoint — honours the caller's JWT for per-user scope.
Mark a habit as done for today (mobile shorthand). Accepts and processes data at habits / complete. Authenticated endpoint — honours the caller's JWT for per-user scope.
Create manual habits in user_habits. Accepts and processes data at habits / manual. Authenticated endpoint — honours the caller's JWT for per-user scope.
Get weekly habit overview bars. Returns data at habits / overview / weekly. Authenticated endpoint — honours the caller's JWT for per-user scope.
| Field | Type | Required | Description |
|---|---|---|---|
| weekStart | string | required | ISO 8601 date string for the start of the week (Monday). Required. (in query) |
Generate habit recommendations (not persisted). Accepts and processes data at habits / recommendations. Authenticated endpoint — honours the caller's JWT for per-user scope.
Save selected recommended habits to user_habits. Accepts and processes data at habits / recommendations / select. Authenticated endpoint — honours the caller's JWT for per-user scope.
Update a habit's definition fields (target value, unit, frequency type/target, schedule days) at habits / :habitId. Authenticated endpoint — honours the caller's JWT for per-user scope. Log state (value/completed) is owned by the log endpoint, not this one.
Permanently removes the user's own habit and all associated logs. Owner-scoped: a user can only delete their own habits. Authenticated endpoint — honours the caller's JWT for per-user scope.
| Field | Type | Required | Description |
|---|---|---|---|
| habitId | string | required |
Upsert habit log for a date (habit_id + log_date). Accepts and processes data at habits / :habitId / log. Authenticated endpoint — honours the caller's JWT for per-user scope.
Fitness
17 endpointsList or search exercises with optional filters. Returns data at exercises. Authenticated endpoint — honours the caller's JWT for per-user scope.
| Field | Type | Required | Description |
|---|---|---|---|
| q | string | optional | Text search query (name, muscle, equipment) (in query) |
| bodyPart | string | optional | Filter by body part (e.g. chest, back, legs) (in query) |
| equipment | string | optional | Filter by equipment (e.g. barbell, dumbbell, bodyweight) (in query) |
| muscleGroup | string | optional | Filter by muscle group (matches target_muscle, secondary_muscles, or exercise_muscle_groups) (in query) |
| category | string | optional | Filter by category (in query) |
| limit | string | optional | Number of results to return (max 100) (in query) |
| includeCustom | string | optional | Include custom exercises for the calling user (default: true) (in query) |
Create a custom exercise for the current user. Accepts and processes data at exercises / custom. Authenticated endpoint — honours the caller's JWT for per-user scope.
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | required | Exercise name |
| targetMuscles | string[] | required | Target muscle groups |
| equipment | string | required | Equipment type |
| bodyPart | string | optional | Primary body part |
| instructions | string[] | optional | Instructions array |
| description | string | optional | Exercise description |
Get per-exercise weight/volume/1RM progress history. Returns data at exercises / :id / progress. Authenticated endpoint — honours the caller's JWT for per-user scope.
| Field | Type | Required | Description |
|---|---|---|---|
| id | number | required |
Create a workout program template (manual or AI-generated). Accepts and processes data at fitness / programs. Authenticated endpoint — honours the caller's JWT for per-user scope.
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | required | |
| description | string | optional | |
| goal | string | optional | Fitness goal (e.g. strength, weight_loss, muscle_gain) |
| difficulty | string | optional | |
| durationWeeks | number | optional | |
| daysPerWeek | number | optional | |
| exercises | object[] | required | |
| source | string | optional | |
| isActive | boolean | optional | When true, program is published (included in weekly schedule and AI context). New programs default to false (draft / hidden). |
| coachingNotes | string[] | optional | Program-level AI coaching notes |
List user workout programs (slim, paginated). Returns data at fitness / programs. Authenticated endpoint — honours the caller's JWT for per-user scope.
| Field | Type | Required | Description |
|---|---|---|---|
| limit | number | optional | (in query) |
| offset | number | optional | (in query) |
Get this week's scheduled programs. Returns data at fitness / programs / weekly. Authenticated endpoint — honours the caller's JWT for per-user scope.
| Field | Type | Required | Description |
|---|---|---|---|
| timezone | string | optional | IANA timezone (e.g. America/Los_Angeles) for user's current weekday (in query) |
Get program detail (full nested with exercises). Returns data at fitness / programs / :id. Authenticated endpoint — honours the caller's JWT for per-user scope.
| Field | Type | Required | Description |
|---|---|---|---|
| id | number | required |
Update program template. Replaces data at fitness / programs / :id. Authenticated endpoint — honours the caller's JWT for per-user scope.
| Field | Type | Required | Description |
|---|---|---|---|
| id | number | required | |
| name | string | optional | |
| description | string | optional | |
| goal | string | optional | Fitness goal (e.g. strength, weight_loss, muscle_gain) |
| difficulty | string | optional | |
| durationWeeks | number | optional | |
| daysPerWeek | number | optional | |
| exercises | object[] | optional | |
| source | string | optional | |
| isActive | boolean | optional | When true, program is published (included in weekly schedule and AI context). New programs default to false (draft / hidden). |
| coachingNotes | string[] | optional | Program-level AI coaching notes |
Soft-delete program template. Removes data at fitness / programs / :id. Authenticated endpoint — honours the caller's JWT for per-user scope.
| Field | Type | Required | Description |
|---|---|---|---|
| id | number | required |
Assign program to weekdays. Accepts and processes data at fitness / programs / :id / schedule. Authenticated endpoint — honours the caller's JWT for per-user scope.
| Field | Type | Required | Description |
|---|---|---|---|
| id | number | required | |
| monday | boolean | optional | |
| tuesday | boolean | optional | |
| wednesday | boolean | optional | |
| thursday | boolean | optional | |
| friday | boolean | optional | |
| saturday | boolean | optional | |
| sunday | boolean | optional |
List session history (slim, paginated). Pass healthkit_synced=false to get unsynced completed sessions.. Returns data at fitness / sessions. Authenticated endpoint — honours the caller's JWT for per-user scope.
| Field | Type | Required | Description |
|---|---|---|---|
| limit | number | optional | (in query) |
| offset | number | optional | (in query) |
| from_date | string | optional | (in query) |
| to_date | string | optional | (in query) |
| healthkit_synced | string | optional | Filter: false = return only unsynced completed sessions (in query) |
Start a workout session (creates DB record immediately). Accepts and processes data at fitness / sessions / start. Authenticated endpoint — honours the caller's JWT for per-user scope.
| Field | Type | Required | Description |
|---|---|---|---|
| programId | number | optional | Program template ID to base this session on |
| sessionName | string | optional | Optional custom session name |
Get session detail (full nested with exercises and sets). Returns data at fitness / sessions / :id. Authenticated endpoint — honours the caller's JWT for per-user scope.
| Field | Type | Required | Description |
|---|---|---|---|
| id | number | required |
Abandon a session (no HealthKit write-back). Accepts and processes data at fitness / sessions / :id / abandon. Authenticated endpoint — honours the caller's JWT for per-user scope.
| Field | Type | Required | Description |
|---|---|---|---|
| id | number | required |
Complete session — batch-POST all exercises and sets. Accepts and processes data at fitness / sessions / :id / complete. Authenticated endpoint — honours the caller's JWT for per-user scope.
| Field | Type | Required | Description |
|---|---|---|---|
| id | number | required | |
| exercises | object[] | required | All exercises logged in this session |
Confirm HealthKit write-back for a session. Accepts and processes data at fitness / sessions / :id / healthkit-sync. Authenticated endpoint — honours the caller's JWT for per-user scope.
| Field | Type | Required | Description |
|---|---|---|---|
| id | number | required |
Returns today's Apple Watch activity rings (move/exercise/stand) with values, goals, and progress fractions, plus an optional recovery score derived from HRV and resting heart rate. Use when the user asks about their activity rings, move/exercise/stand progress, or recovery status. Always check hasData per ring before interpreting values — hasData: false means Apple Watch has not synced data for that ring today, not that the user is sedentary. recoveryAvailable: false means recoveryScore is null due to insufficient HRV history (fewer than 3 nights) — do not interpret null as poor recovery.
Meal Plans
6 endpointsRetrieve the user's current AI-generated meal plan. Returns null if no meal plan has been generated yet. Use when the user asks to see their existing meal plan or wants to check what meals are planned.
Queue a fresh AI-generated meal plan, replacing the existing one. Resets the nutrition profile and enqueues a background generation job. The user receives a push notification when the new plan is ready. Use when the user wants a completely new meal plan.
Retrieve the current meal plan or automatically generate a new one if none exists. This is the recommended endpoint for most use cases as it handles both scenarios. Use when the user wants their meal plan and you want to ensure they always get one. Requires subscription or free-tier usage.
Retrieve the nutrition profile containing dietary preferences, allergies, calorie targets, and macro splits. Use when the user asks about their dietary settings or before generating a meal plan to check current preferences.
Update the nutrition profile with dietary preferences, allergies, calorie targets, and macro distribution. Use when the user changes their dietary preferences, reports new allergies, or adjusts calorie goals. This affects future meal plan generation.
Delete the nutrition profile, which triggers regeneration of the meal plan on the next request. Use when the user wants to start fresh with their dietary preferences.
Meditation
10 endpointsProxies SSE events from meditation-service for dual-stream playback. Events: music (instant library music URL), voice_stream (HLS voice URL), complete (mastered audio URL), error. Use for real-time meditation audio streaming with separate music and voice channels.
| Field | Type | Required | Description |
|---|---|---|---|
| jobId | string | required |
Submits a meditation generation job and returns a jobId immediately for polling. Use when the user requests a new meditation. Specify type (focus, sleep, stress, etc.), duration, and voice preferences. Requires active subscription or free-tier usage.
| Field | Type | Required | Description |
|---|---|---|---|
| type | string | required | Type of meditation to generate |
| duration | number | required | Duration in seconds |
| focus | string | optional | User focus/intention for the session |
| healthContext | object | optional | User health context for personalization |
| thread_id | string | optional | Chat thread ID for associating completion message (chat-initiated meditations) |
| voiceGenerator | string | optional | TTS provider: elevenlabs, cartesia, or openai |
| backgroundMusic | boolean | optional | Whether to include background music (default: true) |
| enableKaraoke | boolean | optional | Whether to enable karaoke mode (word-level TTS timing for lyric display) |
Returns all meditation generation jobs for the authenticated user, ordered by creation date descending. Use when the user wants to see their meditation history or replay a previous session. Supports filtering by status and pagination.
| Field | Type | Required | Description |
|---|---|---|---|
| status | string | optional | Filter by job status (in query) |
| limit | number | optional | Max results (default 50) (in query) |
Creates a meditation job entry in the database for tracking generation progress. Use after initiating meditation generation to register the job for status polling and webhook handling.
Records that the user listened to a meditation until the end or past the completion threshold. Use when the meditation player reports playback completion. Tracks listen history for coaching insights and streak tracking.
| Field | Type | Required | Description |
|---|---|---|---|
| jobId | string | required |
Returns all listen sessions for the authenticated user, ordered by most recent first. Each row represents one completed meditation playback. Use when the user asks about their meditation history or for tracking meditation consistency.
| Field | Type | Required | Description |
|---|---|---|---|
| limit | number | optional | Max results (default 50) (in query) |
Lightweight polling endpoint for meditation job progress with caching. Use for frequent polling during meditation generation to update progress bars without heavy DB lookups.
| Field | Type | Required | Description |
|---|---|---|---|
| jobId | string | required |
Polls for the current status of a meditation generation job including progress percentage, current stage, and URLs when complete. Use to check if a meditation the user requested is ready for playback.
| Field | Type | Required | Description |
|---|---|---|---|
| jobId | string | required |
Proxies the SSE stream from meditation-service for a given job. Use for real-time progress updates during meditation generation. Returns Server-Sent Events with progress, stage, and completion data.
| Field | Type | Required | Description |
|---|---|---|---|
| jobId | string | required |
Returns available meditation TTS voices from the meditation service. Falls back to a static list if the service is unreachable. Use when the user wants to choose a voice for their meditation session.
Recommendations
8 endpointsReturns personalized health product recommendations based on the user's health profile, goals, and preferences. Use when the user asks about supplements, health products, or visits the Shop tab. Supports filtering by category and pagination via limit parameter.
| Field | Type | Required | Description |
|---|---|---|---|
| category | string | required | (in query) |
Returns the list of product categories available in the recommendation catalog (e.g., supplements, fitness equipment, sleep aids). Use to populate category filters in the Shop tab.
Records that the user clicked on a product recommendation. Use for engagement tracking and recommendation quality improvement.
Called by the Anna agentcore surface_recommendation tool when Anna has explicit health data evidence for a product gap. Anna service-token callers may specify any userId. User-JWT callers may only create recommendations for their own account.
| Field | Type | Required | Description |
|---|---|---|---|
| userId | number | required | User ID (numeric). |
| productCategory | string | required | Product category slug (e.g. "vitamin_d_supplement"). |
| rationale | string | required | Human-readable evidence string explaining the recommendation. |
| dataSource | string | required | Health data field that backs this recommendation (e.g. "bloodwork.vitaminD"). |
| affiliateUrl | object | optional | Affiliate URL — must be from an approved affiliate domain. Null until v1.6. |
Records the user's consent for receiving affiliate product recommendations. Required for FTC compliance before showing monetized recommendations. Use when the user opts in or out of affiliate recommendations.
Returns whether the user has consented to affiliate product recommendations. Use to check consent status before displaying monetized product suggestions.
Records that the user completed a follow-up action on a product recommendation (e.g., purchased, added to cart). Use for tracking recommendation engagement and improving future suggestions.
Returns the user's recent product recommendation click history with timestamps. Use to understand user product interests or avoid recommending already-viewed products.
Insights
6 endpointsReturns Food→body causality cards (HEA-4293): paginated, excluding dismissed entries by default. Uses an opaque cursor for stable pagination.
| Field | Type | Required | Description |
|---|---|---|---|
| limit | number | optional | (in query) |
| cursor | string | optional | Opaque pagination cursor from previous response (in query) |
| unshownOnly | boolean | optional | When true, return only cards not yet shown/dismissed (in query) |
Loads one causality card by UUID for the detail screen and records an analytics view event (Amplitude). Returns 404 if the card does not exist or belongs to another user.
| Field | Type | Required | Description |
|---|---|---|---|
| id | string | required |
Soft-dismisses a card for the current user (sets dismissedAt) so it no longer appears in default lists. Optional secondsViewed supports dismiss-rate quality metrics.
| Field | Type | Required | Description |
|---|---|---|---|
| id | string | required | |
| secondsViewed | number | optional | Approximate seconds the card was visible before dismiss |
Increments share count, stamps last share channel when provided, updates sharedAt, and emits an analytics event for funnel measurement.
| Field | Type | Required | Description |
|---|---|---|---|
| id | string | required | |
| channel | string | optional | Share channel label for analytics (e.g. instagram_story, copy_link) |
Returns an estimated biological age derived from the past 30 days of HealthKit data (resting HR, HRV, sleep score, VO2 max). Confidence reflects how many biomarkers had sufficient data. Returns a null-shaped result with confidence=0 when no data is available. DNA layer is V2 — this MVP uses biomarkers only.
Returns a structured snapshot of yesterday health data (sleep, HRV, resting HR, energy score), the latest causality card, and the top recommended habit. Called by AgentCore to compose the voice morning briefing. Free-text fields are PHI-sanitized before return. nextCalendarEvent is always null until a calendar integration is available.
Reports
2 endpointsGet monthly report. Returns data at report / monthly. Authenticated endpoint — honours the caller's JWT for per-user scope.
Get weekly report. Returns data at report / weekly. Authenticated endpoint — honours the caller's JWT for per-user scope.
Check-ins
3 endpointsGet checkup question. Returns data at checkup. Authenticated endpoint — honours the caller's JWT for per-user scope.
Post checkup question. Accepts and processes data at checkup. Authenticated endpoint — honours the caller's JWT for per-user scope.
| Field | Type | Required | Description |
|---|---|---|---|
| question | string | optional | |
| answer | string | optional | |
| questionId | string | optional | Optional question identifier sent by consumer |
Post custom checkup question. Accepts and processes data at checkup / custom. Authenticated endpoint — honours the caller's JWT for per-user scope.
| Field | Type | Required | Description |
|---|---|---|---|
| question | string | optional | |
| answer | string | optional | |
| questionId | string | optional | Optional question identifier sent by consumer |
Milestones
5 endpointsReturns all unlocked achievements for the given userId. Restricted to the authenticated user's own data — returns 403 if userId does not match the caller's JWT subject.
| Field | Type | Required | Description |
|---|---|---|---|
| userId | number | required |
Returns all health milestones awarded to the authenticated user (weight goals, streak achievements, habit formation, etc.). Use when the user asks about their achievements or for gamification displays.
Returns milestones that have been awarded but not yet viewed by the user. Use to trigger celebration UI or congratulatory coaching messages when the user opens the app.
Records that the user shared a milestone and returns a shareable URL for referral loop. Use when the user wants to share a health achievement on social media or with friends.
| Field | Type | Required | Description |
|---|---|---|---|
| id | number | required |
Marks a specific milestone as viewed, dismissing the celebration UI. Use after the user has seen the milestone celebration screen.
| Field | Type | Required | Description |
|---|---|---|---|
| id | number | required |
Notifications
4 endpointsReturns paginated notification history for the authenticated user. Use when the user wants to see their notification feed or check past health reminders, milestone celebrations, and coaching messages. Supports cursor-based pagination.
| Field | Type | Required | Description |
|---|---|---|---|
| take | number | optional | Number of notifications to return (default 100, max 200) (in query) |
| cursor | number | optional | Cursor (last notification ID) for pagination (in query) |
Triggers an immediate AI-generated notification using full health context (HealthKit, DNA, bloodwork, sleep, etc.). Respects throttling limits. Use when the agent wants to proactively send the user a personalized health insight or coaching nudge.
Marks the specified notification IDs as read for the authenticated user. Use when the user opens or dismisses notifications in the app.
Returns only unread notifications for the authenticated user. Use to display a badge count or unread notification list in the app.
Feedback
1 endpointCreate feedback. Accepts and processes data at feedback. Authenticated endpoint — honours the caller's JWT for per-user scope.
Voice
3 endpointsGet voice anna-token. Returns data at voice / anna-token. Authenticated endpoint — honours the caller's JWT for per-user scope.
Create voice transcribe. Accepts and processes data at voice / transcribe. Authenticated endpoint — honours the caller's JWT for per-user scope.
Create voice v1 chat completions. Accepts and processes data at voice / v1 / chat / completions. Authenticated endpoint — honours the caller's JWT for per-user scope.
Attachments
3 endpointsClassifies the uploaded document and directs Anna to refer the user into the correct flow: bloodwork → Bloodwork upload screen, dna → DNA upload screen, other → general Anna acknowledgement. Accepts PDF, plain-text, CSV, and ZIP archives (DNA exports). ZIP files are classified by filename heuristic only — never opened or parsed.
| Field | Type | Required | Description |
|---|---|---|---|
| document | string | required | |
| message | string | optional | Optional caption or question the user typed with the document. |
Upload and store a health-related image (bloodwork photos, meal photos, progress photos, avatar). Returns the public URL of the uploaded image. Max file size 10MB. Use when the user wants to upload a photo for health tracking or profile purposes.
| Field | Type | Required | Description |
|---|---|---|---|
| file | string | required |
Classifies the uploaded photo and forwards it to the right specialist: food → existing analyze-food-photo flow, skin / body / wearable / document / other → AgentCore Anna with image context, bloodwork → existing bloodwork upload-and-analyze flow. Use this endpoint for EVERY chat-attached image so the server picks the right path; never route directly to analyze-food-photo from the chat composer.
| Field | Type | Required | Description |
|---|---|---|---|
| photo | string | required | |
| message | string | optional | Optional caption or question the user typed with the image. |
| forceCategory | string | optional | Optional override — skips classification and routes directly to the named handler. |
Subscriptions
8 endpointsReturns the subscription tier, status, expiration, and trial state for the authenticated user. Use before offering premium features to check if the user has an active subscription. Alias for GET /subscriptions/status.
Updates the subscription tier and status for the authenticated user. Use when processing subscription changes from the app store or admin actions.
| Field | Type | Required | Description |
|---|---|---|---|
| revenueCatUserId | string | optional | RevenueCat user ID |
| revenueCatAliases | string[] | optional | RevenueCat aliases for this user |
| subscriptionStatus | string | optional | Subscription status |
| subscriptionPlan | string | optional | Subscription plan identifier |
| subscriptionStartDate | string | optional | Subscription start date |
| subscriptionEndDate | string | optional | Subscription end date |
| trialStartDate | string | optional | Trial start date |
| trialEndDate | string | optional | Trial end date |
| isTrialActive | boolean | optional | Whether trial is currently active |
| hasUsedTrial | boolean | optional | Whether user has used their trial |
Cancels the current RevenueCat subscription at end-of-period. Idempotent: returns { success: true, already_cancelled: true } if no active subscription exists. Phase 8 destructive op — requires confirmation_token from MCP confirmation flow.
Returns detailed subscription status including tier (free, premium, trial), expiration date, and whether the user is in a trial period. Use to determine feature access before calling premium-only endpoints.
Activates a 7-day free trial of premium features for the authenticated user. Use when the user wants to try premium features. Fails if the user has already used their trial or has an active trial.
Returns usage counts and limits for gated features (chat messages, meal plans, bloodwork analyses, meditations). Use to check remaining free-tier usage before calling a gated endpoint.
Returns tier (trial | free | paid), trial window, and per-feature counters. Mobile polls this on app open and after each feature action.
MUST be called before invoking any gated feature. Uses Redis INCR for atomicity — parallel requests cannot both succeed past the limit. Returns allowed:false + reason when limit is hit; mobile MUST show paywall instead of feature.
| Field | Type | Required | Description |
|---|---|---|---|
| feature | string | required | Feature to increment usage counter for |
Integrations
6 endpointsReturns all active service integrations for the authenticated user.
Returns all supported health connectors with their display name, source (pipedream or open-wearables), and availability status. Use this to drive UI tile rendering. Apple Health is excluded (native HealthKit integration). "coming_soon" tiles are gated pending provider credential provisioning.
Generates a Pipedream Connect token and returns a URL the mobile app or web opens for OAuth. Supported services: fitbit, google-fit-developer-app, withings, strava. Pass platform="web" to receive web-compatible redirect URIs.
| Field | Type | Required | Description |
|---|---|---|---|
| appSlug | string | required | Pipedream app slug for the service to connect |
| platform | string | optional | Platform initiating the connection. Determines OAuth redirect URIs. |
Proxies a connect-initiation request to the Open Wearables aggregator for the given provider (oura, whoop, garmin). Returns an OAuth URL for the user to complete. Returns 503 when the provider credentials have not yet been provisioned — these are gated until the respective developer app secrets are configured.
| Field | Type | Required | Description |
|---|---|---|---|
| provider | string | required | Open Wearables provider to connect |
| platform | string | optional | Platform initiating the connection. Determines OAuth redirect URI. |
Marks the integration as revoked (soft delete). The user can reconnect later.
| Field | Type | Required | Description |
|---|---|---|---|
| service | string | required | Service slug to disconnect |
Fetch health data from a connected wearable service via Pipedream proxy. Use when the user asks about their Fitbit steps, Strava activities, Withings weight, or Google Fit data.
| Field | Type | Required | Description |
|---|---|---|---|
| service | string | required | Service slug to fetch data from |
| metricType | string | required | Metric type to fetch: steps, heart_rate, sleep, weight, activities, calories, blood_pressure |
| startDate | string | required | Start date (YYYY-MM-DD) |
| endDate | string | required | End date (YYYY-MM-DD) |
User & Auth
18 endpointsCreates a new user record with the provided profile data. Use during initial registration when a user account needs to be provisioned after authentication. Returns the created user object.
| Field | Type | Required | Description |
|---|---|---|---|
| appleId | string | optional | |
| string | optional | ||
| name | string | optional | |
| password | string | optional |
Permanently deletes the authenticated user account and all associated data. Use when the user explicitly requests account deletion. This action is irreversible.
Returns the full user profile for the authenticated user including demographics, health goals, dietary preferences, onboarding status, and notification settings. Use when the agent needs user context for personalized coaching or when the user asks about their profile.
Updates the authenticated user profile fields (weight, height, age, gender, activity level, health goals, dietary preferences, etc.). Use when the user provides updated personal information or changes their health goals.
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | required | |
| string | required | ||
| units | object | required | |
| height | number | required | |
| weight | number | required | |
| sex | object | required | |
| age | number | required | |
| heightUnit | string | optional | |
| weightUnit | string | optional | |
| onboardingCompleted | boolean | required | |
| isLoggedIn | boolean | required | |
| pushToken | string | required | |
| dateOfBirth | string | optional | |
| avatar | string | required | |
| language | string | optional | |
| onboardingSource | string | optional | |
| focuses | object | optional | User health focus areas (array of strings or focus objects) |
| threadId | string | required | |
| lastCriticalReport | string | optional | |
| lastNonCriticalReport | string | optional |
Called by the mobile app immediately after the AppsFlyer SDK resolves the install UID. Persists appsflyerId, IDFA (if ATT authorised), and IDFV so the backend can fire server-to-server events (renewals, refunds, dunning) on behalf of this user.
| Field | Type | Required | Description |
|---|---|---|---|
| appsflyerId | string | required | AppsFlyer UID returned by the mobile SDK (appsFlyer.getAppsFlyerUID()) |
| idfa | string | optional | iOS IDFA — only present when ATT is authorised |
| idfv | string | optional | iOS IDFV — always present on iOS, never null |
Returns aggregated dashboard data for the authenticated user including health score, recent metrics, streak info, and quick-glance cards. Use when rendering the main home screen or when the user asks for an overview of their health status.
Stores a client-side data backup snapshot for the authenticated user. Use when the mobile app needs to persist a local state backup to the server for recovery purposes.
Returns a prefixed token and the exact phrase the user must confirm. Token expires in 60 seconds. A 409 is returned if another destructive token is already active for this user.
| Field | Type | Required | Description |
|---|---|---|---|
| mcp_alias | string | required | The manifest alias of the destructive operation to confirm |
| context | object | optional |
Records that the user has unlocked a new focus area (e.g., nutrition, sleep, fitness). Use when the user completes a health domain milestone that grants access to a new coaching focus area.
| Field | Type | Required | Description |
|---|---|---|---|
| focusType | string | required | Focus type being unlocked |
Returns the list of focus areas the user has unlocked through health milestones. Use to display gamification progress or determine which coaching domains are available to the user.
Sets the preferred language for the authenticated user. Use when the user wants to change their app language. Affects AI coaching language and notification language.
Returns the notification preference settings (push, email, reminders, coaching tips) for the authenticated user. Use when checking which notification channels are enabled before sending a notification.
Updates which notification channels and types are enabled for the authenticated user. Use when the user wants to toggle push notifications, email alerts, coaching reminders, or other notification categories.
| Field | Type | Required | Description |
|---|---|---|---|
| profileUpdates | boolean | optional | Receive push notifications when health profile is updated (e.g. after bloodwork/DNA) |
| dnaInsights | boolean | optional | Receive push notifications for DNA insights (medication safety, genetic findings) |
| proactiveInsights | boolean | optional | Receive proactive AI insight nudges |
| mealPlan | boolean | optional | Receive meal plan notifications |
| bloodwork | boolean | optional | Receive bloodwork report notifications |
| meditation | boolean | optional | Receive meditation session notifications |
| checkupReminders | boolean | optional | Receive checkup reminder notifications |
| chat | boolean | optional | Receive chat message notifications |
| proactiveSessions | boolean | optional | Enable per-user timezone-aware proactive check-in sessions via EventBridge Scheduler. When true, a dedicated schedule fires at 9 AM local time daily. When false, the schedule is deleted. |
| suppressWearableNudges | boolean | optional | Suppress all in-app wearable/Apple Watch nudges and omit wearable references from AI coaching. Set to true when user confirms they do not use Apple Watch. |
Returns onboarding completion flag plus basic profile fields (weight, height, age, gender, activity level, health goals, dietary preferences). Use when checking if the user has completed initial setup or to retrieve quick profile context.
DEPRECATED: Use POST /api/user/setup instead. This endpoint is kept for backward compatibility and will be removed in a future version.
| Field | Type | Required | Description |
|---|---|---|---|
| healthGoals | string[] | required | User health goals |
| dietaryPreferences | string[] | required | User dietary preferences |
| activityLevel | string | required | User activity level |
| height | number | required | User height in cm |
| weight | number | required | User weight in kg |
| age | number | required | User age |
| gender | string | required | User gender |
Returns personalized health recommendations for the specified metric name (e.g., sleep, stress, activity). Use when the user asks for advice about a particular health area.
| Field | Type | Required | Description |
|---|---|---|---|
| metricName | string | required |
Initialize user profile, process health metrics, calculate health score, and generate AI recommendations. This endpoint completes the user setup flow. Use after onboarding to finalize the user account with initial health data.
| Field | Type | Required | Description |
|---|---|---|---|
| user | object | required | |
| data | object[] | optional | |
| onboardingSource | string | optional | |
| onboarding | object | optional |
Stores the user device time zone in user_preferences (IANA name). Used for HealthKit "today" aggregation and timezone-aware schedules. Invalid zone names are rejected with 400.
| Field | Type | Required | Description |
|---|---|---|---|
| timezone | string | required | IANA time zone identifier from the device (e.g. from Intl / RN) |