{"openapi":"3.1.0","info":{"title":"Tally API","version":"0.1.0"},"paths":{"/api/health":{"get":{"summary":"Health","operationId":"health_api_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Health Api Health Get"}}}}}}},"/api/logs":{"post":{"summary":"Create Log Endpoint","description":"§5: JSON body (text path) — or multipart with an audio blob + the same\nfields (voice path, create_log_voice above), which is the only way to get\nthe capture_failure response.","operationId":"create_log_endpoint_api_logs_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LogCreate"}},"multipart/form-data":{"schema":{"properties":{"audio":{"type":"string","format":"binary"},"id":{"type":"string","format":"uuid"},"captured_at":{"type":"string","format":"date-time"},"tz":{"type":"string"},"capture_fallback":{"type":"boolean","default":false},"capture_error":{"type":"string"}},"type":"object","required":["audio","id","captured_at","tz"]}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/LogCreateResponse"},{"$ref":"#/components/schemas/CaptureFailureResponse"}],"title":"Response Create Log Endpoint Api Logs Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/logs/{log_id}":{"get":{"summary":"Get Log","operationId":"get_log_api_logs__log_id__get","parameters":[{"name":"log_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Log Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LogPollResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"x-tally-scope":"write"},"delete":{"summary":"Discard Log","description":"§5: discard a staged log — status 'discarded' is adherence-relevant\ndata (§9), so sheet close must land here, not just drop client state.","operationId":"discard_log_api_logs__log_id__delete","parameters":[{"name":"log_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Log Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiscardResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/logs/{log_id}/timings":{"patch":{"summary":"Patch Timings","description":"§9: staged_ms has exactly one write path — this one — and it writes\nonly while NULL, so the first render's timing can never be overwritten.","operationId":"patch_timings_api_logs__log_id__timings_patch","parameters":[{"name":"log_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Log Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TimingsPatch"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TimingsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/logs/{log_id}/items/{item_index}":{"delete":{"summary":"Remove Staged Item","description":"§7.1: removing a staged row writes item_resolutions.status='removed'\nimmediately, so the staging error stays visible in telemetry without\nwaiting for commit (commit-time absence remains the backstop). A removed\nrow never writes an alias and never reaches entries.","operationId":"remove_staged_item_api_logs__log_id__items__item_index__delete","parameters":[{"name":"log_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Log Id"}},{"name":"item_index","in":"path","required":true,"schema":{"type":"integer","title":"Item Index"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemoveItemResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/resolve/tier3":{"post":{"summary":"Kick Tier3","operationId":"kick_tier3_api_resolve_tier3_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Tier3KickRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StagedItem"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/resolve":{"post":{"summary":"Resolve Item","operationId":"resolve_item_api_resolve_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResolveRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StagedItem"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/resolve/answer":{"post":{"summary":"Answer Question","operationId":"answer_question_api_resolve_answer_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnswerRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StagedItem"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/logs/{log_id}/commit":{"post":{"summary":"Commit Log","operationId":"commit_log_api_logs__log_id__commit_post","parameters":[{"name":"log_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Log Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommitRequestIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommitResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/logs/{log_id}/commit-item":{"post":{"summary":"Commit Item","operationId":"commit_item_api_logs__log_id__commit_item_post","parameters":[{"name":"log_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Log Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommitItemRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DayTotals"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/diary":{"get":{"summary":"Get Diary","operationId":"get_diary_api_diary_get","parameters":[{"name":"date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Date"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiaryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/entries/{entry_id}":{"patch":{"summary":"Patch Entry","operationId":"patch_entry_api_entries__entry_id__patch","parameters":[{"name":"entry_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Entry Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntryPatch"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntryPatchResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"summary":"Delete Entry","operationId":"delete_entry_api_entries__entry_id__delete","parameters":[{"name":"entry_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Entry Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DayTotals"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/foods/barcode":{"get":{"summary":"Lookup Barcode","operationId":"lookup_barcode_api_foods_barcode_get","parameters":[{"name":"code","in":"query","required":true,"schema":{"type":"string","title":"Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BarcodeResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"x-tally-scope":"write"}},"/api/logs/from-food":{"post":{"summary":"Create Log From Food","operationId":"create_log_from_food_api_logs_from_food_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FromFoodRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LogResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/logs/photo":{"post":{"summary":"Create Log Photo","description":"Photo → vision → the identical cascade + staging; input_mode='photo'.\nIdempotent by client id like POST /api/logs (§8.6). `tz` is optional —\nwithout it the meal is inferred in the settings timezone.\n\nThe non-streaming entry. The + sheet's photo lane goes through the chat\n(POST /api/agent, §6.4) since 2026-09-08 and shares `_stage_photo` with\nthis route; nothing here changed with it.","operationId":"create_log_photo_api_logs_photo_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_create_log_photo_api_logs_photo_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LogCreateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/foods/search":{"get":{"summary":"Search Foods","operationId":"search_foods_api_foods_search_get","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string","title":"Q"}},{"name":"source","in":"query","required":false,"schema":{"enum":["all","local","fdc"],"type":"string","default":"all","title":"Source"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FoodSearchResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/foods/recent":{"get":{"summary":"List Recent Foods","description":"The foods this account has logged, newest first, one per food, capped\nat foods_repo.RECENT_FOODS_CAP (200) — the Search lane's \"previously\nadded\" list (§7.4). Every hit is already cached (food_id set), so a pick\ngoes straight to /api/logs/from-food. Declared before /api/foods/{food_id}\nso the literal path wins.","operationId":"list_recent_foods_api_foods_recent_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/FoodHit"},"type":"array","title":"Response List Recent Foods Api Foods Recent Get"}}}}}}},"/api/foods/select":{"post":{"summary":"Select Food","operationId":"select_food_api_foods_select_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SelectRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SelectResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/foods/{food_id}":{"get":{"summary":"Get Food Detail","operationId":"get_food_detail_api_foods__food_id__get","parameters":[{"name":"food_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Food Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FoodDetail"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/meals":{"get":{"summary":"List Meals","description":"Active macros; include_inactive=1 adds the deactivated ones (the\nLibrary lists them under \"inactive\" with a reactivate action, §8.4).","operationId":"list_meals_api_meals_get","parameters":[{"name":"include_inactive","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Inactive"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/MealOut"},"title":"Response List Meals Api Meals Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"summary":"Create Meal","operationId":"create_meal_api_meals_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MealCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MealOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/meals/{meal_id}":{"patch":{"summary":"Patch Meal","operationId":"patch_meal_api_meals__meal_id__patch","parameters":[{"name":"meal_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Meal Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MealPatch"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MealOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"summary":"Delete Meal","description":"§8.4: delete = deactivate. Idempotent; the row stays.","operationId":"delete_meal_api_meals__meal_id__delete","parameters":[{"name":"meal_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Meal Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MealDeleteResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/meals/from-log":{"post":{"summary":"Meal From Log","description":"\"Save as meal\": the macro's items are the log's committed entries\n(food, serving, qty as committed). Create-or-update by name, so saying\n\"save this as my usual breakfast\" twice updates the one macro.","operationId":"meal_from_log_api_meals_from_log_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MealFromLog"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MealOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/aliases":{"get":{"summary":"List Aliases","operationId":"list_aliases_api_aliases_get","parameters":[{"name":"phrase","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phrase"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AliasListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/aliases/{alias_id}":{"patch":{"summary":"Patch Alias","operationId":"patch_alias_api_aliases__alias_id__patch","parameters":[{"name":"alias_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Alias Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AliasPatch"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AliasRow"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"summary":"Delete Alias","operationId":"delete_alias_api_aliases__alias_id__delete","parameters":[{"name":"alias_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Alias Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AliasDeleteResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/history":{"get":{"summary":"Get History","operationId":"get_history_api_history_get","parameters":[{"name":"range","in":"query","required":false,"schema":{"enum":["3d","w","m","y"],"type":"string","default":"w","title":"Range"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HistoryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/settings":{"get":{"summary":"Get Settings","operationId":"get_settings_api_settings_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingsResponse"}}}}}},"put":{"summary":"Put Settings","operationId":"put_settings_api_settings_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingsUpdate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/settings/goals/compute":{"post":{"summary":"Compute Goals","operationId":"compute_goals_api_settings_goals_compute_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoalInputs"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoalProposal"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"x-tally-scope":"read"}},"/api/metrics":{"get":{"summary":"Get Metrics","operationId":"get_metrics_api_metrics_get","parameters":[{"name":"range","in":"query","required":false,"schema":{"type":"string","default":"12w","title":"Range"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MetricsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/me":{"get":{"summary":"Get Me","operationId":"get_me_api_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeResponse"}}}}}}},"/api/weights":{"get":{"summary":"Get Weights","operationId":"get_weights_api_weights_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":3660,"minimum":1,"default":90,"title":"Days"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WeightsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"summary":"Put Weight","operationId":"put_weight_api_weights_put","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WeightPut"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WeightEntry"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/agent":{"post":{"summary":"Agent Text","description":"Text: a same-id retry re-attaches to its live run; else the claim\nbefore the stream, then the agent's events → `done`. The multipart form\n(audio + the same fields) is the other content type on this path, as for\nPOST /api/logs.","operationId":"agent_text_api_agent_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LogCreate"}},"multipart/form-data":{"schema":{"properties":{"audio":{"type":"string","format":"binary"},"id":{"type":"string","format":"uuid"},"captured_at":{"type":"string","format":"date-time"},"tz":{"type":"string"},"capture_fallback":{"type":"boolean","default":false},"capture_error":{"type":"string"},"history":{"type":"string","description":"JSON array of AgentTurn — the chat so far (§6.4)"},"image":{"type":"string","format":"binary","description":"a plate photo — the §3.4b lane as a chat turn; exactly one of audio or image"},"text":{"type":"string","description":"said alongside an image — makes it a chat turn the agent can see (§6.4)"},"photo_log_id":{"type":"string","format":"uuid","description":"the staged photo log this conversation is tuning (§3.4b)"},"lat":{"type":"number","description":"the phone's latitude when the photo was taken"},"lng":{"type":"number","description":"the phone's longitude when the photo was taken"},"accuracy":{"type":"number","description":"how far off that fix may be, in meters"}},"type":"object","required":["id","captured_at","tz"]}}},"required":true},"responses":{"200":{"description":"A stream of newline-delimited JSON events, one AgentEvent per line, ending with `done` or `error`.","content":{"application/x-ndjson":{"schema":{"$ref":"#/components/schemas/AgentEvent","type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/oura":{"get":{"summary":"Get Status","operationId":"get_status_api_oura_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OuraStatus"}}}}}}},"/api/oura/authorize":{"get":{"summary":"Authorize","operationId":"authorize_api_oura_authorize_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OuraAuthorize"}}}}}}},"/api/oura/sync":{"post":{"summary":"Post Sync","operationId":"post_sync_api_oura_sync_post","parameters":[{"name":"force","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Force"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OuraSync"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/keys":{"get":{"summary":"List Keys","operationId":"list_keys_api_keys_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ApiKeyOut"},"type":"array","title":"Response List Keys Api Keys Get"}}}}}},"post":{"summary":"Create Key","operationId":"create_key_api_keys_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyCreate"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyCreated"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/keys/{key_id}":{"delete":{"summary":"Revoke Key","operationId":"revoke_key_api_keys__key_id__delete","parameters":[{"name":"key_id","in":"path","required":true,"schema":{"type":"string","title":"Key Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"AdherencePoint":{"properties":{"week":{"type":"string","format":"date","title":"Week"},"days_logged":{"type":"integer","title":"Days Logged"}},"type":"object","required":["week","days_logged"],"title":"AdherencePoint"},"AgentDoneEvent":{"properties":{"type":{"type":"string","const":"done","title":"Type","default":"done"},"log":{"anyOf":[{"$ref":"#/components/schemas/LogCreateResponse"},{"$ref":"#/components/schemas/CaptureFailureResponse"}],"title":"Log"},"replay":{"type":"boolean","title":"Replay","default":false}},"type":"object","required":["log"],"title":"AgentDoneEvent","description":"The last event of a successful run: what POST /api/logs would have\nanswered. `replay` (§8.6): a same-id retry answered from the stored log\nrather than a run this request made or attached to — no tool lines and no\nreply came with it (the reply is not stored, BACKLOG 139)."},"AgentErrorEvent":{"properties":{"type":{"type":"string","const":"error","title":"Type","default":"error"},"status":{"type":"integer","title":"Status"},"detail":{"type":"string","title":"Detail"}},"type":"object","required":["status","detail"],"title":"AgentErrorEvent","description":"The last event of a failed run, with the HTTP status it would have been."},"AgentEvent":{"oneOf":[{"$ref":"#/components/schemas/AgentTranscriptEvent"},{"$ref":"#/components/schemas/AgentToolCallEvent"},{"$ref":"#/components/schemas/AgentToolResultEvent"},{"$ref":"#/components/schemas/AgentReplyEvent"},{"$ref":"#/components/schemas/AgentDoneEvent"},{"$ref":"#/components/schemas/AgentErrorEvent"}],"title":"AgentEvent","description":"One line of the POST /api/agent stream.","discriminator":{"propertyName":"type","mapping":{"done":"#/components/schemas/AgentDoneEvent","error":"#/components/schemas/AgentErrorEvent","reply":"#/components/schemas/AgentReplyEvent","tool_call":"#/components/schemas/AgentToolCallEvent","tool_result":"#/components/schemas/AgentToolResultEvent","transcript":"#/components/schemas/AgentTranscriptEvent"}}},"AgentOutcome":{"properties":{"reply":{"type":"string","title":"Reply"},"weight":{"anyOf":[{"$ref":"#/components/schemas/WeightEntry"},{"type":"null"}]},"options":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Options"},"discarded":{"anyOf":[{"items":{"type":"string","format":"uuid"},"type":"array"},{"type":"null"}],"title":"Discarded"},"updated":{"anyOf":[{"$ref":"#/components/schemas/LogPollResponse"},{"type":"null"}]}},"type":"object","required":["reply"],"title":"AgentOutcome","description":"What the agent lane did with the utterance (§6.4): its one-sentence\nreply, the weigh-in it recorded, if any, the answers it offers when the\nreply is a clarifying question (`options`, tappable in the chat), and the\nearlier staged logs it discarded because this turn replaces them\n(`discarded`). Staged items ride the LogResponse as on any other log.\nAssembled from what the tools did, never from what the model said."},"AgentReplyEvent":{"properties":{"type":{"type":"string","const":"reply","title":"Type","default":"reply"},"text":{"type":"string","title":"Text"},"options":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Options"}},"type":"object","required":["text"],"title":"AgentReplyEvent","description":"The agent's reply — or its clarifying question, when `options` carries\nthe 2–4 answers the chat offers as chips (§6.4)."},"AgentToolCallEvent":{"properties":{"type":{"type":"string","const":"tool_call","title":"Type","default":"tool_call"},"id":{"type":"string","title":"Id"},"name":{"type":"string","title":"Name"},"args":{"additionalProperties":true,"type":"object","title":"Args"}},"type":"object","required":["id","name","args"],"title":"AgentToolCallEvent","description":"The agent called a tool: `name` (log_food, log_estimate, log_weight,\ndiscard_log, past_foods, save_meal, update_meal, adjust_photo, web_search)\nwith `args` as the model passed them. `read_photo` and `look_up` are the\nexceptions — no model called them: the photo turn (§3.4b) emits each pair\nitself so the chat can show the vision call and the lookups while they run."},"AgentToolResultEvent":{"properties":{"type":{"type":"string","const":"tool_result","title":"Type","default":"tool_result"},"id":{"type":"string","title":"Id"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"output":{"title":"Output"}},"type":"object","required":["id"],"title":"AgentToolResultEvent","description":"What the tool answered (sanitized: never macros — the staged list shows\nthose). For web_search: the sources it consulted."},"AgentTranscriptEvent":{"properties":{"type":{"type":"string","const":"transcript","title":"Type","default":"transcript"},"text":{"type":"string","title":"Text"}},"type":"object","required":["text"],"title":"AgentTranscriptEvent","description":"The spoken utterance as transcribed — the chat's user bubble (voice only)."},"AgentTurn":{"properties":{"role":{"type":"string","enum":["user","agent"],"title":"Role"},"text":{"type":"string","title":"Text"},"log_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Log Id"},"items":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Items"},"state":{"anyOf":[{"type":"string","enum":["staged","committed","discarded"]},{"type":"null"}],"title":"State"}},"type":"object","required":["role","text"],"title":"AgentTurn","description":"One earlier turn of the Agent chat (§6.4), as the client remembers it:\nwhat the person said, what the agent replied, and — for a turn that\nstaged a log — the log's id, its rows in words (never macros) and where\nit stands, so a follow-up (\"actually I only had half\") can name it."},"AliasDeleteResponse":{"properties":{"id":{"type":"string","title":"Id"},"deleted":{"type":"boolean","title":"Deleted","default":true}},"type":"object","required":["id"],"title":"AliasDeleteResponse"},"AliasListResponse":{"properties":{"phrase":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phrase"},"phrase_norm":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phrase Norm"},"aliases":{"items":{"$ref":"#/components/schemas/AliasRow"},"type":"array","title":"Aliases"}},"type":"object","required":["aliases"],"title":"AliasListResponse"},"AliasPatch":{"properties":{"pinned":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Pinned"},"default_serving_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Default Serving Id"},"default_qty":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Default Qty"}},"type":"object","title":"AliasPatch"},"AliasRow":{"properties":{"id":{"type":"string","title":"Id"},"alias_norm":{"type":"string","title":"Alias Norm"},"food_id":{"type":"string","title":"Food Id"},"food_name":{"type":"string","title":"Food Name"},"brand":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Brand"},"source":{"type":"string","title":"Source"},"use_count":{"type":"integer","title":"Use Count"},"pinned":{"type":"boolean","title":"Pinned"},"usual":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Usual"},"default_serving_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Default Serving Id"},"default_serving":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Default Serving"},"default_qty":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Default Qty"},"state_answer":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State Answer"},"last_used_at":{"type":"string","format":"date-time","title":"Last Used At"},"last_explicit_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Explicit At"},"rejected_count":{"type":"integer","title":"Rejected Count"},"origin":{"type":"string","title":"Origin"}},"type":"object","required":["id","alias_norm","food_id","food_name","source","use_count","pinned","last_used_at","rejected_count","origin"],"title":"AliasRow","description":"One aliases row ⋈ its food (route-local response shape)."},"Alternate":{"properties":{"source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source"},"source_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Id"},"food_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Food Id"},"label":{"type":"string","title":"Label"},"usual":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Usual"}},"type":"object","required":["label"],"title":"Alternate"},"Answer":{"properties":{"label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Label"},"source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source"},"source_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Id"},"food_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Food Id"},"text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Text"}},"type":"object","title":"Answer","description":"A tapped id-bearing option (source + source_id, or a cached food_id,\nplus label) or free text."},"AnswerRequest":{"properties":{"log_id":{"type":"string","format":"uuid","title":"Log Id"},"item_index":{"type":"integer","title":"Item Index"},"answer":{"$ref":"#/components/schemas/Answer"}},"type":"object","required":["log_id","item_index","answer"],"title":"AnswerRequest"},"ApiKeyCreate":{"properties":{"label":{"type":"string","maxLength":80,"minLength":1,"title":"Label"},"scopes":{"type":"string","enum":["read","read_write"],"title":"Scopes","default":"read_write"},"expires_in_days":{"anyOf":[{"type":"integer","enum":[30,90,365]},{"type":"null"}],"title":"Expires In Days"}},"type":"object","required":["label"],"title":"ApiKeyCreate"},"ApiKeyCreated":{"properties":{"key":{"$ref":"#/components/schemas/ApiKeyOut"},"secret":{"type":"string","title":"Secret"}},"type":"object","required":["key","secret"],"title":"ApiKeyCreated"},"ApiKeyOut":{"properties":{"id":{"type":"string","title":"Id"},"label":{"type":"string","title":"Label"},"scopes":{"items":{"type":"string"},"type":"array","title":"Scopes"},"redacted":{"type":"string","title":"Redacted"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"last_used_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Used At"},"expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Expires At"},"revoked_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Revoked At"}},"type":"object","required":["id","label","scopes","redacted","created_at","last_used_at","expires_at","revoked_at"],"title":"ApiKeyOut"},"BarcodeFood":{"properties":{"id":{"type":"string","title":"Id"},"display_name":{"type":"string","title":"Display Name"},"brand":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Brand"},"source":{"type":"string","title":"Source"},"servings":{"items":{"$ref":"#/components/schemas/ServingOption"},"type":"array","title":"Servings"},"macros_per_100g":{"anyOf":[{"additionalProperties":{"type":"number"},"type":"object"},{"type":"null"}],"title":"Macros Per 100G"}},"type":"object","required":["id","display_name","source","servings"],"title":"BarcodeFood","description":"The cached food a barcode resolved to — enough to render the pick and\nto call /api/logs/from-food with its id."},"BarcodeResponse":{"properties":{"found":{"type":"boolean","title":"Found"},"food":{"anyOf":[{"$ref":"#/components/schemas/BarcodeFood"},{"type":"null"}]}},"type":"object","required":["found"],"title":"BarcodeResponse"},"BodyProfile":{"properties":{"height_cm":{"anyOf":[{"type":"number","maximum":250.0,"minimum":100.0},{"type":"null"}],"title":"Height Cm"},"weight_kg":{"anyOf":[{"type":"number","maximum":300.0,"minimum":30.0},{"type":"null"}],"title":"Weight Kg"},"age":{"anyOf":[{"type":"integer","maximum":120.0,"minimum":13.0},{"type":"null"}],"title":"Age"},"sex":{"anyOf":[{"type":"string","enum":["male","female"]},{"type":"null"}],"title":"Sex"},"activity_level":{"anyOf":[{"type":"string","enum":["sedentary","light","moderate","active","very_active"]},{"type":"null"}],"title":"Activity Level"},"goal_weight_kg":{"anyOf":[{"type":"number","maximum":300.0,"minimum":30.0},{"type":"null"}],"title":"Goal Weight Kg"},"weekly_rate_kg":{"anyOf":[{"type":"number","maximum":1.0,"minimum":0.0},{"type":"null"}],"title":"Weekly Rate Kg"},"units":{"anyOf":[{"type":"string","enum":["metric","imperial"]},{"type":"null"}],"title":"Units"}},"type":"object","title":"BodyProfile","description":"settings.body — every field optional so a partially filled wizard can be\nsaved; the compute endpoint requires the full set (GoalInputs)."},"Body_create_log_photo_api_logs_photo_post":{"properties":{"image":{"type":"string","contentMediaType":"application/octet-stream","title":"Image"},"id":{"type":"string","format":"uuid","title":"Id"},"captured_at":{"type":"string","format":"date-time","title":"Captured At"},"meal_hint":{"anyOf":[{"$ref":"#/components/schemas/Meal"},{"type":"null"}]},"tz":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tz"}},"type":"object","required":["image","id","captured_at"],"title":"Body_create_log_photo_api_logs_photo_post"},"CaptureFailureResponse":{"properties":{"log_id":{"type":"string","format":"uuid","title":"Log Id"},"status":{"type":"string","const":"capture_failure","title":"Status","default":"capture_failure"},"capture_error":{"type":"string","title":"Capture Error","default":"empty_transcript"},"client_capture_error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Capture Error"}},"type":"object","required":["log_id"],"title":"CaptureFailureResponse","description":"§5: an audio log whose transcript came back empty/near-empty. The\nclient prompts retype; the logs row records the failure so the §9\ntelemetry counter increments. NEVER returned as an empty staged log."},"CommitItemError":{"properties":{"item_index":{"type":"integer","title":"Item Index"},"error":{"type":"string","title":"Error"}},"type":"object","required":["item_index","error"],"title":"CommitItemError","description":"One core-macros refusal (§3.5): the item stayed uncommitted as\nneeds_input; the rest of the log committed."},"CommitItemRequest":{"properties":{"item_index":{"type":"integer","title":"Item Index"},"item":{"$ref":"#/components/schemas/StagedItem"}},"type":"object","required":["item_index","item"],"title":"CommitItemRequest","description":"§5: {item_index, StagedItem} — the late-straggler append."},"CommitRequestIn":{"properties":{"items":{"items":{"$ref":"#/components/schemas/StagedItem"},"type":"array","title":"Items"},"save_intent":{"anyOf":[{"$ref":"#/components/schemas/SaveIntent"},{"type":"null"}]}},"type":"object","required":["items"],"title":"CommitRequestIn","description":"CommitRequest + the §3.5 step-4 / §8.4 \"Save as meal\" tap: the staging\nsheet names the meal and the commit creates/updates the macro from the\nitems it writes (route-local, additive over models.py)."},"CommitResponse":{"properties":{"kcal":{"type":"number","title":"Kcal"},"protein_g":{"type":"number","title":"Protein G"},"carb_g":{"type":"number","title":"Carb G"},"fat_g":{"type":"number","title":"Fat G"},"targets":{"$ref":"#/components/schemas/MacroTargets"},"exercise_kcal":{"type":"integer","title":"Exercise Kcal","default":0},"errors":{"items":{"$ref":"#/components/schemas/CommitItemError"},"type":"array","title":"Errors","default":[]},"saved_meal":{"anyOf":[{"$ref":"#/components/schemas/SavedMealNote"},{"type":"null"}]},"totals_day":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Totals Day"}},"type":"object","required":["kcal","protein_g","carb_g","fat_g","targets"],"title":"CommitResponse","description":"DayTotals + per-item refusals. A 200 with non-empty errors is a PARTIAL\ncommit — the client must keep refused rows visible (verify-me / pending),\nnever close over them (§3.5; the silent-protein-hole failure class).\nThe totals are for the day the entries landed on (§7.2 when-shift aware)."},"DayStat":{"properties":{"kcal":{"type":"number","title":"Kcal"},"protein_g":{"type":"number","title":"Protein G"},"carb_g":{"type":"number","title":"Carb G"},"fat_g":{"type":"number","title":"Fat G"},"date":{"type":"string","format":"date","title":"Date"},"entries":{"type":"integer","title":"Entries"},"logged":{"type":"boolean","title":"Logged"},"fiber_g":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Fiber G"},"meals":{"anyOf":[{"additionalProperties":{"$ref":"#/components/schemas/MacroSums"},"type":"object"},{"type":"null"}],"title":"Meals"},"targets":{"anyOf":[{"$ref":"#/components/schemas/MacroTargets"},{"type":"null"}]}},"type":"object","required":["kcal","protein_g","carb_g","fat_g","date","entries","logged"],"title":"DayStat"},"DayTotals":{"properties":{"kcal":{"type":"number","title":"Kcal"},"protein_g":{"type":"number","title":"Protein G"},"carb_g":{"type":"number","title":"Carb G"},"fat_g":{"type":"number","title":"Fat G"},"targets":{"$ref":"#/components/schemas/MacroTargets"},"exercise_kcal":{"type":"integer","title":"Exercise Kcal","default":0}},"type":"object","required":["kcal","protein_g","carb_g","fat_g","targets"],"title":"DayTotals","description":"Consumed totals for the day vs targets (§5: commit response, diary)."},"DemoQuota":{"properties":{"limit":{"type":"integer","title":"Limit"},"used_today":{"type":"integer","title":"Used Today"},"resets_at":{"type":"string","title":"Resets At"}},"type":"object","required":["limit","used_today","resets_at"],"title":"DemoQuota"},"DiaryEntry":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"meal":{"$ref":"#/components/schemas/Meal"},"food":{"$ref":"#/components/schemas/FoodRef"},"serving":{"$ref":"#/components/schemas/ServingRef"},"qty":{"type":"number","title":"Qty"},"macros":{"$ref":"#/components/schemas/Macros"},"logged_at":{"type":"string","format":"date-time","title":"Logged At"},"grams":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Grams"},"source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source"},"web_source":{"anyOf":[{"$ref":"#/components/schemas/WebSource"},{"type":"null"}]},"estimated":{"type":"string","enum":["none","portion"],"title":"Estimated","default":"none"}},"type":"object","required":["id","meal","food","serving","qty","macros","logged_at"],"title":"DiaryEntry","description":"Response-only shape (route-local; the wire contracts live in models.py).\nThe display fields default to None because routes/entries.py builds this\nmodel too (it has no source/web_source at hand)."},"DiaryResponse":{"properties":{"date":{"type":"string","format":"date","title":"Date"},"meals":{"additionalProperties":{"items":{"$ref":"#/components/schemas/DiaryEntry"},"type":"array"},"type":"object","title":"Meals"},"totals":{"$ref":"#/components/schemas/DayTotals"}},"type":"object","required":["date","meals","totals"],"title":"DiaryResponse"},"DiscardResponse":{"properties":{"log_id":{"type":"string","format":"uuid","title":"Log Id"},"status":{"type":"string","const":"discarded","title":"Status","default":"discarded"}},"type":"object","required":["log_id"],"title":"DiscardResponse"},"DuplicatePair":{"properties":{"source":{"type":"string","title":"Source"},"food_a":{"type":"string","title":"Food A"},"name_a":{"type":"string","title":"Name A"},"food_b":{"type":"string","title":"Food B"},"name_b":{"type":"string","title":"Name B"}},"type":"object","required":["source","food_a","name_a","food_b","name_b"],"title":"DuplicatePair"},"EntryPatch":{"properties":{"qty":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Qty"},"serving_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Serving Id"},"food_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Food Id"},"meal":{"anyOf":[{"$ref":"#/components/schemas/Meal"},{"type":"null"}]}},"type":"object","title":"EntryPatch","description":"Any subset: qty scales; serving_id re-derives; food_id corrects + learns;\nmeal refiles the entry under another meal and leaves the portion alone."},"EntryPatchResponse":{"properties":{"entry":{"$ref":"#/components/schemas/DiaryEntry"},"totals":{"$ref":"#/components/schemas/DayTotals"}},"type":"object","required":["entry","totals"],"title":"EntryPatchResponse"},"FoodDetail":{"properties":{"id":{"type":"string","title":"Id"},"source":{"type":"string","title":"Source"},"source_id":{"type":"string","title":"Source Id"},"source_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Url"},"name":{"type":"string","title":"Name"},"display_name":{"type":"string","title":"Display Name"},"brand":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Brand"},"food_type":{"type":"string","title":"Food Type"},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"},"state_sensitive":{"type":"boolean","title":"State Sensitive"},"default_serving_id":{"type":"string","title":"Default Serving Id"},"servings":{"items":{"$ref":"#/components/schemas/ServingOption"},"type":"array","title":"Servings"},"per_100g":{"anyOf":[{"additionalProperties":{"type":"number"},"type":"object"},{"type":"null"}],"title":"Per 100G"},"nutrients":{"items":{"$ref":"#/components/schemas/NutrientRow"},"type":"array","title":"Nutrients"},"badge":{"$ref":"#/components/schemas/SourceBadge"},"citation":{"anyOf":[{"$ref":"#/components/schemas/WebSource"},{"type":"null"}]},"provenance":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Provenance"},"payload":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Payload"},"aliases":{"items":{"$ref":"#/components/schemas/AliasRow"},"type":"array","title":"Aliases"},"refreshed_at":{"type":"string","format":"date-time","title":"Refreshed At"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","source","source_id","name","display_name","food_type","state_sensitive","default_serving_id","servings","nutrients","badge","aliases","refreshed_at","created_at"],"title":"FoodDetail"},"FoodHit":{"properties":{"source":{"type":"string","title":"Source"},"source_id":{"type":"string","title":"Source Id"},"label":{"type":"string","title":"Label"},"brand":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Brand"},"food_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Food Id"},"data_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Data Type"},"protein_per_100g":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Protein Per 100G"},"kcal_per_100g":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Kcal Per 100G"},"per_100ml":{"type":"boolean","title":"Per 100Ml","default":false}},"type":"object","required":["source","source_id","label"],"title":"FoodHit","description":"One condensed search hit — enough to render a row and to select it."},"FoodRef":{"properties":{"id":{"type":"string","title":"Id"},"name":{"type":"string","title":"Name"},"brand":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Brand"}},"type":"object","required":["id","name"],"title":"FoodRef"},"FoodSearchResponse":{"properties":{"query":{"type":"string","title":"Query"},"local":{"items":{"$ref":"#/components/schemas/FoodHit"},"type":"array","title":"Local"},"generic":{"items":{"$ref":"#/components/schemas/FoodHit"},"type":"array","title":"Generic"},"branded":{"items":{"$ref":"#/components/schemas/FoodHit"},"type":"array","title":"Branded"},"fdc_error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Fdc Error"}},"type":"object","required":["query","local","generic","branded"],"title":"FoodSearchResponse"},"FromFoodRequest":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"food_id":{"type":"string","format":"uuid","title":"Food Id"},"serving_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Serving Id"},"qty":{"anyOf":[{"type":"number","maximum":1000.0,"exclusiveMinimum":0.0},{"type":"null"}],"title":"Qty"},"meal_hint":{"anyOf":[{"$ref":"#/components/schemas/Meal"},{"type":"null"}]},"input_mode":{"type":"string","enum":["barcode","search"],"title":"Input Mode"},"captured_at":{"type":"string","format":"date-time","title":"Captured At"}},"type":"object","required":["id","food_id","input_mode","captured_at"],"title":"FromFoodRequest"},"GoalInputs":{"properties":{"height_cm":{"type":"number","maximum":250.0,"minimum":100.0,"title":"Height Cm"},"weight_kg":{"type":"number","maximum":300.0,"minimum":30.0,"title":"Weight Kg"},"age":{"type":"integer","maximum":120.0,"minimum":13.0,"title":"Age"},"sex":{"type":"string","enum":["male","female"],"title":"Sex"},"activity_level":{"type":"string","enum":["sedentary","light","moderate","active","very_active"],"title":"Activity Level"},"goal_weight_kg":{"anyOf":[{"type":"number","maximum":300.0,"minimum":30.0},{"type":"null"}],"title":"Goal Weight Kg"},"weekly_rate_kg":{"anyOf":[{"type":"number","minimum":0.0},{"type":"null"}],"title":"Weekly Rate Kg"},"protein_g_per_kg":{"anyOf":[{"type":"number","maximum":4.0,"exclusiveMinimum":0.0},{"type":"null"}],"title":"Protein G Per Kg"},"fat_g_per_kg":{"anyOf":[{"type":"number","maximum":3.0,"exclusiveMinimum":0.0},{"type":"null"}],"title":"Fat G Per Kg"}},"type":"object","required":["height_cm","weight_kg","age","sex","activity_level"],"title":"GoalInputs"},"GoalProposal":{"properties":{"bmr":{"type":"integer","title":"Bmr"},"tdee":{"type":"integer","title":"Tdee"},"daily_delta_kcal":{"type":"integer","title":"Daily Delta Kcal"},"targets":{"$ref":"#/components/schemas/MacroTargets"},"protein_g_per_kg":{"type":"number","title":"Protein G Per Kg"},"fat_g_per_kg":{"type":"number","title":"Fat G Per Kg"},"notes":{"items":{"type":"string"},"type":"array","title":"Notes"}},"type":"object","required":["bmr","tdee","daily_delta_kcal","targets","protein_g_per_kg","fat_g_per_kg","notes"],"title":"GoalProposal"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"HistoryResponse":{"properties":{"range":{"type":"string","enum":["3d","w","m","y"],"title":"Range"},"timezone":{"type":"string","title":"Timezone"},"start":{"type":"string","format":"date","title":"Start"},"end":{"type":"string","format":"date","title":"End"},"targets":{"$ref":"#/components/schemas/MacroTargets"},"streak":{"type":"integer","title":"Streak"},"baseline_days_per_week":{"type":"number","title":"Baseline Days Per Week"},"days":{"items":{"$ref":"#/components/schemas/DayStat"},"type":"array","title":"Days"},"weeks":{"items":{"$ref":"#/components/schemas/WeekStat"},"type":"array","title":"Weeks"}},"type":"object","required":["range","timezone","start","end","targets","streak","baseline_days_per_week","days","weeks"],"title":"HistoryResponse"},"HitRatePoint":{"properties":{"week":{"type":"string","format":"date","title":"Week"},"items":{"type":"integer","title":"Items"},"hits":{"type":"integer","title":"Hits"},"rate":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Rate"},"items_incl_discarded":{"type":"integer","title":"Items Incl Discarded"},"hits_incl_discarded":{"type":"integer","title":"Hits Incl Discarded"},"rate_incl_discarded":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Rate Incl Discarded"}},"type":"object","required":["week","items","hits","rate","items_incl_discarded","hits_incl_discarded","rate_incl_discarded"],"title":"HitRatePoint"},"LatencyPoint":{"properties":{"week":{"type":"string","format":"date","title":"Week"},"committed_logs":{"type":"integer","title":"Committed Logs"},"commit_ms_p50":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Commit Ms P50"},"commit_ms_p90":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Commit Ms P90"},"staged_ms_p50":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Staged Ms P50"},"staged_ms_p90":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Staged Ms P90"}},"type":"object","required":["week","committed_logs","commit_ms_p50","commit_ms_p90","staged_ms_p50","staged_ms_p90"],"title":"LatencyPoint"},"LogCreate":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"text":{"type":"string","title":"Text"},"captured_at":{"type":"string","format":"date-time","title":"Captured At"},"tz":{"type":"string","title":"Tz"},"capture_fallback":{"type":"boolean","title":"Capture Fallback","default":false},"capture_error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Capture Error"},"history":{"anyOf":[{"items":{"$ref":"#/components/schemas/AgentTurn"},"type":"array"},{"type":"null"}],"title":"History"},"photo_log_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Photo Log Id"}},"type":"object","required":["id","text","captured_at","tz"],"title":"LogCreate"},"LogCreateResponse":{"properties":{"log_id":{"type":"string","format":"uuid","title":"Log Id"},"meal":{"$ref":"#/components/schemas/Meal"},"items":{"items":{"$ref":"#/components/schemas/StagedItem"},"type":"array","title":"Items"},"logged_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Logged At"},"saved_meal":{"anyOf":[{"$ref":"#/components/schemas/SavedMealNote"},{"type":"null"}]},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"},"agent":{"anyOf":[{"$ref":"#/components/schemas/AgentOutcome"},{"type":"null"}]}},"type":"object","required":["log_id","meal","items"],"title":"LogCreateResponse","description":"POST /api/logs: LogResponse + what the agent's meal tools did (§8.4):\n`saved_meal` when a save landed, `note` when it lands at commit or could\nnot — never a silently empty staging list. `agent` carries the agent's\nreply (§6.4) — with zero items it is what the client shows instead of a\nsheet."},"LogPollResponse":{"properties":{"log_id":{"type":"string","format":"uuid","title":"Log Id"},"meal":{"$ref":"#/components/schemas/Meal"},"items":{"items":{"$ref":"#/components/schemas/StagedItemOut"},"type":"array","title":"Items"},"logged_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Logged At"}},"type":"object","required":["log_id","meal","items"],"title":"LogPollResponse","description":"LogResponse whose items can carry the watchdog's stale flag."},"LogResponse":{"properties":{"log_id":{"type":"string","format":"uuid","title":"Log Id"},"meal":{"$ref":"#/components/schemas/Meal"},"items":{"items":{"$ref":"#/components/schemas/StagedItem"},"type":"array","title":"Items"},"logged_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Logged At"}},"type":"object","required":["log_id","meal","items"],"title":"LogResponse"},"MacroSums":{"properties":{"kcal":{"type":"number","title":"Kcal"},"protein_g":{"type":"number","title":"Protein G"},"carb_g":{"type":"number","title":"Carb G"},"fat_g":{"type":"number","title":"Fat G"}},"type":"object","required":["kcal","protein_g","carb_g","fat_g"],"title":"MacroSums"},"MacroTargets":{"properties":{"kcal":{"type":"number","title":"Kcal"},"protein_g":{"type":"number","title":"Protein G"},"carb_g":{"type":"number","title":"Carb G"},"fat_g":{"type":"number","title":"Fat G"}},"type":"object","required":["kcal","protein_g","carb_g","fat_g"],"title":"MacroTargets"},"Macros":{"properties":{"kcal":{"type":"number","title":"Kcal"},"protein_g":{"type":"number","title":"Protein G"},"carb_g":{"type":"number","title":"Carb G"},"fat_g":{"type":"number","title":"Fat G"},"fiber_g":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Fiber G"}},"additionalProperties":{"type":"number"},"type":"object","required":["kcal","protein_g","carb_g","fat_g"],"title":"Macros","description":"§5: core macros required, fiber optional, extra micros allowed (all numeric)."},"MeResponse":{"properties":{"email":{"type":"string","title":"Email"},"is_owner":{"type":"boolean","title":"Is Owner"},"demo":{"anyOf":[{"$ref":"#/components/schemas/DemoQuota"},{"type":"null"}]},"oura_connected":{"type":"boolean","title":"Oura Connected","default":false}},"type":"object","required":["email","is_owner","demo"],"title":"MeResponse"},"Meal":{"type":"string","enum":["breakfast","lunch","dinner","snack"],"title":"Meal"},"MealCreate":{"properties":{"name":{"type":"string","minLength":1,"title":"Name"},"trigger_phrases":{"items":{"type":"string"},"type":"array","title":"Trigger Phrases","default":[]},"items":{"items":{"$ref":"#/components/schemas/MealItemIn"},"type":"array","title":"Items"}},"type":"object","required":["name","items"],"title":"MealCreate"},"MealDeleteResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"is_active":{"type":"boolean","title":"Is Active","default":false}},"type":"object","required":["id"],"title":"MealDeleteResponse"},"MealFromLog":{"properties":{"log_id":{"type":"string","format":"uuid","title":"Log Id"},"name":{"type":"string","minLength":1,"title":"Name"},"trigger_phrases":{"items":{"type":"string"},"type":"array","title":"Trigger Phrases","default":[]}},"type":"object","required":["log_id","name"],"title":"MealFromLog"},"MealItemIn":{"properties":{"food_id":{"type":"string","title":"Food Id"},"serving_id":{"type":"string","title":"Serving Id"},"qty":{"type":"number","title":"Qty","default":1.0}},"type":"object","required":["food_id","serving_id"],"title":"MealItemIn"},"MealItemOut":{"properties":{"food_id":{"type":"string","title":"Food Id"},"serving_id":{"type":"string","title":"Serving Id"},"qty":{"type":"number","title":"Qty","default":1.0},"food_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Food Name"},"brand":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Brand"},"serving_description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Serving Description"}},"type":"object","required":["food_id","serving_id"],"title":"MealItemOut","description":"Stored item + display fields from the foods cache (Library rendering)."},"MealOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"trigger_phrases":{"items":{"type":"string"},"type":"array","title":"Trigger Phrases"},"items":{"items":{"$ref":"#/components/schemas/MealItemOut"},"type":"array","title":"Items"},"is_active":{"type":"boolean","title":"Is Active"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","name","trigger_phrases","items","is_active","created_at","updated_at"],"title":"MealOut"},"MealPatch":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"trigger_phrases":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Trigger Phrases"},"items":{"anyOf":[{"items":{"$ref":"#/components/schemas/MealItemIn"},"type":"array"},{"type":"null"}],"title":"Items"},"is_active":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Active"}},"type":"object","title":"MealPatch","description":"Any subset. trigger_phrases/items REPLACE the stored lists."},"MealWindow":{"properties":{"start":{"type":"string","title":"Start"},"end":{"type":"string","title":"End"}},"type":"object","required":["start","end"],"title":"MealWindow"},"MealWindows":{"properties":{"breakfast":{"$ref":"#/components/schemas/MealWindow"},"lunch":{"$ref":"#/components/schemas/MealWindow"},"dinner":{"$ref":"#/components/schemas/MealWindow"},"default":{"type":"string","enum":["breakfast","lunch","dinner","snack"],"title":"Default","default":"snack"}},"type":"object","required":["breakfast","lunch","dinner"],"title":"MealWindows"},"MetricsResponse":{"properties":{"range":{"type":"string","title":"Range"},"timezone":{"type":"string","title":"Timezone"},"weeks":{"items":{"type":"string","format":"date"},"type":"array","title":"Weeks"},"baseline_days_per_week":{"type":"integer","title":"Baseline Days Per Week"},"latency":{"items":{"$ref":"#/components/schemas/LatencyPoint"},"type":"array","title":"Latency"},"hit_rate":{"items":{"$ref":"#/components/schemas/HitRatePoint"},"type":"array","title":"Hit Rate"},"adherence":{"items":{"$ref":"#/components/schemas/AdherencePoint"},"type":"array","title":"Adherence"},"secondary":{"items":{"$ref":"#/components/schemas/SecondaryPoint"},"type":"array","title":"Secondary"},"duplicate_suspects":{"items":{"$ref":"#/components/schemas/DuplicatePair"},"type":"array","title":"Duplicate Suspects"}},"type":"object","required":["range","timezone","weeks","baseline_days_per_week","latency","hit_rate","adherence","secondary","duplicate_suspects"],"title":"MetricsResponse"},"NutrientRow":{"properties":{"name":{"type":"string","title":"Name"},"amount":{"type":"number","title":"Amount"},"unit":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Unit"},"basis":{"type":"string","title":"Basis"}},"type":"object","required":["name","amount","basis"],"title":"NutrientRow","description":"One nutrient as the source reported it. ``basis`` is the denominator:\nper 100 g / 100 ml for FDC foodNutrients, per serving for branded label\npanels and web-transcribed values."},"OuraAuthorize":{"properties":{"url":{"type":"string","title":"Url"}},"type":"object","required":["url"],"title":"OuraAuthorize"},"OuraDay":{"properties":{"day":{"type":"string","format":"date","title":"Day"},"total_calories":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Total Calories"},"active_calories":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Active Calories"},"steps":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Steps"}},"type":"object","required":["day","total_calories","active_calories","steps"],"title":"OuraDay"},"OuraStatus":{"properties":{"available":{"type":"boolean","title":"Available"},"connected":{"type":"boolean","title":"Connected"},"last_synced_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Synced At"},"missing":{"items":{"type":"string"},"type":"array","title":"Missing","default":[]},"days":{"items":{"$ref":"#/components/schemas/OuraDay"},"type":"array","title":"Days","default":[]}},"type":"object","required":["available","connected"],"title":"OuraStatus"},"OuraSync":{"properties":{"skipped":{"type":"boolean","title":"Skipped"},"days":{"type":"integer","title":"Days"},"workouts":{"type":"integer","title":"Workouts"},"last_synced_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Synced At"},"missing":{"items":{"type":"string"},"type":"array","title":"Missing","default":[]}},"type":"object","required":["skipped","days","workouts","last_synced_at"],"title":"OuraSync","description":"One sync's outcome — also POST /api/oura/sync's answer."},"Question":{"properties":{"text":{"type":"string","title":"Text"},"options":{"items":{"$ref":"#/components/schemas/QuestionOption"},"type":"array","title":"Options"}},"type":"object","required":["text","options"],"title":"Question"},"QuestionOption":{"properties":{"label":{"type":"string","title":"Label"},"source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source"},"source_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Id"}},"type":"object","required":["label"],"title":"QuestionOption"},"RemoveItemResponse":{"properties":{"log_id":{"type":"string","format":"uuid","title":"Log Id"},"item_index":{"type":"integer","title":"Item Index"},"status":{"type":"string","const":"removed","title":"Status","default":"removed"}},"type":"object","required":["log_id","item_index"],"title":"RemoveItemResponse"},"ResolveRequest":{"properties":{"log_id":{"type":"string","format":"uuid","title":"Log Id"},"item_index":{"type":"integer","title":"Item Index"},"phrase":{"type":"string","title":"Phrase"},"qty":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Qty"},"unit":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Unit"}},"type":"object","required":["log_id","item_index","phrase"],"title":"ResolveRequest"},"SaveIntent":{"properties":{"name":{"type":"string","title":"Name"}},"type":"object","required":["name"],"title":"SaveIntent"},"SavedMealNote":{"properties":{"meal_id":{"type":"string","format":"uuid","title":"Meal Id"},"name":{"type":"string","title":"Name"},"item_count":{"type":"integer","title":"Item Count"}},"type":"object","required":["meal_id","name","item_count"],"title":"SavedMealNote","description":"A macro this request created/updated (§8.4) — enough for the client to\nconfirm it (\"Saved as 'usual breakfast' · 3 items\")."},"SecondaryPoint":{"properties":{"week":{"type":"string","format":"date","title":"Week"},"committed_logs":{"type":"integer","title":"Committed Logs"},"items":{"type":"integer","title":"Items"},"edited":{"type":"integer","title":"Edited"},"edit_rate":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Edit Rate"},"disambiguated":{"type":"integer","title":"Disambiguated"},"disambiguation_rate":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Disambiguation Rate"},"tier3":{"type":"integer","title":"Tier3"},"short_circuit_logs":{"type":"integer","title":"Short Circuit Logs"},"short_circuit_share":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Short Circuit Share"},"discarded_logs":{"type":"integer","title":"Discarded Logs"},"capture_failures":{"type":"integer","title":"Capture Failures"}},"type":"object","required":["week","committed_logs","items","edited","edit_rate","disambiguated","disambiguation_rate","tier3","short_circuit_logs","short_circuit_share","discarded_logs","capture_failures"],"title":"SecondaryPoint"},"SelectRequest":{"properties":{"source":{"type":"string","title":"Source"},"source_id":{"type":"string","title":"Source Id"},"display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Display Name"},"log_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Log Id"},"item_index":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Item Index"}},"type":"object","required":["source","source_id"],"title":"SelectRequest"},"SelectResponse":{"properties":{"food_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Food Id"},"item":{"anyOf":[{"$ref":"#/components/schemas/StagedItem"},{"type":"null"}]}},"type":"object","title":"SelectResponse"},"ServingOption":{"properties":{"serving_id":{"type":"string","title":"Serving Id"},"description":{"type":"string","title":"Description"},"grams":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Grams"},"macros":{"anyOf":[{"additionalProperties":{"type":"number"},"type":"object"},{"type":"null"}],"title":"Macros"}},"type":"object","required":["serving_id","description"],"title":"ServingOption","description":"One row of foods.servings, surfaced on staged rows so the §7.1 portion\nsheet can list every serving the database defines — with per-single-serving\nmacros for the live preview."},"ServingRef":{"properties":{"id":{"type":"string","title":"Id"},"description":{"type":"string","title":"Description"}},"type":"object","required":["id","description"],"title":"ServingRef"},"SettingsResponse":{"properties":{"body":{"$ref":"#/components/schemas/BodyProfile"},"targets":{"anyOf":[{"$ref":"#/components/schemas/MacroTargets"},{"type":"null"}]},"meal_windows":{"$ref":"#/components/schemas/MealWindows"},"profile_notes":{"type":"string","title":"Profile Notes"},"timezone":{"type":"string","title":"Timezone"},"cronometer_baseline_days_per_week":{"type":"integer","title":"Cronometer Baseline Days Per Week"}},"type":"object","required":["body","targets","meal_windows","profile_notes","timezone","cronometer_baseline_days_per_week"],"title":"SettingsResponse"},"SettingsUpdate":{"properties":{"body":{"anyOf":[{"$ref":"#/components/schemas/BodyProfile"},{"type":"null"}]},"targets":{"anyOf":[{"$ref":"#/components/schemas/TargetsIn"},{"type":"null"}]},"meal_windows":{"anyOf":[{"$ref":"#/components/schemas/MealWindows"},{"type":"null"}]},"profile_notes":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}],"title":"Profile Notes"},"timezone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Timezone"},"cronometer_baseline_days_per_week":{"anyOf":[{"type":"integer","maximum":7.0,"minimum":0.0},{"type":"null"}],"title":"Cronometer Baseline Days Per Week"}},"type":"object","title":"SettingsUpdate","description":"PUT body: every field optional; only fields present are written."},"SourceBadge":{"properties":{"source":{"type":"string","title":"Source"},"label":{"type":"string","title":"Label"},"data_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Data Type"},"data_source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Data Source"},"published_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Published Date"},"modified_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Modified Date"},"quality_flags":{"items":{"type":"string"},"type":"array","title":"Quality Flags"}},"type":"object","required":["source","label","quality_flags"],"title":"SourceBadge"},"StagedItem":{"properties":{"item_index":{"type":"integer","title":"Item Index"},"phrase":{"type":"string","title":"Phrase"},"status":{"type":"string","enum":["resolved","searching","needs_input","not_found"],"title":"Status"},"tier":{"anyOf":[{"type":"integer","enum":[0,1,2,3]},{"type":"null"}],"title":"Tier"},"food":{"anyOf":[{"$ref":"#/components/schemas/FoodRef"},{"type":"null"}]},"serving":{"anyOf":[{"$ref":"#/components/schemas/ServingRef"},{"type":"null"}]},"qty":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Qty"},"macros":{"anyOf":[{"$ref":"#/components/schemas/Macros"},{"type":"null"}]},"meal":{"$ref":"#/components/schemas/Meal"},"alternates":{"anyOf":[{"items":{"$ref":"#/components/schemas/Alternate"},"type":"array"},{"type":"null"}],"title":"Alternates"},"state_question":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"State Question"},"question":{"anyOf":[{"$ref":"#/components/schemas/Question"},{"type":"null"}]},"confidence":{"anyOf":[{"type":"string","enum":["high","medium","low"]},{"type":"null"}],"title":"Confidence"},"servings":{"anyOf":[{"items":{"$ref":"#/components/schemas/ServingOption"},"type":"array"},{"type":"null"}],"title":"Servings"},"search_instead":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Search Instead"},"web_source":{"anyOf":[{"$ref":"#/components/schemas/WebSource"},{"type":"null"}]},"estimated":{"type":"string","enum":["none","portion","unresolved"],"title":"Estimated","default":"none"},"estimate_note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Estimate Note"}},"type":"object","required":["item_index","phrase","status","meal"],"title":"StagedItem"},"StagedItemOut":{"properties":{"item_index":{"type":"integer","title":"Item Index"},"phrase":{"type":"string","title":"Phrase"},"status":{"type":"string","enum":["resolved","searching","needs_input","not_found"],"title":"Status"},"tier":{"anyOf":[{"type":"integer","enum":[0,1,2,3]},{"type":"null"}],"title":"Tier"},"food":{"anyOf":[{"$ref":"#/components/schemas/FoodRef"},{"type":"null"}]},"serving":{"anyOf":[{"$ref":"#/components/schemas/ServingRef"},{"type":"null"}]},"qty":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Qty"},"macros":{"anyOf":[{"$ref":"#/components/schemas/Macros"},{"type":"null"}]},"meal":{"$ref":"#/components/schemas/Meal"},"alternates":{"anyOf":[{"items":{"$ref":"#/components/schemas/Alternate"},"type":"array"},{"type":"null"}],"title":"Alternates"},"state_question":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"State Question"},"question":{"anyOf":[{"$ref":"#/components/schemas/Question"},{"type":"null"}]},"confidence":{"anyOf":[{"type":"string","enum":["high","medium","low"]},{"type":"null"}],"title":"Confidence"},"servings":{"anyOf":[{"items":{"$ref":"#/components/schemas/ServingOption"},"type":"array"},{"type":"null"}],"title":"Servings"},"search_instead":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Search Instead"},"web_source":{"anyOf":[{"$ref":"#/components/schemas/WebSource"},{"type":"null"}]},"estimated":{"type":"string","enum":["none","portion","unresolved"],"title":"Estimated","default":"none"},"estimate_note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Estimate Note"},"stale":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Stale"}},"type":"object","required":["item_index","phrase","status","meal"],"title":"StagedItemOut","description":"A StagedItem as returned by GET /api/logs/{id}, plus the watchdog flag.\n\nstale=true marks a status=\"searching\" item whose tier-3 run started (or\nwas staged) more than 60s ago with tier3_attempts < 2: the client should\nre-kick it once via POST /api/resolve/tier3 (§3.4 failure lifecycle).\nComputed at poll time, never persisted; null/absent everywhere else."},"TargetsIn":{"properties":{"kcal":{"type":"number","maximum":10000.0,"minimum":800.0,"title":"Kcal"},"protein_g":{"type":"number","maximum":1000.0,"minimum":0.0,"title":"Protein G"},"carb_g":{"type":"number","maximum":2000.0,"minimum":0.0,"title":"Carb G"},"fat_g":{"type":"number","maximum":1000.0,"minimum":0.0,"title":"Fat G"}},"type":"object","required":["kcal","protein_g","carb_g","fat_g"],"title":"TargetsIn"},"Tier3KickRequest":{"properties":{"log_id":{"type":"string","format":"uuid","title":"Log Id"},"item_index":{"type":"integer","title":"Item Index"}},"type":"object","required":["log_id","item_index"],"title":"Tier3KickRequest"},"TimingsPatch":{"properties":{"staged_ms":{"type":"integer","minimum":0.0,"title":"Staged Ms"}},"type":"object","required":["staged_ms"],"title":"TimingsPatch","description":"§9: client-observed capture-start → list-rendered, in milliseconds."},"TimingsResponse":{"properties":{"log_id":{"type":"string","format":"uuid","title":"Log Id"},"staged_ms":{"type":"integer","title":"Staged Ms"}},"type":"object","required":["log_id","staged_ms"],"title":"TimingsResponse"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"WebSource":{"properties":{"url":{"type":"string","title":"Url"},"title":{"type":"string","title":"Title"}},"type":"object","required":["url","title"],"title":"WebSource","description":"§3.4a: the citation for a web-transcribed (chain) food — the UI must\nrender it as a visible, clickable link (OpenAI usage-terms requirement)."},"WeekStat":{"properties":{"week_start":{"type":"string","format":"date","title":"Week Start"},"days_logged":{"type":"integer","title":"Days Logged"},"adherence":{"type":"number","title":"Adherence"},"avg":{"anyOf":[{"$ref":"#/components/schemas/MacroSums"},{"type":"null"}]}},"type":"object","required":["week_start","days_logged","adherence"],"title":"WeekStat"},"WeightEntry":{"properties":{"day":{"type":"string","format":"date","title":"Day"},"weight_kg":{"type":"number","title":"Weight Kg"},"unit":{"type":"string","enum":["kg","lb"],"title":"Unit"},"source":{"type":"string","enum":["agent","manual"],"title":"Source"},"log_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Log Id"}},"type":"object","required":["day","weight_kg","unit","source"],"title":"WeightEntry"},"WeightPut":{"properties":{"weight":{"type":"number","exclusiveMinimum":0.0,"title":"Weight"},"unit":{"type":"string","enum":["kg","lb"],"title":"Unit"},"day":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Day"}},"type":"object","required":["weight","unit"],"title":"WeightPut"},"WeightsResponse":{"properties":{"latest":{"anyOf":[{"$ref":"#/components/schemas/WeightEntry"},{"type":"null"}]},"entries":{"items":{"$ref":"#/components/schemas/WeightEntry"},"type":"array","title":"Entries"}},"type":"object","required":["latest","entries"],"title":"WeightsResponse"}}}}