health-api exposes two AI surfaces on top of a user’s harmonized health data:
chat completionsfor conversational AI with ONVY context injectionai_summariesfor typed, persisted AI outputs that turn raw inputs (meals, workouts, sleep, daily and weekly trends) into structured analysis your product can read back later
ai_summaries rather than as a separate resource.
AI summaries
GET /users/{user_id}/ai/summaries and related routes manage persisted AI summaries. Each summary carries a name (the summary type), a period, structured data, and llm_output with a generated title, text, and optional followup_questions.
Summary types
System-generated summaries are produced asynchronously when the underlying data becomes available. You consume them through the same list and detail routes regardless of who triggered the generation.
Read AI summaries
name, start_date, end_date, and limit. Treat the returned page and next_page as opaque pagination tokens.
Create a meal summary
The current public create surface acceptstype=meal:
description or an image_base64. The response returns a MealSummary with data (calories, macros, glucose impact, healthiness score) and llm_output (title, text, follow-up questions).
Meal endpoint vs AI summary endpoint
POST /users/{user_id}/nutrition/meals is the higher-level meal flow. It stores the meal, runs nutrition analysis asynchronously, links the resulting MealSummary via summary_id, and emits a meals:updated webhook when analysis completes. Use the meals endpoint when you want a meal record in your timeline; use POST /users/{user_id}/ai/summaries when you only want the AI analysis.
User feedback on summaries
PATCH /users/{user_id}/ai/summaries/{summary_id} updates user_comment and user_rating (-1, 0, 1) without re-running generation. PUT regenerates the llm_output for the same summary identifier.
Chat completions
POST /users/{user_id}/chat/completions is an OpenAI-compatible chat surface that injects ONVY context for the user.
Request body highlights:
messagesmodeltemperaturemax_tokensstreamexclude_context
exclude_context lets you suppress parts of ONVY enrichment, for example knowledge, scores, workouts, facts, or all. Otherwise the call automatically uses the same harmonized health context that powers AI summaries: scores, workouts, facts, and knowledge matches for the user.
Completions are persisted. Use GET /users/{user_id}/chat/completions to list them, GET /users/{user_id}/chat/completions/{completion_id} to read one, and PATCH to update fields such as user feedback.
Usage limits
AI-bearing operations draw on a per-project monthly processing quota. It is a single combined budget across the operations that incur model cost — chat completions, AI summary generation, and lab-test extraction — and it is cost-weighted, so a heavier operation (such as a lab extraction) consumes more of the budget than a lighter one (a single chat turn). The window is a tumbling UTC calendar month, so the budget resets at the start of each month. The quota is configured by ONVY on a per-project basis. Most projects run without a quota; one is applied where cost needs to be bounded, for example an evaluation sandbox. When a project’s monthly quota is exhausted:- Synchronous calls that return generated output — for example
POST /users/{user_id}/chat/completions— return HTTP429with an OpenAI-style error object whosecodeisrate_limit_exceeded. The model is not called, so a rejected request incurs no spend. - Asynchronous, system-triggered generation — such as system summaries and lab-test extraction — is skipped for the rest of the window; the summary is simply not produced until the quota resets, and no partial output is persisted.
An operation counts against the quota when it is attempted, including when the model call itself later fails — a failed attempt is not refunded. If you expect to reach the limit during an evaluation, contact ONVY to review your project’s quota rather than retrying.
Webhook events for AI outputs
Subscribe toai_summaries:* to react to summary generation, regeneration, and updates. meals:* events also signal when a meal’s summary_id becomes available after async analysis.