Ulivo MCP connector
Endpoint https://getulivo.com/mcp (Streamable HTTP, stateless JSON). OAuth 2.1 + PKCE (S256). Discovery: /.well-known/oauth-protected-resource/mcp, /.well-known/oauth-authorization-server. Client ID options: CIMD https://getulivo.com/.well-known/muse-client.json. Scopes: dinner.read, dinner.write, dinner.invite; a read-only option is offered on the consent screen.
Machine-readable: MCP Server Card (SEP-2127), listed in the AI Catalog; a plain-text overview for assistants at llms.txt.
Rate limits: 60 calls/min and 2,000/day per token; generate_week_plan 20/hour per household; swaps and previews 120/hour; Instacart links 30/day (new links); invite emails 10/day; imports 10 calls/hour and 500 rows/day.
Status handling
Success: structuredContent matches the tool's output schema, and the text block has a short summary followed by the same JSON. Write tools may add notices (each with a code and message) for things the user should hear, such as a changed setting or a dinner that's no longer safe.
Errors: the result has isError: true. The error object is in _meta["ulivo/error"] and, as JSON, in the text block: { code, message, retryable, retry_after_ms?, details?, user_action? }. message is written for the user. user_action (label, url) is a link to show them. Only retry when retryable is true, after retry_after_ms if it's set.
Writes: pass an idempotency_key to make a write safe to retry. The same key with the same arguments returns the first result and changes nothing again; with different arguments it fails with IDEMPOTENCY_MISMATCH. Keys are kept for 24 hours. generate_week_plan, swap_meal, set_plan_day, confirm_week_plan and set_week_schedule take an optional expected_revision and fail with CONFLICT_VERSION if someone else changed the plan or schedule first.
Arguments that don't match the input schema return VALIDATION_FAILED as above. An unknown tool name is a JSON-RPC error (-32602). HTTP 401 with WWW-Authenticate means the token is missing, expired or revoked: sign in again.
Error codes
| Code | Retryable | Meaning | What to do |
|---|---|---|---|
VALIDATION_FAILED | No | An argument is missing or invalid. details.fields names them. | Fix the named fields (ask the user if you need to). Don't retry unchanged. |
AMBIGUOUS_REFERENCE | No | A name matches more than one person or recipe. details.candidates lists them. | Ask the user which one, then call again with its id. |
NOT_FOUND | No | The person, recipe, plan or link isn't in this household. | Re-read (get_household, search_recipes, get_week_plan) and use an id from the result. |
HOUSEHOLD_NOT_SET_UP | No | The signed-in account has no household yet. details.next_steps says how to start. | Start one with save_household_member (is_me: true), or point the user to the setup link. |
FORBIDDEN_ROLE | No | The signed-in adult's role can't do this; some actions are owner-only. details.role is their role. | Tell the user that the household owner can do it. |
INSUFFICIENT_SCOPE | No | The connection was approved without the access this tool needs (e.g. read-only, or no dinner.invite). details.required_scope names it. | Ask the user to reconnect Ulivo and approve that access. |
PLAN_LIMIT | No | This needs Ulivo Plus, or a plan limit is reached. details.limit and details.used give the numbers; user_action links to the Ulivo account page. | Explain the limit and share the user_action link. Plus is only sold on the website, never in chat. |
HEALTH_DATA_CONSENT_REQUIRED | No | Allergies, calorie targets and weight goals can't be saved until the account holder consents. | Show the consent text to the user word for word. Only after they agree, call again with health_data_consent: true. |
CONFLICT_VERSION | No | The plan or household changed since you read it (expected_revision is out of date), or another request changed it at the same moment (details.reason: concurrent_update). Nothing was saved. | Re-read, tell the user if the change matters, then retry with the new revision. |
CONFLICT_IN_PROGRESS | Yes | The same request (same idempotency_key) is still running. | Wait retry_after_ms, then retry with the same key. |
IDEMPOTENCY_MISMATCH | No | This idempotency_key was already used with different arguments. | Use a new key for a new request. |
INFEASIBLE_CONSTRAINTS | No | No plan fits everyone's strict rules (details.cause: rules), or no week of dinners that fits them stays within the weekly budget (details.cause: budget); nothing was saved. details.summary, blocking_slots and suggestions explain why. | Explain the reason and offer the suggestions. Never relax an allergy or other strict rule on your own. |
RATE_LIMITED | Yes | Too many calls for one of the limits above. retry_after_ms is set when known. | Wait, then retry. If it's a daily limit, tell the user when they can try again. |
UPSTREAM_UNAVAILABLE | Yes | A partner service (Instacart, email or payments) isn't available. | Retry later. The rest of Ulivo keeps working. |
UPSTREAM_TIMEOUT | Yes | A partner service didn't answer in time. | Retry once; for writes, reuse the same idempotency_key so nothing is done twice. |
INVALID_STATE | No | The request doesn't fit the current state (e.g. the week is over, a plan already covers those days, or a link expired). | Explain the message to the user. Don't retry unchanged. |
INTERNAL | Yes | Something went wrong on Ulivo's side. | Retry once with the same idempotency_key. If it keeps happening, point the user to /support. |
Tools
get_my_account · Get My Account
Read · scope dinner.read · roles owner, adult · readOnly true · destructive false · openWorld false
Returns the Ulivo account of the person who connected this app: a stable opaque account id, their name, email, and a label such as 'Sam (Sam, Alex & Maya)'. Use it to know who is speaking, e.g. before recording feedback on someone's behalf. Read-only; changes nothing.
Input / output schema
{
"input": {
"type": "object",
"properties": {},
"additionalProperties": false
},
"output": {
"type": "object",
"properties": {
"id": {
"type": "string",
"minLength": 1,
"pattern": "\\S",
"description": "Opaque profile identifier, unique within this app and unchanged across token refresh, reconnection, and display-metadata changes. Never reassigned to another profile."
},
"name": {
"description": "Display name for the authenticated profile.",
"type": "string"
},
"email": {
"description": "Email address for display; not used as the profile identity.",
"type": "string"
},
"nickname": {
"description": "A useful label that helps users distinguish connected profiles.",
"type": "string"
}
},
"required": [
"id"
],
"additionalProperties": false
}
}get_household · Get Household
Read · scope dinner.read · roles owner, adult · readOnly true · destructive false · openWorld false
Returns the household's dinner setup: every member (adults and parent-managed child/teen profiles) with their allergies, foods they don't eat, dislikes, portion size, optional dinner calorie target, an adult's weight goal (shown back only, never used for planning) and weekly schedule; the plan week start day; grocery delivery day and time; stores and which sections go to which store; pantry staples; cooking-time defaults; units; and setup progress with next steps. Call this first in a new conversation about dinners, before planning, or when the user asks what the planner knows about their family. Read-only.
Input / output schema
{
"input": {
"type": "object",
"properties": {
"include": {
"description": "Sections to include; default all.",
"type": "array",
"items": {
"type": "string",
"enum": [
"members",
"settings",
"stores",
"staples",
"setup"
]
}
}
},
"additionalProperties": false
},
"output": {
"type": "object",
"properties": {
"setup_state": {
"type": "string",
"enum": [
"needs_household",
"needs_members",
"needs_settings",
"ready"
]
},
"me": {
"type": "object",
"properties": {
"account_id": {
"type": "string"
},
"member_id": {
"type": [
"string",
"null"
]
},
"role": {
"anyOf": [
{
"type": "string",
"enum": [
"owner",
"adult"
]
},
{
"type": "null"
}
]
},
"connection_scopes": {
"type": "array",
"items": {
"type": "string"
}
},
"read_only": {
"type": "boolean"
}
},
"required": [
"account_id",
"member_id",
"role",
"connection_scopes",
"read_only"
],
"additionalProperties": false
},
"next_steps": {
"type": "array",
"items": {
"type": "string"
}
},
"household": {
"anyOf": [
{
"type": "object",
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"timezone": {
"type": "string"
},
"plan_week_start_dow": {
"type": "string",
"enum": [
"mon",
"tue",
"wed",
"thu",
"fri",
"sat",
"sun"
]
},
"today": {
"description": "The household's local date, in its timezone. Use it to resolve 'tonight', 'tomorrow' or 'this Tuesday'.",
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
"current_week_start": {
"description": "Start date of the plan week that contains today.",
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
"delivery": {
"anyOf": [
{
"type": "object",
"properties": {
"dow": {
"type": "string",
"enum": [
"mon",
"tue",
"wed",
"thu",
"fri",
"sat",
"sun"
]
},
"time": {
"type": "string"
},
"provider": {
"type": "string",
"enum": [
"instacart",
"other",
"pickup",
"none"
]
}
},
"additionalProperties": false
},
{
"type": "null"
}
]
},
"unit_system": {
"type": "string",
"enum": [
"us_customary",
"metric"
]
},
"default_time_budget_minutes": {
"type": "object",
"properties": {
"weekday": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"weekend": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
}
},
"required": [
"weekday",
"weekend"
],
"additionalProperties": false
},
"weekly_budget_cents": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"leftovers_target_per_week": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"min_repeat_days": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"favorite_return_days": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "How many days until a favorite comes back (default 21)."
},
"plan": {
"type": "string",
"enum": [
"plus",
"none"
],
"description": "plus: the household has Ulivo Plus (trial, subscription or complimentary). none: no Plus right now, so planning is paused; reading and family edits still work."
}
},
"required": [
"id",
"name",
"timezone",
"plan_week_start_dow",
"delivery",
"unit_system",
"default_time_budget_minutes",
"weekly_budget_cents",
"leftovers_target_per_week",
"min_repeat_days",
"favorite_return_days",
"plan"
],
"additionalProperties": false
},
{
"type": "null"
}
]
},
"members": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
},
"display_name": {
"type": "string"
},
"age_band": {
"type": "string",
"enum": [
"adult",
"teen_13_17",
"child_under_13"
]
},
"has_login": {
"type": "boolean"
},
"role": {
"type": "string",
"enum": [
"owner",
"adult",
"profile_only"
]
},
"portion_factor": {
"type": "number"
},
"dinner_kcal_target": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"weight_goal": {
"anyOf": [
{
"type": "object",
"properties": {
"direction": {
"type": "string",
"enum": [
"lose",
"gain"
]
},
"lbs": {
"type": "integer",
"minimum": 1,
"maximum": 100
}
},
"required": [
"direction",
"lbs"
],
"additionalProperties": false
},
{
"type": "null"
}
]
},
"constraints": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
},
"type": {
"type": "string",
"enum": [
"allergy",
"exclusion",
"diet",
"dislike"
]
},
"term": {
"type": "string"
},
"resolved_kind": {
"type": "string",
"enum": [
"tag",
"ingredient",
"allergen",
"diet",
"recipe"
]
},
"resolved_key": {
"type": "string"
},
"label": {
"type": "string"
},
"strength": {
"type": "string",
"enum": [
"hard",
"soft"
]
}
},
"required": [
"id",
"type",
"term",
"resolved_kind",
"resolved_key",
"label",
"strength"
],
"additionalProperties": false
}
},
"schedule": {
"type": "array",
"items": {
"type": "object",
"properties": {
"dow": {
"type": "string",
"enum": [
"mon",
"tue",
"wed",
"thu",
"fri",
"sat",
"sun"
]
},
"attending": {
"type": "boolean"
},
"max_cook_minutes": {
"anyOf": [
{
"type": "integer",
"minimum": 5,
"maximum": 240
},
{
"type": "null"
}
]
},
"note": {
"description": "Short reason shown in plans, e.g. 'padel'.",
"anyOf": [
{
"type": "string",
"maxLength": 60
},
{
"type": "null"
}
]
}
},
"required": [
"dow",
"attending"
],
"additionalProperties": false
}
}
},
"required": [
"id",
"display_name",
"age_band",
"has_login",
"role",
"portion_factor",
"dinner_kcal_target",
"weight_goal",
"constraints",
"schedule"
],
"additionalProperties": false
}
},
"stores": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
},
"name": {
"type": "string"
},
"is_default": {
"type": "boolean"
},
"sections": {
"type": "array",
"items": {
"type": "string",
"enum": [
"produce",
"meat",
"seafood",
"dairy",
"bakery",
"pantry",
"frozen",
"spices",
"beverages",
"household",
"other"
]
}
},
"instacart_enabled": {
"type": "boolean"
}
},
"required": [
"id",
"name",
"is_default",
"sections",
"instacart_enabled"
],
"additionalProperties": false
}
},
"staples": {
"type": "array",
"items": {
"type": "string"
}
},
"invites": {
"type": "array",
"items": {
"type": "object",
"properties": {
"email": {
"type": [
"string",
"null"
]
},
"channel": {
"type": "string"
},
"status": {
"type": "string"
},
"expires_at": {
"type": "string"
}
},
"required": [
"email",
"channel",
"status",
"expires_at"
],
"additionalProperties": false
}
},
"notices": {
"type": "array",
"items": {
"type": "object",
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
}
},
"required": [
"code",
"message"
],
"additionalProperties": false
}
}
},
"required": [
"setup_state",
"notices"
],
"additionalProperties": false
}
}search_recipes · Search Recipes
Read · scope dinner.read · roles owner, adult · readOnly true · destructive false · openWorld false
Searches the household's own recipes and the Ulivo starter library. Filters: text, max total minutes, cuisine, main protein, tags (e.g. kid_friendly, leftovers_ok, one_pot), source (household or library), minimum household rating, and 'safe for' members (excludes anything that breaks those members' allergies, exclusions or diets). Returns summaries with ratings, cook time, calories per serving and last served date. Use it to browse or answer questions like "what quick chicken dinners do we have". To change a specific night, use preview_meal_options. Read-only.
Input / output schema
{
"input": {
"type": "object",
"properties": {
"query": {
"type": "string",
"maxLength": 100
},
"max_total_minutes": {
"type": "integer",
"minimum": 5,
"maximum": 480
},
"cuisine": {
"type": "string",
"maxLength": 40
},
"main_protein": {
"type": "string",
"enum": [
"chicken",
"beef",
"pork",
"lamb",
"turkey",
"fish",
"shellfish",
"eggs",
"tofu",
"beans_legumes",
"cheese_dairy",
"none_veg",
"mixed"
]
},
"tags": {
"maxItems": 5,
"type": "array",
"items": {
"type": "string",
"maxLength": 100
}
},
"source": {
"default": "any",
"type": "string",
"enum": [
"household",
"library",
"any"
]
},
"visibility": {
"description": "Same as source: household = this family's own, global = Ulivo's shared recipes.",
"type": "string",
"enum": [
"household",
"global",
"any"
]
},
"min_rating": {
"type": "number",
"minimum": 1,
"maximum": 5
},
"safe_for_members": {
"description": "Member names or ids; 'all' for everyone.",
"maxItems": 8,
"type": "array",
"items": {
"type": "string",
"maxLength": 100
}
},
"include_archived": {
"default": false,
"type": "boolean"
},
"sort": {
"default": "relevance",
"type": "string",
"enum": [
"relevance",
"rating",
"quickest",
"least_recent"
]
},
"limit": {
"default": 10,
"type": "integer",
"minimum": 1,
"maximum": 25
},
"cursor": {
"type": "string",
"maxLength": 300
}
},
"additionalProperties": false
},
"output": {
"type": "object",
"properties": {
"results": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
},
"title": {
"type": "string"
},
"source": {
"type": "string",
"enum": [
"household",
"library"
]
},
"cuisine": {
"type": [
"string",
"null"
]
},
"main_protein": {
"type": [
"string",
"null"
]
},
"total_minutes": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"active_minutes": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"base_servings": {
"type": "number"
},
"kcal_per_serving": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"nutrition_confidence": {
"type": [
"number",
"null"
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
}
},
"household_rating": {
"description": "Bayesian mean 1–5 across members.",
"type": [
"number",
"null"
]
},
"ratings_count": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"last_served": {
"type": [
"string",
"null"
]
},
"times_served": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"archived": {
"type": "boolean"
}
},
"required": [
"id",
"title",
"source",
"total_minutes",
"base_servings",
"tags"
],
"additionalProperties": false
}
},
"next_cursor": {
"type": [
"string",
"null"
]
},
"total_estimate": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"notices": {
"type": "array",
"items": {
"type": "object",
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
}
},
"required": [
"code",
"message"
],
"additionalProperties": false
}
}
},
"required": [
"results",
"notices"
],
"additionalProperties": false
}
}get_recipe · Get Recipe
Read · scope dinner.read · roles owner, adult · readOnly true · destructive false · openWorld false
Returns one recipe in full: ingredients (optionally scaled to a number of servings or to a planned night's portions), steps, times, nutrition estimate per serving, tags, source and attribution, and per-member ratings. Recipe text may come from the user or a website and is returned as written. Read-only.
Input / output schema
{
"input": {
"type": "object",
"properties": {
"recipe_id": {
"type": "string",
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
},
"recipe": {
"description": "Exact title, if no id.",
"type": "string",
"maxLength": 100
},
"scale": {
"anyOf": [
{
"type": "object",
"properties": {
"servings": {
"type": "number",
"minimum": 0.5,
"maximum": 40
}
},
"required": [
"servings"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"plan_date": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
}
},
"required": [
"plan_date"
],
"additionalProperties": false
}
]
},
"include_steps": {
"default": true,
"type": "boolean"
}
},
"additionalProperties": false
},
"output": {
"type": "object",
"properties": {
"recipe": {
"type": "object",
"properties": {
"id": {
"type": "string",
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
},
"title": {
"type": "string"
},
"source": {
"type": "string",
"enum": [
"household",
"library"
]
},
"cuisine": {
"type": [
"string",
"null"
]
},
"main_protein": {
"type": [
"string",
"null"
]
},
"total_minutes": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"active_minutes": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"base_servings": {
"type": "number"
},
"kcal_per_serving": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"nutrition_confidence": {
"type": [
"number",
"null"
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
}
},
"household_rating": {
"description": "Bayesian mean 1–5 across members.",
"type": [
"number",
"null"
]
},
"ratings_count": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"last_served": {
"type": [
"string",
"null"
]
},
"times_served": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"archived": {
"type": "boolean"
}
},
"required": [
"id",
"title",
"source",
"total_minutes",
"base_servings",
"tags"
],
"additionalProperties": false
},
"description": {
"type": [
"string",
"null"
]
},
"servings_shown": {
"type": "number"
},
"ingredients": {
"type": "array",
"items": {
"type": "object",
"properties": {
"raw_text": {
"type": "string"
},
"ingredient_id": {
"type": [
"string",
"null"
]
},
"canonical_name": {
"type": [
"string",
"null"
]
},
"qty_display": {
"type": [
"string",
"null"
]
},
"unit_display": {
"type": [
"string",
"null"
]
},
"qty_base": {
"type": [
"number",
"null"
]
},
"base_unit": {
"anyOf": [
{
"type": "string",
"enum": [
"g",
"ml",
"each"
]
},
{
"type": "null"
}
]
},
"preparation": {
"type": [
"string",
"null"
]
},
"section": {
"type": "string",
"enum": [
"produce",
"meat",
"seafood",
"dairy",
"bakery",
"pantry",
"frozen",
"spices",
"beverages",
"household",
"other"
]
},
"optional": {
"type": "boolean"
},
"omittable": {
"type": "boolean"
},
"parse_status": {
"type": "string",
"enum": [
"ok",
"needs_review",
"unmapped"
]
}
},
"required": [
"raw_text",
"ingredient_id",
"canonical_name",
"qty_display",
"unit_display",
"section",
"optional",
"omittable",
"parse_status"
],
"additionalProperties": false
}
},
"steps": {
"type": "array",
"items": {
"type": "string"
}
},
"nutrition_per_serving": {
"anyOf": [
{
"type": "object",
"properties": {
"kcal": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"protein_g": {
"type": "number"
},
"fat_g": {
"type": "number"
},
"carbs_g": {
"type": "number"
},
"fiber_g": {
"type": "number"
},
"sodium_mg": {
"type": "number"
},
"confidence": {
"type": "number"
},
"source": {
"type": "string",
"enum": [
"usda_estimate",
"user"
]
}
},
"required": [
"kcal",
"protein_g",
"fat_g",
"carbs_g",
"fiber_g",
"sodium_mg",
"confidence",
"source"
],
"additionalProperties": false
},
{
"type": "null"
}
]
},
"member_ratings": {
"type": "array",
"items": {
"type": "object",
"properties": {
"member": {
"type": "string"
},
"avg": {
"type": "number"
},
"count": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
}
},
"required": [
"member",
"avg",
"count"
],
"additionalProperties": false
}
},
"source_url": {
"type": [
"string",
"null"
]
},
"source_name": {
"type": [
"string",
"null"
]
},
"allergen_summary": {
"type": "array",
"items": {
"type": "string"
}
},
"disclaimer": {
"type": "string"
},
"notices": {
"type": "array",
"items": {
"type": "object",
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
}
},
"required": [
"code",
"message"
],
"additionalProperties": false
}
}
},
"required": [
"recipe",
"ingredients",
"notices"
],
"additionalProperties": false
}
}get_week_plan · Get Week Plan
Read · scope dinner.read · roles owner, adult · readOnly true · destructive false · openWorld false
Returns the dinner plan for a week: each night's recipe or status (leftovers, eating out, skipped), who is eating, each person's portion and calories (for members with a calorie target), cooking time versus that night's time budget and the schedule reason, ingredients to leave off for specific people, why each meal was chosen, the hard-constraint report, and estimated cost. format='markdown' adds a ready-to-paste document (e.g. for a Google Doc). Returns plan_exists=false if no plan has been generated yet. Read-only.
Input / output schema
{
"input": {
"type": "object",
"properties": {
"week": {
"default": "next",
"type": "string",
"pattern": "^(current|next|previous|\\d{4}-\\d{2}-\\d{2})$",
"description": "'current', 'next', 'previous', or any date (YYYY-MM-DD) inside the wanted plan week."
},
"format": {
"default": "structured",
"type": "string",
"enum": [
"structured",
"markdown"
]
},
"include_explanations": {
"default": true,
"type": "boolean"
}
},
"additionalProperties": false
},
"output": {
"type": "object",
"properties": {
"plan_exists": {
"type": "boolean"
},
"week_start": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
"plan": {
"type": "object",
"properties": {
"plan_id": {
"type": "string",
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
},
"week_start": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
"week_end": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
"status": {
"type": "string",
"enum": [
"draft",
"confirmed",
"completed"
]
},
"revision": {
"type": "integer",
"minimum": 1,
"maximum": 9007199254740991
},
"days": {
"maxItems": 7,
"type": "array",
"items": {
"type": "object",
"properties": {
"date": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
"dow": {
"type": "string",
"enum": [
"mon",
"tue",
"wed",
"thu",
"fri",
"sat",
"sun"
]
},
"kind": {
"type": "string",
"enum": [
"recipe",
"leftovers",
"eating_out",
"skip",
"unplanned"
]
},
"locked": {
"type": "boolean"
},
"recipe": {
"type": "object",
"properties": {
"id": {
"type": "string",
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
},
"title": {
"type": "string"
},
"source": {
"type": "string",
"enum": [
"household",
"library"
]
},
"cuisine": {
"type": [
"string",
"null"
]
},
"main_protein": {
"type": [
"string",
"null"
]
},
"total_minutes": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"active_minutes": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"base_servings": {
"type": "number"
},
"kcal_per_serving": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"nutrition_confidence": {
"type": [
"number",
"null"
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
}
},
"household_rating": {
"description": "Bayesian mean 1–5 across members.",
"type": [
"number",
"null"
]
},
"ratings_count": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"last_served": {
"type": [
"string",
"null"
]
},
"times_served": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"archived": {
"type": "boolean"
}
},
"required": [
"id",
"title",
"source",
"total_minutes",
"base_servings",
"tags"
],
"additionalProperties": false
},
"leftovers_of_date": {
"type": [
"string",
"null"
]
},
"attending": {
"type": "array",
"items": {
"type": "object",
"properties": {
"member_id": {
"type": "string",
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
},
"display_name": {
"type": "string"
},
"portion": {
"type": "number"
},
"kcal": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"kcal_target": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
}
},
"required": [
"member_id",
"display_name",
"portion"
],
"additionalProperties": false
}
},
"servings_to_cook": {
"type": [
"number",
"null"
]
},
"time_minutes": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"time_budget_minutes": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"schedule_reason": {
"type": [
"string",
"null"
]
},
"omit_for": {
"type": "array",
"items": {
"type": "object",
"properties": {
"ingredient": {
"type": "string"
},
"members": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": [
"ingredient",
"members"
],
"additionalProperties": false
}
},
"why": {
"maxItems": 3,
"type": "array",
"items": {
"type": "string"
}
},
"needs_swap": {
"type": "boolean"
},
"swap_reasons": {
"description": "When needs_swap: who and which strict rule this dinner breaks, e.g. \"Not safe for Mia (fish allergy)\". Tell the user and offer swap_meal.",
"type": "array",
"items": {
"type": "string"
}
},
"estimated_cost_cents": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
}
},
"required": [
"date",
"dow",
"kind",
"locked",
"attending",
"time_budget_minutes",
"why"
],
"additionalProperties": false
}
},
"constraint_report": {
"type": "object",
"properties": {
"all_hard_constraints_satisfied": {
"type": "boolean"
},
"items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"constraint": {
"type": "string"
},
"applies_to": {
"type": "array",
"items": {
"type": "string"
}
},
"satisfied_days": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"total_days": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"detail": {
"type": [
"string",
"null"
]
},
"status": {
"type": "string",
"enum": [
"applied",
"not_applied_plan_limit",
"not_applicable"
]
}
},
"required": [
"constraint",
"applies_to",
"satisfied_days",
"total_days"
],
"additionalProperties": false
}
}
},
"required": [
"all_hard_constraints_satisfied",
"items"
],
"additionalProperties": false
},
"estimated_total_cost_cents": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"weekly_budget_cents": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"confirmed_at": {
"type": [
"string",
"null"
]
},
"shopping_list_changed_since_handoff": {
"type": "boolean"
},
"markdown": {
"description": "Present only when format='markdown'.",
"type": [
"string",
"null"
]
}
},
"required": [
"plan_id",
"week_start",
"week_end",
"status",
"revision",
"days",
"constraint_report"
],
"additionalProperties": false
},
"notices": {
"type": "array",
"items": {
"type": "object",
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
}
},
"required": [
"code",
"message"
],
"additionalProperties": false
}
}
},
"required": [
"plan_exists",
"notices"
],
"additionalProperties": false
}
}preview_meal_options · Preview Meal Options
Read · scope dinner.read · roles owner, adult · readOnly true · destructive false · openWorld false
Suggests up to 5 recipes that would fit a specific night in the plan, checked against everyone's allergies, exclusions, diets, calorie targets, that night's cooking-time budget and recent repeats, ranked by family ratings and fit. Optional text filter (e.g. 'chicken', 'pasta'). Use this before swap_meal so the user can choose. Does not change the plan.
Input / output schema
{
"input": {
"type": "object",
"properties": {
"week": {
"description": "Omit with a weekday to mean its next occurrence from the household's today (tonight if it's today). 'current' or 'next' pick a plan week explicitly.",
"type": "string",
"pattern": "^(current|next|previous|\\d{4}-\\d{2}-\\d{2})$"
},
"day": {
"type": "string",
"pattern": "^(mon|tue|wed|thu|fri|sat|sun|\\d{4}-\\d{2}-\\d{2})$",
"description": "Weekday within the resolved plan week, or an exact date (YYYY-MM-DD)."
},
"query": {
"description": "Text to match (a recipe name, ingredient, protein or cuisine). 'quick', 'fast' or 'easy' means a total time of 30 minutes or less.",
"type": "string",
"maxLength": 60
},
"max_total_minutes": {
"type": "integer",
"minimum": 5,
"maximum": 480
},
"source": {
"default": "any",
"type": "string",
"enum": [
"household",
"library",
"any"
]
},
"limit": {
"default": 3,
"type": "integer",
"minimum": 1,
"maximum": 5
}
},
"required": [
"day"
],
"additionalProperties": false
},
"output": {
"type": "object",
"properties": {
"day": {
"type": "object",
"properties": {
"date": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
"dow": {
"type": "string",
"enum": [
"mon",
"tue",
"wed",
"thu",
"fri",
"sat",
"sun"
]
},
"kind": {
"type": "string",
"enum": [
"recipe",
"leftovers",
"eating_out",
"skip",
"unplanned"
]
},
"locked": {
"type": "boolean"
},
"recipe": {
"type": "object",
"properties": {
"id": {
"type": "string",
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
},
"title": {
"type": "string"
},
"source": {
"type": "string",
"enum": [
"household",
"library"
]
},
"cuisine": {
"type": [
"string",
"null"
]
},
"main_protein": {
"type": [
"string",
"null"
]
},
"total_minutes": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"active_minutes": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"base_servings": {
"type": "number"
},
"kcal_per_serving": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"nutrition_confidence": {
"type": [
"number",
"null"
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
}
},
"household_rating": {
"description": "Bayesian mean 1–5 across members.",
"type": [
"number",
"null"
]
},
"ratings_count": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"last_served": {
"type": [
"string",
"null"
]
},
"times_served": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"archived": {
"type": "boolean"
}
},
"required": [
"id",
"title",
"source",
"total_minutes",
"base_servings",
"tags"
],
"additionalProperties": false
},
"leftovers_of_date": {
"type": [
"string",
"null"
]
},
"attending": {
"type": "array",
"items": {
"type": "object",
"properties": {
"member_id": {
"type": "string",
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
},
"display_name": {
"type": "string"
},
"portion": {
"type": "number"
},
"kcal": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"kcal_target": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
}
},
"required": [
"member_id",
"display_name",
"portion"
],
"additionalProperties": false
}
},
"servings_to_cook": {
"type": [
"number",
"null"
]
},
"time_minutes": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"time_budget_minutes": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"schedule_reason": {
"type": [
"string",
"null"
]
},
"omit_for": {
"type": "array",
"items": {
"type": "object",
"properties": {
"ingredient": {
"type": "string"
},
"members": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": [
"ingredient",
"members"
],
"additionalProperties": false
}
},
"why": {
"maxItems": 3,
"type": "array",
"items": {
"type": "string"
}
},
"needs_swap": {
"type": "boolean"
},
"swap_reasons": {
"description": "When needs_swap: who and which strict rule this dinner breaks, e.g. \"Not safe for Mia (fish allergy)\". Tell the user and offer swap_meal.",
"type": "array",
"items": {
"type": "string"
}
},
"estimated_cost_cents": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
}
},
"required": [
"date",
"dow",
"kind",
"locked",
"attending",
"time_budget_minutes",
"why"
],
"additionalProperties": false
},
"options": {
"type": "array",
"items": {
"type": "object",
"properties": {
"recipe": {
"type": "object",
"properties": {
"id": {
"type": "string",
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
},
"title": {
"type": "string"
},
"source": {
"type": "string",
"enum": [
"household",
"library"
]
},
"cuisine": {
"type": [
"string",
"null"
]
},
"main_protein": {
"type": [
"string",
"null"
]
},
"total_minutes": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"active_minutes": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"base_servings": {
"type": "number"
},
"kcal_per_serving": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"nutrition_confidence": {
"type": [
"number",
"null"
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
}
},
"household_rating": {
"description": "Bayesian mean 1–5 across members.",
"type": [
"number",
"null"
]
},
"ratings_count": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"last_served": {
"type": [
"string",
"null"
]
},
"times_served": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"archived": {
"type": "boolean"
}
},
"required": [
"id",
"title",
"source",
"total_minutes",
"base_servings",
"tags"
],
"additionalProperties": false
},
"fit_score": {
"type": "number"
},
"why": {
"type": "array",
"items": {
"type": "string"
}
},
"portions": {
"type": "array",
"items": {
"type": "object",
"properties": {
"member_id": {
"type": "string",
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
},
"display_name": {
"type": "string"
},
"portion": {
"type": "number"
},
"kcal": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"kcal_target": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
}
},
"required": [
"member_id",
"display_name",
"portion"
],
"additionalProperties": false
}
}
},
"required": [
"recipe",
"fit_score",
"why"
],
"additionalProperties": false
}
},
"excluded_counts": {
"description": "How many recipes each hard constraint removed.",
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"type": "number"
}
},
"notices": {
"type": "array",
"items": {
"type": "object",
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
}
},
"required": [
"code",
"message"
],
"additionalProperties": false
}
}
},
"required": [
"day",
"options",
"notices"
],
"additionalProperties": false
}
}get_shopping_list · Get Shopping List
Read · scope dinner.read · roles owner, adult · readOnly true · destructive false · openWorld false
Returns the shopping list for a week's dinner plan, combined across recipes, scaled to the family's portions, with pantry staples and items already at home removed. Grouped by store (e.g. Butcher, Supermarket) and aisle section. Each item shows quantity, which dinners use it and an estimated cost. format='text' returns a plain list per store, ready to send or print. Read-only; to hand the list to Instacart use create_instacart_link.
Input / output schema
{
"input": {
"type": "object",
"properties": {
"week": {
"default": "next",
"type": "string",
"pattern": "^(current|next|previous|\\d{4}-\\d{2}-\\d{2})$",
"description": "'current', 'next', 'previous', or any date (YYYY-MM-DD) inside the wanted plan week."
},
"store": {
"description": "Store name to filter; default all.",
"type": "string",
"maxLength": 100
},
"include_checked": {
"default": false,
"type": "boolean"
},
"format": {
"default": "structured",
"type": "string",
"enum": [
"structured",
"text"
]
}
},
"additionalProperties": false
},
"output": {
"type": "object",
"properties": {
"week_start": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
"plan_status": {
"type": "string"
},
"plan_revision": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"list_version": {
"description": "list_hash",
"type": "string"
},
"stores": {
"type": "array",
"items": {
"type": "object",
"properties": {
"store": {
"type": "string"
},
"items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
},
"display_name": {
"type": "string"
},
"qty_display": {
"type": "string"
},
"unit_display": {
"type": "string"
},
"section": {
"type": "string",
"enum": [
"produce",
"meat",
"seafood",
"dairy",
"bakery",
"pantry",
"frozen",
"spices",
"beverages",
"household",
"other"
]
},
"store": {
"type": "string"
},
"status": {
"type": "string",
"enum": [
"needed",
"checked",
"have_it",
"removed"
]
},
"source": {
"type": "string",
"enum": [
"plan",
"manual"
]
},
"used_in": {
"description": "Recipe titles with dates.",
"type": "array",
"items": {
"type": "string"
}
},
"partially_in_pantry": {
"type": "boolean"
},
"estimated_cost_cents": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"note": {
"type": [
"string",
"null"
]
}
},
"required": [
"id",
"display_name",
"qty_display",
"unit_display",
"section",
"store",
"status",
"source"
],
"additionalProperties": false
}
},
"estimated_cost_cents": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"text": {
"type": [
"string",
"null"
]
}
},
"required": [
"store",
"items",
"estimated_cost_cents",
"text"
],
"additionalProperties": false
}
},
"last_instacart_link": {
"anyOf": [
{
"type": "object",
"properties": {
"url": {
"type": "string"
},
"created_at": {
"type": "string"
},
"matches_current_list": {
"type": "boolean"
}
},
"required": [
"url",
"created_at",
"matches_current_list"
],
"additionalProperties": false
},
{
"type": "null"
}
]
},
"notices": {
"type": "array",
"items": {
"type": "object",
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
}
},
"required": [
"code",
"message"
],
"additionalProperties": false
}
}
},
"required": [
"week_start",
"plan_revision",
"stores",
"notices"
],
"additionalProperties": false
}
}get_feedback_summary · Get Feedback Summary
Read · scope dinner.read · roles owner, adult · readOnly true · destructive false · openWorld false
Summarizes how the family rated dinners: for a week, or for a recipe or member, it returns each person's ratings and tags (e.g. 'too spicy', 'don't make again'), averages, favourites, and recipes someone dislikes. Includes feedback that adults recorded for the people in their household. Read-only.
Input / output schema
{
"input": {
"type": "object",
"properties": {
"week": {
"type": "string",
"pattern": "^(current|next|previous|\\d{4}-\\d{2}-\\d{2})$",
"description": "'current', 'next', 'previous', or any date (YYYY-MM-DD) inside the wanted plan week."
},
"recipe_id": {
"type": "string",
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
},
"recipe": {
"type": "string",
"maxLength": 100
},
"member": {
"type": "string",
"maxLength": 100
},
"top_n": {
"default": 5,
"type": "integer",
"minimum": 1,
"maximum": 20
}
},
"additionalProperties": false
},
"output": {
"type": "object",
"properties": {
"entries": {
"type": "array",
"items": {
"type": "object",
"properties": {
"date": {
"type": [
"string",
"null"
]
},
"recipe": {
"type": "string"
},
"recipe_id": {
"type": "string"
},
"member": {
"type": "string"
},
"rating": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"tags": {
"type": "array",
"items": {
"type": "string"
}
},
"recorded_by": {
"type": "string"
},
"via": {
"type": "string",
"enum": [
"agent",
"web",
"rating_link",
"import"
]
}
},
"required": [
"date",
"recipe",
"recipe_id",
"member",
"rating",
"tags",
"recorded_by",
"via"
],
"additionalProperties": false
}
},
"favourites": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
},
"title": {
"type": "string"
},
"source": {
"type": "string",
"enum": [
"household",
"library"
]
},
"cuisine": {
"type": [
"string",
"null"
]
},
"main_protein": {
"type": [
"string",
"null"
]
},
"total_minutes": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"active_minutes": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"base_servings": {
"type": "number"
},
"kcal_per_serving": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"nutrition_confidence": {
"type": [
"number",
"null"
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
}
},
"household_rating": {
"description": "Bayesian mean 1–5 across members.",
"type": [
"number",
"null"
]
},
"ratings_count": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"last_served": {
"type": [
"string",
"null"
]
},
"times_served": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"archived": {
"type": "boolean"
}
},
"required": [
"id",
"title",
"source",
"total_minutes",
"base_servings",
"tags"
],
"additionalProperties": false
}
},
"disliked": {
"type": "array",
"items": {
"type": "object",
"properties": {
"recipe": {
"type": "string"
},
"members": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": [
"recipe",
"members"
],
"additionalProperties": false
}
},
"missing_feedback": {
"type": "array",
"items": {
"type": "object",
"properties": {
"date": {
"type": "string"
},
"recipe": {
"type": "string"
},
"members": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": [
"date",
"recipe",
"members"
],
"additionalProperties": false
}
},
"notices": {
"type": "array",
"items": {
"type": "object",
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
}
},
"required": [
"code",
"message"
],
"additionalProperties": false
}
}
},
"required": [
"entries",
"notices"
],
"additionalProperties": false
}
}get_household_favorites · Get Household Favorites
Read · scope dinner.read · roles owner, adult · readOnly true · destructive false · openWorld false
Lists the family's favorite dinners, from their ratings (recent ones count more) and 'loved it' or 'more please' tags: each with how every person rates it, when it was last served and whether it's due back. With member, that person's favorites. Use it for questions like "what do the kids love?" or "what haven't we had in a while?". Favorites come back on their own every few weeks; nothing here changes a plan. Read-only.
Input / output schema
{
"input": {
"type": "object",
"properties": {
"member": {
"description": "Whose favorites (name or id). Default: the household.",
"type": "string",
"maxLength": 100
},
"limit": {
"default": 10,
"type": "integer",
"minimum": 1,
"maximum": 20
}
},
"additionalProperties": false
},
"output": {
"type": "object",
"properties": {
"favorites": {
"type": "array",
"items": {
"type": "object",
"properties": {
"recipe": {
"type": "string"
},
"recipe_id": {
"type": "string",
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
},
"member_means": {
"type": "array",
"items": {
"type": "object",
"properties": {
"member": {
"type": "string"
},
"mean": {
"type": "number"
},
"n": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
}
},
"required": [
"member",
"mean",
"n"
],
"additionalProperties": false
},
"description": "Each person's rating of it. mean is smoothed toward the household's rating of the dish (3.5 before anyone rated it) until the person has rated it more often, so a single 5★ can show as 4; recent ratings and similar dishes they rated count too. n is how many times they rated this one."
},
"last_served": {
"anyOf": [
{
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
{
"type": "null"
}
],
"description": "The last night it was on a plan, up to today. A rating alone does not set it."
},
"due_back": {
"type": "boolean"
}
},
"required": [
"recipe",
"recipe_id",
"member_means",
"last_served",
"due_back"
],
"additionalProperties": false
}
},
"notices": {
"type": "array",
"items": {
"type": "object",
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
}
},
"required": [
"code",
"message"
],
"additionalProperties": false
}
}
},
"required": [
"favorites",
"notices"
],
"additionalProperties": false
}
}list_plan_history · List Plan History
Read · scope dinner.read · roles owner, adult · readOnly true · destructive false · openWorld false
Lists past and upcoming weekly plans with dates, status, number of dinners, average rating and the dinners in each. Use it for questions like "what did we eat last month" or "when did we last have tacos". Read-only.
Input / output schema
{
"input": {
"type": "object",
"properties": {
"from": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
"to": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
"limit": {
"default": 8,
"type": "integer",
"minimum": 1,
"maximum": 26
},
"cursor": {
"type": "string",
"maxLength": 300
}
},
"additionalProperties": false
},
"output": {
"type": "object",
"properties": {
"weeks": {
"type": "array",
"items": {
"type": "object",
"properties": {
"plan_id": {
"type": "string"
},
"week_start": {
"type": "string"
},
"status": {
"type": "string"
},
"dinners": {
"type": "array",
"items": {
"type": "object",
"properties": {
"date": {
"type": "string"
},
"title": {
"type": "string"
},
"kind": {
"type": "string"
}
},
"required": [
"date",
"title",
"kind"
],
"additionalProperties": false
}
},
"avg_rating": {
"type": [
"number",
"null"
]
}
},
"required": [
"plan_id",
"week_start",
"status",
"dinners",
"avg_rating"
],
"additionalProperties": false
}
},
"next_cursor": {
"type": [
"string",
"null"
]
},
"hidden_by_plan_limit": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"notices": {
"type": "array",
"items": {
"type": "object",
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
}
},
"required": [
"code",
"message"
],
"additionalProperties": false
}
}
},
"required": [
"weeks",
"notices"
],
"additionalProperties": false
}
}get_subscription_status · Get Subscription Status
Read · scope dinner.read · roles owner, adult · readOnly true · destructive false · openWorld false
Returns whether the household has Ulivo Plus (the only plan) or is paused without it, whether it's in a free trial and when that ends, the next charge or cancellation date (dates are the household's local dates), usage against weekly limits, and a link to the Ulivo account page. Prices and plan changes are only on the Ulivo website, where the household owner manages the plan, not in chat. Read-only.
Input / output schema
{
"input": {
"type": "object",
"properties": {},
"additionalProperties": false
},
"output": {
"type": "object",
"properties": {
"plan": {
"type": "string",
"enum": [
"plus",
"none"
]
},
"plan_source": {
"type": "string",
"enum": [
"trial",
"subscription",
"comp",
"none"
]
},
"status": {
"description": "free_trial: a trial without a live subscription (started before card trials, or cancelled during the trial); planning pauses when it ends and nothing is charged. card_trial: Plus with a card on file, nothing charged yet; first charge on next_charge_on unless cancelled. paused: no Plus right now; planning waits until the owner manages the plan on the Ulivo website, and nothing is deleted.",
"type": "string",
"enum": [
"free_trial",
"card_trial",
"active",
"cancelling",
"past_due",
"complimentary",
"paused"
]
},
"trial_ends_at": {
"type": [
"string",
"null"
]
},
"trial_ends_on": {
"description": "The trial's last day as the household's local date.",
"anyOf": [
{
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
{
"type": "null"
}
]
},
"next_charge_on": {
"description": "Local date of the next charge, if the plan renews. No amounts: prices are on the Ulivo website.",
"anyOf": [
{
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
{
"type": "null"
}
]
},
"renews_at": {
"type": [
"string",
"null"
]
},
"cancels_at": {
"type": [
"string",
"null"
]
},
"limits": {
"type": "array",
"items": {
"type": "object",
"properties": {
"feature": {
"type": "string"
},
"used": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"limit": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
}
},
"required": [
"feature",
"used",
"limit"
],
"additionalProperties": false
}
},
"billing_url": {
"type": "string"
},
"plans_summary": {
"type": "string"
},
"notices": {
"type": "array",
"items": {
"type": "object",
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
}
},
"required": [
"code",
"message"
],
"additionalProperties": false
}
}
},
"required": [
"plan",
"billing_url",
"notices"
],
"additionalProperties": false
}
}update_household_settings · Update Household Settings
Write · scope dinner.write · roles owner, adult · readOnly false · destructive false · openWorld false
Changes household-level dinner settings: household name, timezone, plan week start day, grocery delivery day/time/provider, units (US or metric), default cooking-time budgets for weekdays and weekends, minimum days before repeating a recipe, leftovers per week, weekly grocery budget, and stores with the aisle sections each store handles (e.g. meat and seafood go to 'Butcher'). Only the fields you pass are changed. Weekly budget and more than one store require Plus; the weekly budget, stores and delivery settings can only be changed by the household owner.
Input / output schema
{
"input": {
"type": "object",
"properties": {
"household_name": {
"type": "string",
"minLength": 1,
"maxLength": 60
},
"timezone": {
"description": "IANA, e.g. America/New_York",
"type": "string",
"maxLength": 64
},
"plan_week_start_dow": {
"description": "The day plan weeks start on. It can't change while a current or upcoming plan exists; change it once those weeks have passed.",
"type": "string",
"enum": [
"mon",
"tue",
"wed",
"thu",
"fri",
"sat",
"sun"
]
},
"delivery": {
"type": "object",
"properties": {
"dow": {
"type": "string",
"enum": [
"mon",
"tue",
"wed",
"thu",
"fri",
"sat",
"sun"
]
},
"time": {
"type": "string",
"pattern": "^([01]\\d|2[0-3]):[0-5]\\d$"
},
"provider": {
"type": "string",
"enum": [
"instacart",
"other",
"pickup",
"none"
]
}
},
"additionalProperties": false
},
"unit_system": {
"type": "string",
"enum": [
"us_customary",
"metric"
]
},
"default_time_budget_minutes": {
"type": "object",
"properties": {
"weekday": {
"type": "integer",
"minimum": 10,
"maximum": 240
},
"weekend": {
"type": "integer",
"minimum": 10,
"maximum": 240
}
},
"additionalProperties": false
},
"min_repeat_days": {
"type": "integer",
"minimum": 0,
"maximum": 60
},
"favorite_return_days": {
"description": "How often favorites come back, in days (14–60; default 21), e.g. \"bring the souvlaki back every two weeks\" = 14.",
"type": "integer",
"minimum": 14,
"maximum": 60
},
"leftovers_target_per_week": {
"type": "integer",
"minimum": 0,
"maximum": 3
},
"weekly_budget_usd": {
"description": "null removes the budget.",
"anyOf": [
{
"type": "number",
"minimum": 20,
"maximum": 2000
},
{
"type": "null"
}
]
},
"stores": {
"description": "Full replacement list of stores.",
"maxItems": 5,
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string",
"minLength": 1,
"maxLength": 40
},
"is_default": {
"type": "boolean"
},
"sections": {
"type": "array",
"items": {
"type": "string",
"enum": [
"produce",
"meat",
"seafood",
"dairy",
"bakery",
"pantry",
"frozen",
"spices",
"beverages",
"household",
"other"
]
}
},
"instacart_enabled": {
"type": "boolean"
}
},
"required": [
"name"
],
"additionalProperties": false
}
},
"idempotency_key": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,64}$",
"description": "Optional. Reuse the same value if you retry this exact call after a timeout or error."
}
},
"additionalProperties": false
},
"output": {
"type": "object",
"properties": {
"household": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"timezone": {
"type": "string"
},
"plan_week_start_dow": {
"type": "string",
"enum": [
"mon",
"tue",
"wed",
"thu",
"fri",
"sat",
"sun"
]
},
"today": {
"description": "The household's local date, in its timezone. Use it to resolve 'tonight', 'tomorrow' or 'this Tuesday'.",
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
"current_week_start": {
"description": "Start date of the plan week that contains today.",
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
"delivery": {
"anyOf": [
{
"type": "object",
"properties": {
"dow": {
"type": "string",
"enum": [
"mon",
"tue",
"wed",
"thu",
"fri",
"sat",
"sun"
]
},
"time": {
"type": "string"
},
"provider": {
"type": "string",
"enum": [
"instacart",
"other",
"pickup",
"none"
]
}
},
"additionalProperties": false
},
{
"type": "null"
}
]
},
"unit_system": {
"type": "string",
"enum": [
"us_customary",
"metric"
]
},
"default_time_budget_minutes": {
"type": "object",
"properties": {
"weekday": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"weekend": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
}
},
"required": [
"weekday",
"weekend"
],
"additionalProperties": false
},
"weekly_budget_cents": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"leftovers_target_per_week": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"min_repeat_days": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"favorite_return_days": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "How many days until a favorite comes back (default 21)."
},
"plan": {
"type": "string",
"enum": [
"plus",
"none"
],
"description": "plus: the household has Ulivo Plus (trial, subscription or complimentary). none: no Plus right now, so planning is paused; reading and family edits still work."
}
},
"required": [
"id",
"name",
"timezone",
"plan_week_start_dow",
"delivery",
"unit_system",
"default_time_budget_minutes",
"weekly_budget_cents",
"leftovers_target_per_week",
"min_repeat_days",
"favorite_return_days",
"plan"
],
"additionalProperties": false
},
"stores": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
},
"name": {
"type": "string"
},
"is_default": {
"type": "boolean"
},
"sections": {
"type": "array",
"items": {
"type": "string",
"enum": [
"produce",
"meat",
"seafood",
"dairy",
"bakery",
"pantry",
"frozen",
"spices",
"beverages",
"household",
"other"
]
}
},
"instacart_enabled": {
"type": "boolean"
}
},
"required": [
"id",
"name",
"is_default",
"sections",
"instacart_enabled"
],
"additionalProperties": false
}
},
"changed_fields": {
"type": "array",
"items": {
"type": "string"
}
},
"notices": {
"type": "array",
"items": {
"type": "object",
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
}
},
"required": [
"code",
"message"
],
"additionalProperties": false
}
},
"replayed": {
"type": "boolean"
}
},
"required": [
"household",
"changed_fields",
"notices",
"replayed"
],
"additionalProperties": false
}
}save_household_member · Save Household Member
Write · scope dinner.write · roles owner, adult · readOnly false · destructive false · openWorld false
Adds a person to the household or updates one. People can be adults or parent-managed teen/child profiles (minors never get their own login). Set their name, age band, portion size, allergies, foods they never eat (exclusions), diets, dislikes (avoided when possible), a weekly at-home schedule with optional max cooking minutes per weekday, an optional dinner calorie target, and an adult's weight goal (recorded and shown back only). Allergies, exclusions and diets are strict: the planner never schedules a dinner that breaks them. Allergies, a calorie target or a weight goal need the account holder's health-data consent the first time. Calorie targets and per-person cooking-time limits require Plus. Without member_id, a name already in the household updates that person (refused if their age band would change), so a new person needs a new name. Creates the household if none exists.
Input / output schema
{
"input": {
"type": "object",
"properties": {
"member_id": {
"description": "Omit to add a new person, or to update the person who already has this display_name.",
"type": "string",
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
},
"member": {
"description": "Existing member name, alternative to member_id.",
"type": "string",
"maxLength": 100
},
"display_name": {
"description": "First name or nickname only.",
"type": "string",
"minLength": 1,
"maxLength": 40
},
"age_band": {
"type": "string",
"enum": [
"adult",
"teen_13_17",
"child_under_13"
]
},
"is_me": {
"description": "True if this profile is the person using this connection (links it to their account).",
"type": "boolean"
},
"portion_factor": {
"description": "Share of a standard adult portion, rounded to the nearest 0.05. Typical: babies and toddlers (under 3) 0.25–0.4, young children 0.5–0.6, older children 0.75, teens and adults 1, bigger appetites 1.25–1.5. Defaults from the age band when a person is added.",
"type": "number",
"minimum": 0.25,
"maximum": 2
},
"dinner_kcal_target": {
"description": "Calories for dinner, chosen by the user. null removes it.",
"anyOf": [
{
"type": "integer",
"minimum": 250,
"maximum": 2000
},
{
"type": "null"
}
]
},
"weight_goal": {
"description": "An adult's own weight goal, e.g. { direction: 'lose', lbs: 5 }. Ulivo only records it and shows it back; it never sets or changes calorie targets, portions or dinners, so don't plan, size portions or suggest calories from it. Health information: needs the consent. null removes it.",
"anyOf": [
{
"type": "object",
"properties": {
"direction": {
"type": "string",
"enum": [
"lose",
"gain"
]
},
"lbs": {
"type": "integer",
"minimum": 1,
"maximum": 100
}
},
"required": [
"direction",
"lbs"
],
"additionalProperties": false
},
{
"type": "null"
}
]
},
"constraints_set": {
"description": "Replaces all constraints.",
"maxItems": 40,
"type": "array",
"items": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"allergy",
"exclusion",
"diet",
"dislike"
]
},
"term": {
"type": "string",
"minLength": 2,
"maxLength": 60,
"description": "Food, food group, allergen or diet, e.g. 'cheese', 'peanuts', 'shellfish', 'vegetarian', 'banana'."
}
},
"required": [
"type",
"term"
],
"additionalProperties": false
}
},
"constraints_add": {
"maxItems": 20,
"type": "array",
"items": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"allergy",
"exclusion",
"diet",
"dislike"
]
},
"term": {
"type": "string",
"minLength": 2,
"maxLength": 60,
"description": "Food, food group, allergen or diet, e.g. 'cheese', 'peanuts', 'shellfish', 'vegetarian', 'banana'."
}
},
"required": [
"type",
"term"
],
"additionalProperties": false
}
},
"constraints_remove": {
"maxItems": 20,
"type": "array",
"items": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"allergy",
"exclusion",
"diet",
"dislike"
]
},
"term": {
"type": "string",
"minLength": 2,
"maxLength": 60,
"description": "Food, food group, allergen or diet, e.g. 'cheese', 'peanuts', 'shellfish', 'vegetarian', 'banana'."
}
},
"required": [
"type",
"term"
],
"additionalProperties": false
}
},
"schedule": {
"description": "Weekly defaults; days not listed are unchanged.",
"maxItems": 7,
"type": "array",
"items": {
"type": "object",
"properties": {
"dow": {
"type": "string",
"enum": [
"mon",
"tue",
"wed",
"thu",
"fri",
"sat",
"sun"
]
},
"attending": {
"type": "boolean"
},
"max_cook_minutes": {
"anyOf": [
{
"type": "integer",
"minimum": 5,
"maximum": 240
},
{
"type": "null"
}
]
},
"note": {
"description": "Short reason shown in plans, e.g. 'padel'.",
"anyOf": [
{
"type": "string",
"maxLength": 60
},
{
"type": "null"
}
]
}
},
"required": [
"dow",
"attending"
],
"additionalProperties": false
}
},
"health_data_consent": {
"description": "Set true only after the user has agreed to both parts of the consent text returned in a HEALTH_DATA_CONSENT_REQUIRED error: storing this health information, and sharing it with this assistant.",
"type": "boolean"
},
"idempotency_key": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,64}$",
"description": "Optional. Reuse the same value if you retry this exact call after a timeout or error."
}
},
"additionalProperties": false
},
"output": {
"type": "object",
"properties": {
"member": {
"type": "object",
"properties": {
"id": {
"type": "string",
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
},
"display_name": {
"type": "string"
},
"age_band": {
"type": "string",
"enum": [
"adult",
"teen_13_17",
"child_under_13"
]
},
"has_login": {
"type": "boolean"
},
"role": {
"type": "string",
"enum": [
"owner",
"adult",
"profile_only"
]
},
"portion_factor": {
"type": "number"
},
"dinner_kcal_target": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"weight_goal": {
"anyOf": [
{
"type": "object",
"properties": {
"direction": {
"type": "string",
"enum": [
"lose",
"gain"
]
},
"lbs": {
"type": "integer",
"minimum": 1,
"maximum": 100
}
},
"required": [
"direction",
"lbs"
],
"additionalProperties": false
},
{
"type": "null"
}
]
},
"constraints": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
},
"type": {
"type": "string",
"enum": [
"allergy",
"exclusion",
"diet",
"dislike"
]
},
"term": {
"type": "string"
},
"resolved_kind": {
"type": "string",
"enum": [
"tag",
"ingredient",
"allergen",
"diet",
"recipe"
]
},
"resolved_key": {
"type": "string"
},
"label": {
"type": "string"
},
"strength": {
"type": "string",
"enum": [
"hard",
"soft"
]
}
},
"required": [
"id",
"type",
"term",
"resolved_kind",
"resolved_key",
"label",
"strength"
],
"additionalProperties": false
}
},
"schedule": {
"type": "array",
"items": {
"type": "object",
"properties": {
"dow": {
"type": "string",
"enum": [
"mon",
"tue",
"wed",
"thu",
"fri",
"sat",
"sun"
]
},
"attending": {
"type": "boolean"
},
"max_cook_minutes": {
"anyOf": [
{
"type": "integer",
"minimum": 5,
"maximum": 240
},
{
"type": "null"
}
]
},
"note": {
"description": "Short reason shown in plans, e.g. 'padel'.",
"anyOf": [
{
"type": "string",
"maxLength": 60
},
{
"type": "null"
}
]
}
},
"required": [
"dow",
"attending"
],
"additionalProperties": false
}
}
},
"required": [
"id",
"display_name",
"age_band",
"has_login",
"role",
"portion_factor",
"dinner_kcal_target",
"weight_goal",
"constraints",
"schedule"
],
"additionalProperties": false
},
"created": {
"type": "boolean"
},
"household_created": {
"type": "boolean"
},
"deduplicated": {
"type": "boolean"
},
"affected_plans": {
"description": "Upcoming plans with nights from today on whose dinner needs a swap after this save.",
"type": "array",
"items": {
"type": "object",
"properties": {
"week_start": {
"type": "string"
},
"infeasible_days": {
"type": "array",
"items": {
"type": "string"
}
},
"nights": {
"type": "array",
"items": {
"type": "object",
"properties": {
"date": {
"type": "string"
},
"reasons": {
"type": "array",
"items": {
"type": "string"
},
"description": "Why the dinner no longer fits, e.g. \"Not safe for Rita (dairy free diet)\"."
},
"newly_flagged": {
"type": "boolean",
"description": "true when this save made the night need a swap, or added a new reason; false when it already needed one for the same reasons."
},
"new_reasons": {
"description": "The reasons this save added.",
"type": "array",
"items": {
"type": "string"
}
}
},
"required": [
"date",
"reasons",
"newly_flagged"
],
"additionalProperties": false
}
}
},
"required": [
"week_start",
"infeasible_days"
],
"additionalProperties": false
}
},
"notices": {
"type": "array",
"items": {
"type": "object",
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
}
},
"required": [
"code",
"message"
],
"additionalProperties": false
}
},
"replayed": {
"type": "boolean"
}
},
"required": [
"member",
"created",
"notices",
"replayed"
],
"additionalProperties": false
}
}remove_household_member · Remove Household Member
Write · scope dinner.write · roles owner, adult · readOnly false · destructive true · openWorld false
Removes a person from the household's dinner planning. Their profile, constraints and schedule are hidden immediately and permanently deleted after 30 days; ratings they gave stay as anonymous household ratings. If the person has their own login, they lose access to this household (their account remains). This can't be undone in chat or on the website. Only the owner can remove adults with logins.
Input / output schema
{
"input": {
"type": "object",
"properties": {
"member_id": {
"type": "string",
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
},
"member": {
"type": "string",
"maxLength": 100
},
"idempotency_key": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,64}$",
"description": "Optional. Reuse the same value if you retry this exact call after a timeout or error."
}
},
"additionalProperties": false
},
"output": {
"type": "object",
"properties": {
"removed_member_id": {
"type": "string"
},
"restorable_until": {
"type": "string",
"description": "When the hidden profile is permanently deleted."
},
"access_revoked_for_account": {
"type": "boolean"
},
"notices": {
"type": "array",
"items": {
"type": "object",
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
}
},
"required": [
"code",
"message"
],
"additionalProperties": false
}
},
"replayed": {
"type": "boolean"
}
},
"required": [
"removed_member_id",
"restorable_until",
"notices",
"replayed"
],
"additionalProperties": false
}
}set_week_schedule · Set Week Schedule
Write · scope dinner.write · roles owner, adult · readOnly false · destructive false · openWorld false
Sets one-off schedule changes for specific dates: who is home for dinner and the maximum cooking time that night (e.g. "Leo has a tournament Saturday", "only 15 minutes on Monday", "Alex is away Tuesday to Thursday"). Overrides the weekly defaults for those dates only. If a plan exists for the week, portions and fit are re-checked and any night that no longer fits is reported. Requires Plus.
Input / output schema
{
"input": {
"type": "object",
"properties": {
"changes": {
"minItems": 1,
"maxItems": 21,
"type": "array",
"items": {
"type": "object",
"properties": {
"date": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
"members_away": {
"description": "Names or ids not eating at home.",
"type": "array",
"items": {
"type": "string",
"maxLength": 100
}
},
"members_home": {
"type": "array",
"items": {
"type": "string",
"maxLength": 100
}
},
"max_cook_minutes": {
"anyOf": [
{
"type": "integer",
"minimum": 5,
"maximum": 240
},
{
"type": "null"
}
]
},
"note": {
"anyOf": [
{
"type": "string",
"maxLength": 60
},
{
"type": "null"
}
]
},
"clear": {
"description": "Remove all overrides for this date.",
"type": "boolean"
}
},
"required": [
"date"
],
"additionalProperties": false
}
},
"expected_revision": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"idempotency_key": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,64}$",
"description": "Optional. Reuse the same value if you retry this exact call after a timeout or error."
}
},
"required": [
"changes"
],
"additionalProperties": false
},
"output": {
"type": "object",
"properties": {
"applied": {
"type": "array",
"items": {
"type": "object",
"properties": {
"date": {
"type": "string"
},
"attending": {
"type": "array",
"items": {
"type": "string"
}
},
"time_budget_minutes": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"note": {
"type": [
"string",
"null"
]
}
},
"required": [
"date",
"attending",
"time_budget_minutes",
"note"
],
"additionalProperties": false
}
},
"plan_impacts": {
"type": "array",
"items": {
"type": "object",
"properties": {
"date": {
"type": "string"
},
"status": {
"type": "string",
"enum": [
"ok_portions_updated",
"needs_swap",
"no_one_home_marked_skip"
]
},
"detail": {
"type": "string"
}
},
"required": [
"date",
"status",
"detail"
],
"additionalProperties": false
}
},
"plan_revision": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"shopping_list_changed_since_handoff": {
"type": "boolean"
},
"notices": {
"type": "array",
"items": {
"type": "object",
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
}
},
"required": [
"code",
"message"
],
"additionalProperties": false
}
},
"replayed": {
"type": "boolean"
}
},
"required": [
"applied",
"notices",
"replayed"
],
"additionalProperties": false
}
}save_recipe · Save Recipe
Write · scope dinner.write · roles owner, adult · readOnly false · destructive false · openWorld false
Adds a recipe to the household's private recipe library, or updates one. Accepts title, servings, times, ingredient lines (plain text like '2 lb chicken thighs' or structured), steps, cuisine, main protein, tags (e.g. leftovers_ok, kid_friendly), an optional source URL and name for attribution, and an optional rating from the household. Ingredients are matched to a food database to check allergies and estimate nutrition; lines that couldn't be understood are returned as warnings so you can clarify. Every recipe is checked: cuisine must be Mediterranean (greek, italian, spanish, portuguese, levantine, turkish, north_african, provencal, mediterranean_other) and it's checked against everyone's food rules; one that isn't Mediterranean is kept as needs_fix with reasons and isn't planned until fixed.
Input / output schema
{
"input": {
"type": "object",
"properties": {
"recipe_id": {
"description": "Omit to create.",
"type": "string",
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
},
"title": {
"type": "string",
"minLength": 2,
"maxLength": 100
},
"description": {
"type": "string",
"maxLength": 300
},
"base_servings": {
"type": "number",
"minimum": 1,
"maximum": 24
},
"total_minutes": {
"type": "integer",
"minimum": 1,
"maximum": 1440
},
"active_minutes": {
"type": "integer",
"minimum": 1,
"maximum": 1440
},
"ingredients": {
"minItems": 1,
"maxItems": 60,
"type": "array",
"items": {
"type": "object",
"properties": {
"text": {
"description": "Original line, e.g. '1 1/2 cups shredded mozzarella'. Either text or name is required.",
"type": "string",
"maxLength": 200
},
"name": {
"type": "string",
"maxLength": 80
},
"quantity": {
"anyOf": [
{
"type": "number",
"exclusiveMinimum": 0
},
{
"type": "null"
}
]
},
"unit": {
"anyOf": [
{
"type": "string",
"maxLength": 20
},
{
"type": "null"
}
]
},
"preparation": {
"anyOf": [
{
"type": "string",
"maxLength": 60
},
{
"type": "null"
}
]
},
"optional": {
"default": false,
"type": "boolean"
},
"omittable": {
"default": false,
"description": "Can be left off individual plates (e.g. a cheese topping).",
"type": "boolean"
}
},
"additionalProperties": false
}
},
"steps": {
"maxItems": 40,
"type": "array",
"items": {
"type": "string",
"maxLength": 600
}
},
"cuisine": {
"type": "string",
"maxLength": 40
},
"main_protein": {
"type": "string",
"enum": [
"chicken",
"beef",
"pork",
"lamb",
"turkey",
"fish",
"shellfish",
"eggs",
"tofu",
"beans_legumes",
"cheese_dairy",
"none_veg",
"mixed"
]
},
"tags": {
"maxItems": 10,
"type": "array",
"items": {
"type": "string",
"enum": [
"kid_friendly",
"leftovers_ok",
"freezer_ok",
"one_pot",
"sheet_pan",
"slow_cooker",
"grill",
"no_cook",
"make_ahead",
"spicy"
]
}
},
"season_months": {
"type": "array",
"items": {
"type": "integer",
"minimum": 1,
"maximum": 12
}
},
"source_url": {
"type": "string",
"maxLength": 500,
"format": "uri"
},
"source_name": {
"type": "string",
"maxLength": 80
},
"household_rating": {
"description": "Overall rating from an existing list (e.g. a spreadsheet). Per-person ratings go in record_meal_feedback.",
"type": "number",
"minimum": 1,
"maximum": 5
},
"kcal_per_serving_override": {
"type": "integer",
"minimum": 50,
"maximum": 3000
},
"idempotency_key": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,64}$",
"description": "Optional. Reuse the same value if you retry this exact call after a timeout or error."
}
},
"additionalProperties": false
},
"output": {
"type": "object",
"properties": {
"recipe": {
"type": "object",
"properties": {
"id": {
"type": "string",
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
},
"title": {
"type": "string"
},
"source": {
"type": "string",
"enum": [
"household",
"library"
]
},
"cuisine": {
"type": [
"string",
"null"
]
},
"main_protein": {
"type": [
"string",
"null"
]
},
"total_minutes": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"active_minutes": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"base_servings": {
"type": "number"
},
"kcal_per_serving": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"nutrition_confidence": {
"type": [
"number",
"null"
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
}
},
"household_rating": {
"description": "Bayesian mean 1–5 across members.",
"type": [
"number",
"null"
]
},
"ratings_count": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"last_served": {
"type": [
"string",
"null"
]
},
"times_served": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"archived": {
"type": "boolean"
}
},
"required": [
"id",
"title",
"source",
"total_minutes",
"base_servings",
"tags"
],
"additionalProperties": false
},
"created": {
"type": "boolean"
},
"deduplicated": {
"type": "boolean"
},
"warnings": {
"type": "array",
"items": {
"type": "object",
"properties": {
"line": {
"type": "string"
},
"issue": {
"type": "string",
"enum": [
"unparsed_quantity",
"unknown_ingredient",
"unit_not_convertible",
"possible_allergen_unmapped"
]
},
"suggestion": {
"type": [
"string",
"null"
]
}
},
"required": [
"line",
"issue",
"suggestion"
],
"additionalProperties": false
}
},
"allergen_summary": {
"type": "array",
"items": {
"type": "string"
}
},
"nutrition_confidence": {
"type": [
"number",
"null"
]
},
"status": {
"type": "string",
"enum": [
"active",
"needs_fix"
]
},
"med_fit": {
"type": "string",
"enum": [
"pass",
"borderline",
"fail"
]
},
"med_fit_reasons": {
"type": "array",
"items": {
"type": "string"
}
},
"conflicts": {
"type": "array",
"items": {
"type": "object",
"properties": {
"member": {
"type": "string"
},
"rule": {
"type": "string"
},
"ingredient": {
"type": "string"
}
},
"required": [
"member",
"rule",
"ingredient"
],
"additionalProperties": false
}
},
"notices": {
"type": "array",
"items": {
"type": "object",
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
}
},
"required": [
"code",
"message"
],
"additionalProperties": false
}
},
"replayed": {
"type": "boolean"
}
},
"required": [
"recipe",
"created",
"warnings",
"notices",
"replayed"
],
"additionalProperties": false
}
}create_recipe · Create Recipe
Write · scope dinner.write · roles owner, adult · readOnly false · destructive false · openWorld false
Creates a new dinner recipe you wrote for this household: title, cuisine (a Mediterranean one), main protein, servings, times, ingredient lines and steps. Ulivo checks it: it must be Mediterranean (cook with olive oil; no soy sauce, tortillas, cheddar and the like), and it's checked against everyone's allergies and food rules. A recipe that isn't Mediterranean is kept as needs_fix with the reasons: fix it and save again with save_recipe. One that someone can't eat is kept and only planned when they're away. Private to this household. Optionally place it on a planned night (plan_on). Always pass on the allergy notice.
Input / output schema
{
"input": {
"type": "object",
"properties": {
"title": {
"type": "string",
"minLength": 2,
"maxLength": 100
},
"description": {
"type": "string",
"maxLength": 300
},
"cuisine": {
"type": "string",
"enum": [
"greek",
"italian",
"spanish",
"portuguese",
"levantine",
"turkish",
"north_african",
"provencal",
"mediterranean_other"
]
},
"main_protein": {
"type": "string",
"enum": [
"chicken",
"beef",
"pork",
"lamb",
"turkey",
"fish",
"shellfish",
"eggs",
"tofu",
"beans_legumes",
"cheese_dairy",
"none_veg",
"mixed"
]
},
"base_servings": {
"type": "number",
"minimum": 1,
"maximum": 24
},
"total_minutes": {
"type": "integer",
"minimum": 1,
"maximum": 600
},
"active_minutes": {
"type": "integer",
"minimum": 1,
"maximum": 600
},
"ingredients": {
"minItems": 2,
"maxItems": 40,
"type": "array",
"items": {
"type": "object",
"properties": {
"text": {
"description": "Original line, e.g. '1 1/2 cups shredded mozzarella'. Either text or name is required.",
"type": "string",
"maxLength": 200
},
"name": {
"type": "string",
"maxLength": 80
},
"quantity": {
"anyOf": [
{
"type": "number",
"exclusiveMinimum": 0
},
{
"type": "null"
}
]
},
"unit": {
"anyOf": [
{
"type": "string",
"maxLength": 20
},
{
"type": "null"
}
]
},
"preparation": {
"anyOf": [
{
"type": "string",
"maxLength": 60
},
{
"type": "null"
}
]
},
"optional": {
"default": false,
"type": "boolean"
},
"omittable": {
"default": false,
"description": "Can be left off individual plates (e.g. a cheese topping).",
"type": "boolean"
}
},
"additionalProperties": false
}
},
"steps": {
"minItems": 1,
"maxItems": 30,
"type": "array",
"items": {
"type": "string",
"maxLength": 600
}
},
"tags": {
"maxItems": 10,
"type": "array",
"items": {
"type": "string",
"enum": [
"kid_friendly",
"leftovers_ok",
"freezer_ok",
"one_pot",
"sheet_pan",
"slow_cooker",
"grill",
"no_cook",
"make_ahead",
"spicy"
]
}
},
"season_months": {
"type": "array",
"items": {
"type": "integer",
"minimum": 1,
"maximum": 12
}
},
"origin": {
"default": "ai_generated",
"description": "'user' when the person dictated their own recipe.",
"type": "string",
"enum": [
"ai_generated",
"user"
]
},
"plan_on": {
"description": "A planned night to put it on (same checks as swap_meal).",
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
"idempotency_key": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,64}$",
"description": "Optional. Reuse the same value if you retry this exact call after a timeout or error."
}
},
"required": [
"title",
"cuisine",
"main_protein",
"base_servings",
"total_minutes",
"ingredients",
"steps"
],
"additionalProperties": false
},
"output": {
"type": "object",
"properties": {
"recipe": {
"type": "object",
"properties": {
"id": {
"type": "string",
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
},
"title": {
"type": "string"
},
"source": {
"type": "string",
"enum": [
"household",
"library"
]
},
"cuisine": {
"type": [
"string",
"null"
]
},
"main_protein": {
"type": [
"string",
"null"
]
},
"total_minutes": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"active_minutes": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"base_servings": {
"type": "number"
},
"kcal_per_serving": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"nutrition_confidence": {
"type": [
"number",
"null"
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
}
},
"household_rating": {
"description": "Bayesian mean 1–5 across members.",
"type": [
"number",
"null"
]
},
"ratings_count": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"last_served": {
"type": [
"string",
"null"
]
},
"times_served": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"archived": {
"type": "boolean"
}
},
"required": [
"id",
"title",
"source",
"total_minutes",
"base_servings",
"tags"
],
"additionalProperties": false
},
"status": {
"type": "string",
"enum": [
"active",
"needs_fix"
]
},
"med_fit": {
"type": "string",
"enum": [
"pass",
"borderline",
"fail"
]
},
"med_fit_reasons": {
"type": "array",
"items": {
"type": "string"
}
},
"conflicts": {
"type": "array",
"items": {
"type": "object",
"properties": {
"member": {
"type": "string"
},
"rule": {
"type": "string"
},
"ingredient": {
"type": "string"
}
},
"required": [
"member",
"rule",
"ingredient"
],
"additionalProperties": false
}
},
"allergen_summary": {
"type": "array",
"items": {
"type": "string"
}
},
"allergy_notice": {
"type": "string"
},
"warnings": {
"type": "array",
"items": {
"type": "object",
"properties": {
"line": {
"type": "string"
},
"issue": {
"type": "string",
"enum": [
"unparsed_quantity",
"unknown_ingredient",
"unit_not_convertible",
"possible_allergen_unmapped"
]
},
"suggestion": {
"type": [
"string",
"null"
]
}
},
"required": [
"line",
"issue",
"suggestion"
],
"additionalProperties": false
}
},
"placed": {
"type": "object",
"properties": {
"date": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
"ok": {
"type": "boolean"
},
"reason": {
"type": "string"
}
},
"required": [
"date",
"ok"
],
"additionalProperties": false
},
"notices": {
"type": "array",
"items": {
"type": "object",
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
}
},
"required": [
"code",
"message"
],
"additionalProperties": false
}
},
"replayed": {
"type": "boolean"
}
},
"required": [
"recipe",
"status",
"med_fit",
"med_fit_reasons",
"conflicts",
"allergen_summary",
"allergy_notice",
"warnings",
"notices",
"replayed"
],
"additionalProperties": false
}
}request_recipe_promotion · Request Recipe Promotion
Write · scope dinner.write · roles owner · readOnly false · destructive false · openWorld false
Asks Ulivo to consider one of this household's recipes for the recipes all families can use. Only the household owner, and only after they agree to this text, word for word: "Share this recipe (title, ingredients and steps only) for Ulivo to review and possibly add, without your name or household details, to the recipes all families can use." Set consent true only if they agreed. A person reviews it; nothing is shared until then, and the household keeps its own copy. Recipes saved from a website can't be shared.
Input / output schema
{
"input": {
"type": "object",
"properties": {
"recipe_id": {
"type": "string",
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
},
"consent": {
"type": "boolean",
"const": true
},
"idempotency_key": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,64}$",
"description": "Optional. Reuse the same value if you retry this exact call after a timeout or error."
}
},
"required": [
"recipe_id",
"consent"
],
"additionalProperties": false
},
"output": {
"type": "object",
"properties": {
"request_id": {
"type": "string",
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
},
"state": {
"type": "string",
"const": "pending"
},
"notices": {
"type": "array",
"items": {
"type": "object",
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
}
},
"required": [
"code",
"message"
],
"additionalProperties": false
}
},
"replayed": {
"type": "boolean"
}
},
"required": [
"request_id",
"state",
"notices",
"replayed"
],
"additionalProperties": false
}
}import_recipes · Import Recipes
Write · scope dinner.write · roles owner, adult · readOnly false · destructive false · openWorld false
Imports up to 50 recipes at once into the household's private library, for example rows the user has in a spreadsheet. Each row has a title and, where available, servings, total minutes, ingredient lines, steps, tags, source and an overall rating. Rows with only a title are saved as 'needs details' and are not used in plans until ingredients are added. Returns a per-row result (created, updated, duplicate, rejected with reason).
Input / output schema
{
"input": {
"type": "object",
"properties": {
"rows": {
"minItems": 1,
"maxItems": 50,
"type": "array",
"items": {
"type": "object",
"properties": {
"row_ref": {
"description": "Caller's row label, echoed back (e.g. 'Sheet row 12').",
"type": "string",
"maxLength": 40
},
"title": {
"type": "string",
"minLength": 2,
"maxLength": 100
},
"base_servings": {
"type": "number",
"minimum": 1,
"maximum": 24
},
"total_minutes": {
"type": "integer",
"minimum": 1,
"maximum": 1440
},
"ingredients": {
"maxItems": 60,
"type": "array",
"items": {
"type": "object",
"properties": {
"text": {
"description": "Original line, e.g. '1 1/2 cups shredded mozzarella'. Either text or name is required.",
"type": "string",
"maxLength": 200
},
"name": {
"type": "string",
"maxLength": 80
},
"quantity": {
"anyOf": [
{
"type": "number",
"exclusiveMinimum": 0
},
{
"type": "null"
}
]
},
"unit": {
"anyOf": [
{
"type": "string",
"maxLength": 20
},
{
"type": "null"
}
]
},
"preparation": {
"anyOf": [
{
"type": "string",
"maxLength": 60
},
{
"type": "null"
}
]
},
"optional": {
"default": false,
"type": "boolean"
},
"omittable": {
"default": false,
"description": "Can be left off individual plates (e.g. a cheese topping).",
"type": "boolean"
}
},
"additionalProperties": false
}
},
"ingredients_text": {
"description": "Alternative: all ingredient lines in one block, one per line.",
"type": "string",
"maxLength": 4000
},
"steps_text": {
"type": "string",
"maxLength": 8000
},
"tags": {
"type": "array",
"items": {
"type": "string",
"maxLength": 40
}
},
"cuisine": {
"type": "string",
"maxLength": 40
},
"main_protein": {
"type": "string",
"maxLength": 40
},
"source_url": {
"type": "string",
"maxLength": 500
},
"household_rating": {
"type": "number",
"minimum": 1,
"maximum": 5
},
"last_made": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
}
},
"required": [
"title"
],
"additionalProperties": false
}
},
"on_duplicate": {
"default": "skip",
"type": "string",
"enum": [
"skip",
"update"
]
},
"idempotency_key": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,64}$",
"description": "Optional. Reuse the same value if you retry this exact call after a timeout or error."
}
},
"required": [
"rows"
],
"additionalProperties": false
},
"output": {
"type": "object",
"properties": {
"results": {
"type": "array",
"items": {
"type": "object",
"properties": {
"row_ref": {
"type": [
"string",
"null"
]
},
"title": {
"type": "string"
},
"status": {
"type": "string",
"enum": [
"created",
"updated",
"duplicate_skipped",
"needs_details",
"rejected"
]
},
"recipe_id": {
"type": [
"string",
"null"
]
},
"reason": {
"type": [
"string",
"null"
]
},
"warnings_count": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
}
},
"required": [
"row_ref",
"title",
"status",
"recipe_id",
"reason",
"warnings_count"
],
"additionalProperties": false
}
},
"summary": {
"type": "object",
"properties": {
"created": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"updated": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"skipped": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"needs_details": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"rejected": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
}
},
"required": [
"created",
"updated",
"skipped",
"needs_details",
"rejected"
],
"additionalProperties": false
},
"notices": {
"type": "array",
"items": {
"type": "object",
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
}
},
"required": [
"code",
"message"
],
"additionalProperties": false
}
},
"replayed": {
"type": "boolean"
}
},
"required": [
"results",
"summary",
"notices",
"replayed"
],
"additionalProperties": false
}
}archive_recipe · Archive Recipe
Write · scope dinner.write · roles owner, adult · readOnly false · destructive true · openWorld false
Archives a household recipe so it is no longer planned or listed (unless include_archived), or restores it. Ratings and history are kept. Library recipes can be hidden for this household the same way. Nothing is permanently deleted.
Input / output schema
{
"input": {
"type": "object",
"properties": {
"recipe_id": {
"type": "string",
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
},
"recipe": {
"type": "string",
"maxLength": 100
},
"restore": {
"default": false,
"type": "boolean"
},
"idempotency_key": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,64}$",
"description": "Optional. Reuse the same value if you retry this exact call after a timeout or error."
}
},
"additionalProperties": false
},
"output": {
"type": "object",
"properties": {
"recipe": {
"type": "object",
"properties": {
"id": {
"type": "string",
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
},
"title": {
"type": "string"
},
"source": {
"type": "string",
"enum": [
"household",
"library"
]
},
"cuisine": {
"type": [
"string",
"null"
]
},
"main_protein": {
"type": [
"string",
"null"
]
},
"total_minutes": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"active_minutes": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"base_servings": {
"type": "number"
},
"kcal_per_serving": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"nutrition_confidence": {
"type": [
"number",
"null"
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
}
},
"household_rating": {
"description": "Bayesian mean 1–5 across members.",
"type": [
"number",
"null"
]
},
"ratings_count": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"last_served": {
"type": [
"string",
"null"
]
},
"times_served": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"archived": {
"type": "boolean"
}
},
"required": [
"id",
"title",
"source",
"total_minutes",
"base_servings",
"tags"
],
"additionalProperties": false
},
"archived": {
"type": "boolean"
},
"planned_on": {
"description": "Upcoming dates where this recipe is still planned (not changed automatically).",
"type": "array",
"items": {
"type": "string"
}
},
"notices": {
"type": "array",
"items": {
"type": "object",
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
}
},
"required": [
"code",
"message"
],
"additionalProperties": false
}
},
"replayed": {
"type": "boolean"
}
},
"required": [
"recipe",
"archived",
"notices",
"replayed"
],
"additionalProperties": false
}
}generate_week_plan · Generate Week Plan
Write · scope dinner.write · roles owner, adult · readOnly false · destructive false · openWorld false
Creates or regenerates the dinner plan for a week using the household's members, schedules, recipes, ratings, pantry and settings. Every dinner respects everyone's allergies, exclusions and diets, each night's cooking-time budget, calorie targets and the weekly budget (Plus). Nights the user locked, or marked eating out or skipped, are kept. Returns the full plan with reasons and a constraint report. If no plan can satisfy the constraints, nothing is saved and the response explains which constraint blocks which night with suggested changes. Regenerating replaces unlocked nights (a confirmed plan becomes a draft again).
Input / output schema
{
"input": {
"type": "object",
"properties": {
"week": {
"default": "next",
"type": "string",
"pattern": "^(current|next|previous|\\d{4}-\\d{2}-\\d{2})$",
"description": "'current', 'next', 'previous', or any date (YYYY-MM-DD) inside the wanted plan week."
},
"keep_days": {
"description": "Additional nights to keep unchanged for this run.",
"type": "array",
"items": {
"type": "string",
"pattern": "^(mon|tue|wed|thu|fri|sat|sun|\\d{4}-\\d{2}-\\d{2})$",
"description": "Weekday within the resolved plan week, or an exact date (YYYY-MM-DD)."
}
},
"preferences": {
"description": "One-off nudges for this run only.",
"type": "object",
"properties": {
"include_recipes": {
"description": "Recipe names/ids that should appear if they fit.",
"maxItems": 7,
"type": "array",
"items": {
"type": "string",
"maxLength": 100
}
},
"avoid_recipes": {
"maxItems": 20,
"type": "array",
"items": {
"type": "string",
"maxLength": 100
}
},
"more_of": {
"description": "Proteins (chicken, tofu, fish, beans_legumes), cuisines (mexican), tags (kid_friendly, one_pot) or diets (vegetarian, vegan, gluten_free) to favour. Terms no recipe matches are reported in notices, and so is a wanted term no planned dinner ended up matching.",
"maxItems": 5,
"type": "array",
"items": {
"type": "string",
"maxLength": 100
}
},
"less_of": {
"maxItems": 5,
"type": "array",
"items": {
"type": "string",
"maxLength": 100
}
},
"new_recipes": {
"description": "How many never-tried recipes to include.",
"type": "integer",
"minimum": 0,
"maximum": 7
}
},
"additionalProperties": false
},
"expected_revision": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"idempotency_key": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,64}$",
"description": "Optional. Reuse the same value if you retry this exact call after a timeout or error."
}
},
"additionalProperties": false
},
"output": {
"type": "object",
"properties": {
"plan": {
"type": "object",
"properties": {
"plan_id": {
"type": "string",
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
},
"week_start": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
"week_end": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
"status": {
"type": "string",
"enum": [
"draft",
"confirmed",
"completed"
]
},
"revision": {
"type": "integer",
"minimum": 1,
"maximum": 9007199254740991
},
"days": {
"maxItems": 7,
"type": "array",
"items": {
"type": "object",
"properties": {
"date": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
"dow": {
"type": "string",
"enum": [
"mon",
"tue",
"wed",
"thu",
"fri",
"sat",
"sun"
]
},
"kind": {
"type": "string",
"enum": [
"recipe",
"leftovers",
"eating_out",
"skip",
"unplanned"
]
},
"locked": {
"type": "boolean"
},
"recipe": {
"type": "object",
"properties": {
"id": {
"type": "string",
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
},
"title": {
"type": "string"
},
"source": {
"type": "string",
"enum": [
"household",
"library"
]
},
"cuisine": {
"type": [
"string",
"null"
]
},
"main_protein": {
"type": [
"string",
"null"
]
},
"total_minutes": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"active_minutes": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"base_servings": {
"type": "number"
},
"kcal_per_serving": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"nutrition_confidence": {
"type": [
"number",
"null"
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
}
},
"household_rating": {
"description": "Bayesian mean 1–5 across members.",
"type": [
"number",
"null"
]
},
"ratings_count": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"last_served": {
"type": [
"string",
"null"
]
},
"times_served": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"archived": {
"type": "boolean"
}
},
"required": [
"id",
"title",
"source",
"total_minutes",
"base_servings",
"tags"
],
"additionalProperties": false
},
"leftovers_of_date": {
"type": [
"string",
"null"
]
},
"attending": {
"type": "array",
"items": {
"type": "object",
"properties": {
"member_id": {
"type": "string",
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
},
"display_name": {
"type": "string"
},
"portion": {
"type": "number"
},
"kcal": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"kcal_target": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
}
},
"required": [
"member_id",
"display_name",
"portion"
],
"additionalProperties": false
}
},
"servings_to_cook": {
"type": [
"number",
"null"
]
},
"time_minutes": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"time_budget_minutes": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"schedule_reason": {
"type": [
"string",
"null"
]
},
"omit_for": {
"type": "array",
"items": {
"type": "object",
"properties": {
"ingredient": {
"type": "string"
},
"members": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": [
"ingredient",
"members"
],
"additionalProperties": false
}
},
"why": {
"maxItems": 3,
"type": "array",
"items": {
"type": "string"
}
},
"needs_swap": {
"type": "boolean"
},
"swap_reasons": {
"description": "When needs_swap: who and which strict rule this dinner breaks, e.g. \"Not safe for Mia (fish allergy)\". Tell the user and offer swap_meal.",
"type": "array",
"items": {
"type": "string"
}
},
"estimated_cost_cents": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
}
},
"required": [
"date",
"dow",
"kind",
"locked",
"attending",
"time_budget_minutes",
"why"
],
"additionalProperties": false
}
},
"constraint_report": {
"type": "object",
"properties": {
"all_hard_constraints_satisfied": {
"type": "boolean"
},
"items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"constraint": {
"type": "string"
},
"applies_to": {
"type": "array",
"items": {
"type": "string"
}
},
"satisfied_days": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"total_days": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"detail": {
"type": [
"string",
"null"
]
},
"status": {
"type": "string",
"enum": [
"applied",
"not_applied_plan_limit",
"not_applicable"
]
}
},
"required": [
"constraint",
"applies_to",
"satisfied_days",
"total_days"
],
"additionalProperties": false
}
}
},
"required": [
"all_hard_constraints_satisfied",
"items"
],
"additionalProperties": false
},
"estimated_total_cost_cents": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"weekly_budget_cents": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"confirmed_at": {
"type": [
"string",
"null"
]
},
"shopping_list_changed_since_handoff": {
"type": "boolean"
},
"markdown": {
"description": "Present only when format='markdown'.",
"type": [
"string",
"null"
]
}
},
"required": [
"plan_id",
"week_start",
"week_end",
"status",
"revision",
"days",
"constraint_report"
],
"additionalProperties": false
},
"changed_days": {
"type": "array",
"items": {
"type": "string"
}
},
"regenerations_used": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"regenerations_limit": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"solver": {
"type": "object",
"properties": {
"duration_ms": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"candidates_considered": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"truncated": {
"type": "boolean"
}
},
"required": [
"duration_ms",
"candidates_considered",
"truncated"
],
"additionalProperties": false
},
"notices": {
"type": "array",
"items": {
"type": "object",
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
}
},
"required": [
"code",
"message"
],
"additionalProperties": false
}
},
"replayed": {
"type": "boolean"
}
},
"required": [
"plan",
"notices",
"replayed"
],
"additionalProperties": false
}
}swap_meal · Swap Meal
Write · scope dinner.write · roles owner, adult · readOnly false · destructive false · openWorld false
Replaces the dinner on one night with a specific recipe the user chose (e.g. from preview_meal_options), or with the top-ranked fitting alternative if no recipe is given. The new dinner is checked against all hard constraints for the people eating that night; a recipe that breaks one is refused with the reason. Updates portions and the shopping list. Optionally locks the night so future regenerations keep it. To mark a night eating out, skipped or leftovers, use set_plan_day.
Input / output schema
{
"input": {
"type": "object",
"properties": {
"week": {
"description": "Omit with a weekday to mean its next occurrence from the household's today (tonight if it's today). 'current' or 'next' pick a plan week explicitly.",
"type": "string",
"pattern": "^(current|next|previous|\\d{4}-\\d{2}-\\d{2})$"
},
"day": {
"type": "string",
"pattern": "^(mon|tue|wed|thu|fri|sat|sun|\\d{4}-\\d{2}-\\d{2})$",
"description": "Weekday within the resolved plan week, or an exact date (YYYY-MM-DD)."
},
"recipe_id": {
"type": "string",
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
},
"recipe": {
"type": "string",
"maxLength": 100
},
"query": {
"description": "If no recipe given: pick the best fit matching this text (a recipe name, ingredient, protein or cuisine). 'quick', 'fast' or 'easy' means a total time of 30 minutes or less.",
"type": "string",
"maxLength": 60
},
"lock": {
"default": true,
"type": "boolean"
},
"expected_revision": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"idempotency_key": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,64}$",
"description": "Optional. Reuse the same value if you retry this exact call after a timeout or error."
}
},
"required": [
"day"
],
"additionalProperties": false
},
"output": {
"type": "object",
"properties": {
"day": {
"type": "object",
"properties": {
"date": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
"dow": {
"type": "string",
"enum": [
"mon",
"tue",
"wed",
"thu",
"fri",
"sat",
"sun"
]
},
"kind": {
"type": "string",
"enum": [
"recipe",
"leftovers",
"eating_out",
"skip",
"unplanned"
]
},
"locked": {
"type": "boolean"
},
"recipe": {
"type": "object",
"properties": {
"id": {
"type": "string",
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
},
"title": {
"type": "string"
},
"source": {
"type": "string",
"enum": [
"household",
"library"
]
},
"cuisine": {
"type": [
"string",
"null"
]
},
"main_protein": {
"type": [
"string",
"null"
]
},
"total_minutes": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"active_minutes": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"base_servings": {
"type": "number"
},
"kcal_per_serving": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"nutrition_confidence": {
"type": [
"number",
"null"
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
}
},
"household_rating": {
"description": "Bayesian mean 1–5 across members.",
"type": [
"number",
"null"
]
},
"ratings_count": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"last_served": {
"type": [
"string",
"null"
]
},
"times_served": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"archived": {
"type": "boolean"
}
},
"required": [
"id",
"title",
"source",
"total_minutes",
"base_servings",
"tags"
],
"additionalProperties": false
},
"leftovers_of_date": {
"type": [
"string",
"null"
]
},
"attending": {
"type": "array",
"items": {
"type": "object",
"properties": {
"member_id": {
"type": "string",
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
},
"display_name": {
"type": "string"
},
"portion": {
"type": "number"
},
"kcal": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"kcal_target": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
}
},
"required": [
"member_id",
"display_name",
"portion"
],
"additionalProperties": false
}
},
"servings_to_cook": {
"type": [
"number",
"null"
]
},
"time_minutes": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"time_budget_minutes": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"schedule_reason": {
"type": [
"string",
"null"
]
},
"omit_for": {
"type": "array",
"items": {
"type": "object",
"properties": {
"ingredient": {
"type": "string"
},
"members": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": [
"ingredient",
"members"
],
"additionalProperties": false
}
},
"why": {
"maxItems": 3,
"type": "array",
"items": {
"type": "string"
}
},
"needs_swap": {
"type": "boolean"
},
"swap_reasons": {
"description": "When needs_swap: who and which strict rule this dinner breaks, e.g. \"Not safe for Mia (fish allergy)\". Tell the user and offer swap_meal.",
"type": "array",
"items": {
"type": "string"
}
},
"estimated_cost_cents": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
}
},
"required": [
"date",
"dow",
"kind",
"locked",
"attending",
"time_budget_minutes",
"why"
],
"additionalProperties": false
},
"previous": {
"anyOf": [
{
"type": "object",
"properties": {
"title": {
"type": "string"
},
"kind": {
"type": "string"
}
},
"required": [
"title",
"kind"
],
"additionalProperties": false
},
{
"type": "null"
}
]
},
"plan_revision": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"plan_status": {
"type": "string"
},
"shopping_list_delta": {
"type": "object",
"properties": {
"added": {
"type": "array",
"items": {
"type": "string"
}
},
"removed": {
"type": "array",
"items": {
"type": "string"
}
},
"changed": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": [
"added",
"removed",
"changed"
],
"additionalProperties": false
},
"shopping_list_changed_since_handoff": {
"type": "boolean"
},
"unchanged": {
"description": "True when the night already had that dinner: nothing was swapped and no swap was used.",
"type": "boolean"
},
"swaps_used": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"swaps_limit": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"notices": {
"type": "array",
"items": {
"type": "object",
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
}
},
"required": [
"code",
"message"
],
"additionalProperties": false
}
},
"replayed": {
"type": "boolean"
}
},
"required": [
"day",
"previous",
"plan_revision",
"notices",
"replayed"
],
"additionalProperties": false
}
}set_plan_day · Set Plan Day
Write · scope dinner.write · roles owner, adult · readOnly false · destructive false · openWorld false
Changes the status of one night in a week plan without picking a new recipe: mark eating out, skip, or leftovers from an earlier night; clear a night back to unplanned; lock or unlock it; or move a night's dinner to another date in the same week (swapping the two). Updates portions and the shopping list. Leftovers nights require Plus. To choose a different recipe, use swap_meal.
Input / output schema
{
"input": {
"type": "object",
"properties": {
"week": {
"description": "Omit with a weekday to mean its next occurrence from the household's today (tonight if it's today). 'current' or 'next' pick a plan week explicitly.",
"type": "string",
"pattern": "^(current|next|previous|\\d{4}-\\d{2}-\\d{2})$"
},
"day": {
"type": "string",
"pattern": "^(mon|tue|wed|thu|fri|sat|sun|\\d{4}-\\d{2}-\\d{2})$",
"description": "Weekday within the resolved plan week, or an exact date (YYYY-MM-DD)."
},
"operation": {
"type": "string",
"enum": [
"eating_out",
"skip",
"leftovers",
"unplanned",
"lock",
"unlock",
"move"
]
},
"leftovers_from": {
"description": "Required for operation=leftovers.",
"type": "string",
"pattern": "^(mon|tue|wed|thu|fri|sat|sun|\\d{4}-\\d{2}-\\d{2})$"
},
"move_to": {
"description": "Required for operation=move.",
"type": "string",
"pattern": "^(mon|tue|wed|thu|fri|sat|sun|\\d{4}-\\d{2}-\\d{2})$"
},
"expected_revision": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"idempotency_key": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,64}$",
"description": "Optional. Reuse the same value if you retry this exact call after a timeout or error."
}
},
"required": [
"day",
"operation"
],
"additionalProperties": false
},
"output": {
"type": "object",
"properties": {
"days": {
"type": "array",
"items": {
"type": "object",
"properties": {
"date": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
"dow": {
"type": "string",
"enum": [
"mon",
"tue",
"wed",
"thu",
"fri",
"sat",
"sun"
]
},
"kind": {
"type": "string",
"enum": [
"recipe",
"leftovers",
"eating_out",
"skip",
"unplanned"
]
},
"locked": {
"type": "boolean"
},
"recipe": {
"type": "object",
"properties": {
"id": {
"type": "string",
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
},
"title": {
"type": "string"
},
"source": {
"type": "string",
"enum": [
"household",
"library"
]
},
"cuisine": {
"type": [
"string",
"null"
]
},
"main_protein": {
"type": [
"string",
"null"
]
},
"total_minutes": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"active_minutes": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"base_servings": {
"type": "number"
},
"kcal_per_serving": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"nutrition_confidence": {
"type": [
"number",
"null"
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
}
},
"household_rating": {
"description": "Bayesian mean 1–5 across members.",
"type": [
"number",
"null"
]
},
"ratings_count": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"last_served": {
"type": [
"string",
"null"
]
},
"times_served": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"archived": {
"type": "boolean"
}
},
"required": [
"id",
"title",
"source",
"total_minutes",
"base_servings",
"tags"
],
"additionalProperties": false
},
"leftovers_of_date": {
"type": [
"string",
"null"
]
},
"attending": {
"type": "array",
"items": {
"type": "object",
"properties": {
"member_id": {
"type": "string",
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
},
"display_name": {
"type": "string"
},
"portion": {
"type": "number"
},
"kcal": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"kcal_target": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
}
},
"required": [
"member_id",
"display_name",
"portion"
],
"additionalProperties": false
}
},
"servings_to_cook": {
"type": [
"number",
"null"
]
},
"time_minutes": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"time_budget_minutes": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"schedule_reason": {
"type": [
"string",
"null"
]
},
"omit_for": {
"type": "array",
"items": {
"type": "object",
"properties": {
"ingredient": {
"type": "string"
},
"members": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": [
"ingredient",
"members"
],
"additionalProperties": false
}
},
"why": {
"maxItems": 3,
"type": "array",
"items": {
"type": "string"
}
},
"needs_swap": {
"type": "boolean"
},
"swap_reasons": {
"description": "When needs_swap: who and which strict rule this dinner breaks, e.g. \"Not safe for Mia (fish allergy)\". Tell the user and offer swap_meal.",
"type": "array",
"items": {
"type": "string"
}
},
"estimated_cost_cents": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
}
},
"required": [
"date",
"dow",
"kind",
"locked",
"attending",
"time_budget_minutes",
"why"
],
"additionalProperties": false
}
},
"plan_revision": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"shopping_list_delta": {
"type": "object",
"properties": {
"added": {
"type": "array",
"items": {
"type": "string"
}
},
"removed": {
"type": "array",
"items": {
"type": "string"
}
},
"changed": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": [
"added",
"removed",
"changed"
],
"additionalProperties": false
},
"shopping_list_changed_since_handoff": {
"type": "boolean"
},
"notices": {
"type": "array",
"items": {
"type": "object",
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
}
},
"required": [
"code",
"message"
],
"additionalProperties": false
}
},
"replayed": {
"type": "boolean"
}
},
"required": [
"days",
"plan_revision",
"notices",
"replayed"
],
"additionalProperties": false
}
}confirm_week_plan · Confirm Week Plan
Write · scope dinner.write · roles owner, adult · readOnly false · destructive false · openWorld false
Marks a week's dinner plan as confirmed (final), freezing the current version of its shopping list. Use it when the user approves the plan. Later edits are still possible and are tracked as new revisions. Does not order groceries or send anything.
Input / output schema
{
"input": {
"type": "object",
"properties": {
"week": {
"default": "next",
"type": "string",
"pattern": "^(current|next|previous|\\d{4}-\\d{2}-\\d{2})$",
"description": "'current', 'next', 'previous', or any date (YYYY-MM-DD) inside the wanted plan week."
},
"expected_revision": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"idempotency_key": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,64}$",
"description": "Optional. Reuse the same value if you retry this exact call after a timeout or error."
}
},
"additionalProperties": false
},
"output": {
"type": "object",
"properties": {
"plan": {
"type": "object",
"properties": {
"plan_id": {
"type": "string",
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
},
"week_start": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
"week_end": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
"status": {
"type": "string",
"enum": [
"draft",
"confirmed",
"completed"
]
},
"revision": {
"type": "integer",
"minimum": 1,
"maximum": 9007199254740991
},
"days": {
"maxItems": 7,
"type": "array",
"items": {
"type": "object",
"properties": {
"date": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
"dow": {
"type": "string",
"enum": [
"mon",
"tue",
"wed",
"thu",
"fri",
"sat",
"sun"
]
},
"kind": {
"type": "string",
"enum": [
"recipe",
"leftovers",
"eating_out",
"skip",
"unplanned"
]
},
"locked": {
"type": "boolean"
},
"recipe": {
"type": "object",
"properties": {
"id": {
"type": "string",
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
},
"title": {
"type": "string"
},
"source": {
"type": "string",
"enum": [
"household",
"library"
]
},
"cuisine": {
"type": [
"string",
"null"
]
},
"main_protein": {
"type": [
"string",
"null"
]
},
"total_minutes": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"active_minutes": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"base_servings": {
"type": "number"
},
"kcal_per_serving": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"nutrition_confidence": {
"type": [
"number",
"null"
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
}
},
"household_rating": {
"description": "Bayesian mean 1–5 across members.",
"type": [
"number",
"null"
]
},
"ratings_count": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"last_served": {
"type": [
"string",
"null"
]
},
"times_served": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"archived": {
"type": "boolean"
}
},
"required": [
"id",
"title",
"source",
"total_minutes",
"base_servings",
"tags"
],
"additionalProperties": false
},
"leftovers_of_date": {
"type": [
"string",
"null"
]
},
"attending": {
"type": "array",
"items": {
"type": "object",
"properties": {
"member_id": {
"type": "string",
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
},
"display_name": {
"type": "string"
},
"portion": {
"type": "number"
},
"kcal": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"kcal_target": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
}
},
"required": [
"member_id",
"display_name",
"portion"
],
"additionalProperties": false
}
},
"servings_to_cook": {
"type": [
"number",
"null"
]
},
"time_minutes": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"time_budget_minutes": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"schedule_reason": {
"type": [
"string",
"null"
]
},
"omit_for": {
"type": "array",
"items": {
"type": "object",
"properties": {
"ingredient": {
"type": "string"
},
"members": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": [
"ingredient",
"members"
],
"additionalProperties": false
}
},
"why": {
"maxItems": 3,
"type": "array",
"items": {
"type": "string"
}
},
"needs_swap": {
"type": "boolean"
},
"swap_reasons": {
"description": "When needs_swap: who and which strict rule this dinner breaks, e.g. \"Not safe for Mia (fish allergy)\". Tell the user and offer swap_meal.",
"type": "array",
"items": {
"type": "string"
}
},
"estimated_cost_cents": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
}
},
"required": [
"date",
"dow",
"kind",
"locked",
"attending",
"time_budget_minutes",
"why"
],
"additionalProperties": false
}
},
"constraint_report": {
"type": "object",
"properties": {
"all_hard_constraints_satisfied": {
"type": "boolean"
},
"items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"constraint": {
"type": "string"
},
"applies_to": {
"type": "array",
"items": {
"type": "string"
}
},
"satisfied_days": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"total_days": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"detail": {
"type": [
"string",
"null"
]
},
"status": {
"type": "string",
"enum": [
"applied",
"not_applied_plan_limit",
"not_applicable"
]
}
},
"required": [
"constraint",
"applies_to",
"satisfied_days",
"total_days"
],
"additionalProperties": false
}
}
},
"required": [
"all_hard_constraints_satisfied",
"items"
],
"additionalProperties": false
},
"estimated_total_cost_cents": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"weekly_budget_cents": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"confirmed_at": {
"type": [
"string",
"null"
]
},
"shopping_list_changed_since_handoff": {
"type": "boolean"
},
"markdown": {
"description": "Present only when format='markdown'.",
"type": [
"string",
"null"
]
}
},
"required": [
"plan_id",
"week_start",
"week_end",
"status",
"revision",
"days",
"constraint_report"
],
"additionalProperties": false
},
"shopping_list_summary": {
"type": "array",
"items": {
"type": "object",
"properties": {
"store": {
"type": "string"
},
"item_count": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"estimated_cost_cents": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
}
},
"required": [
"store",
"item_count",
"estimated_cost_cents"
],
"additionalProperties": false
}
},
"next_steps": {
"type": "array",
"items": {
"type": "string"
}
},
"notices": {
"type": "array",
"items": {
"type": "object",
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
}
},
"required": [
"code",
"message"
],
"additionalProperties": false
}
},
"replayed": {
"type": "boolean"
}
},
"required": [
"plan",
"shopping_list_summary",
"notices",
"replayed"
],
"additionalProperties": false
}
}record_meal_feedback · Record Meal Feedback
Write · scope dinner.write · roles owner, adult · readOnly false · destructive false · openWorld false
Records how each person liked a dinner, from what the user says: "loved" = 5 + loved_it, "liked" = 4, "it was ok" = 3, "didn't like" = 2, "hated" = 1, and dont_make_again only if they say never again. Other tags: more_please, too_spicy, too_bland, took_too_long, too_much_work, not_enough_food, too_much_food. Use when: 'last_week' or 'this_week' with the dish as they said it ("the souvlaki"); Ulivo finds that night, or asks which one if two dinners match. note keeps a short reason; never turn a note into an allergy or rule. An adult records their own or a login-less person's feedback ("Maya said 2 stars"). Ratings shape future plans.
Input / output schema
{
"input": {
"type": "object",
"properties": {
"entries": {
"minItems": 1,
"maxItems": 20,
"type": "array",
"items": {
"type": "object",
"properties": {
"date": {
"description": "Dinner date; identifies the planned recipe.",
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
"when": {
"description": "When they had it: 'today' (or 'tonight'), 'yesterday', 'last_week', 'this_week' or a date; with recipe, 'last_week' and 'this_week' find that week's night for it.",
"anyOf": [
{
"type": "string",
"enum": [
"today",
"tonight",
"yesterday",
"last_week",
"this_week"
]
},
{
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
}
]
},
"recipe_id": {
"type": "string",
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
},
"recipe": {
"type": "string",
"maxLength": 100
},
"member": {
"description": "Whose opinion this is (name or id). Default: the signed-in person.",
"type": "string",
"maxLength": 100
},
"rating": {
"type": "integer",
"minimum": 1,
"maximum": 5
},
"tags": {
"maxItems": 5,
"type": "array",
"items": {
"type": "string",
"enum": [
"loved_it",
"more_please",
"too_spicy",
"too_bland",
"took_too_long",
"too_much_work",
"not_enough_food",
"too_much_food",
"dont_make_again"
]
}
},
"note": {
"description": "Their reason in a few words (e.g. 'too fishy'). Stays with the household; never parsed into allergies or rules.",
"type": "string",
"minLength": 1,
"maxLength": 140
}
},
"required": [
"rating"
],
"additionalProperties": false
}
},
"idempotency_key": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,64}$",
"description": "Optional. Reuse the same value if you retry this exact call after a timeout or error."
}
},
"required": [
"entries"
],
"additionalProperties": false
},
"output": {
"type": "object",
"properties": {
"saved": {
"type": "array",
"items": {
"type": "object",
"properties": {
"member": {
"type": "string"
},
"recipe": {
"type": "string"
},
"date": {
"type": [
"string",
"null"
]
},
"rating": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"tags": {
"type": "array",
"items": {
"type": "string"
}
},
"note": {
"type": [
"string",
"null"
]
},
"updated_existing": {
"type": "boolean"
}
},
"required": [
"member",
"recipe",
"date",
"rating",
"tags",
"updated_existing"
],
"additionalProperties": false
}
},
"recipe_new_household_rating": {
"type": "array",
"items": {
"type": "object",
"properties": {
"recipe": {
"type": "string"
},
"rating": {
"type": "number"
}
},
"required": [
"recipe",
"rating"
],
"additionalProperties": false
}
},
"notices": {
"type": "array",
"items": {
"type": "object",
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
}
},
"required": [
"code",
"message"
],
"additionalProperties": false
}
},
"replayed": {
"type": "boolean"
}
},
"required": [
"saved",
"notices",
"replayed"
],
"additionalProperties": false
}
}update_pantry · Update Pantry
Write · scope dinner.write · roles owner, adult · readOnly false · destructive false · openWorld false
Updates what the household has at home: add or remove always-stocked staples (e.g. olive oil, rice) that never go on the shopping list, and record items on hand with quantity and optional use-by date (e.g. half a roast chicken, 1 lb spinach expiring Friday) so plans use them up and the shopping list subtracts them. Full pantry tracking requires Plus; staples work on all plans.
Input / output schema
{
"input": {
"type": "object",
"properties": {
"staples_add": {
"maxItems": 30,
"type": "array",
"items": {
"type": "string",
"maxLength": 60
}
},
"staples_remove": {
"maxItems": 30,
"type": "array",
"items": {
"type": "string",
"maxLength": 60
}
},
"items_set": {
"maxItems": 30,
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string",
"maxLength": 60
},
"quantity": {
"type": "number",
"exclusiveMinimum": 0
},
"unit": {
"type": "string",
"maxLength": 20
},
"use_by": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
"cooked": {
"default": false,
"type": "boolean"
}
},
"required": [
"name"
],
"additionalProperties": false
}
},
"items_remove": {
"maxItems": 30,
"type": "array",
"items": {
"type": "string",
"maxLength": 100
}
},
"idempotency_key": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,64}$",
"description": "Optional. Reuse the same value if you retry this exact call after a timeout or error."
}
},
"additionalProperties": false
},
"output": {
"type": "object",
"properties": {
"staples": {
"type": "array",
"items": {
"type": "string"
}
},
"items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"quantity_display": {
"type": [
"string",
"null"
]
},
"use_by": {
"type": [
"string",
"null"
]
}
},
"required": [
"name",
"quantity_display",
"use_by"
],
"additionalProperties": false
}
},
"unresolved": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"candidates": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": [
"name",
"candidates"
],
"additionalProperties": false
}
},
"shopping_list_updated_weeks": {
"type": "array",
"items": {
"type": "string"
}
},
"notices": {
"type": "array",
"items": {
"type": "object",
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
}
},
"required": [
"code",
"message"
],
"additionalProperties": false
}
},
"replayed": {
"type": "boolean"
}
},
"required": [
"staples",
"items",
"unresolved",
"notices",
"replayed"
],
"additionalProperties": false
}
}update_shopping_list · Update Shopping List
Write · scope dinner.write · roles owner, adult · readOnly false · destructive false · openWorld false
Edits a week's shopping list: check off or uncheck items, mark items you already have, remove items, move an item to another store, or add extra items not in any recipe (e.g. milk, paper towels). Manual additions stay when the plan changes. Does not send the list anywhere.
Input / output schema
{
"input": {
"type": "object",
"properties": {
"week": {
"default": "next",
"type": "string",
"pattern": "^(current|next|previous|\\d{4}-\\d{2}-\\d{2})$",
"description": "'current', 'next', 'previous', or any date (YYYY-MM-DD) inside the wanted plan week."
},
"operations": {
"minItems": 1,
"maxItems": 50,
"type": "array",
"items": {
"type": "object",
"properties": {
"op": {
"type": "string",
"enum": [
"check",
"uncheck",
"have_it",
"remove",
"restore",
"move_store",
"add"
]
},
"item_id": {
"type": "string",
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
},
"item": {
"description": "Item name if no id.",
"type": "string",
"maxLength": 100
},
"store": {
"description": "Target store for move_store/add.",
"type": "string",
"maxLength": 100
},
"name": {
"type": "string",
"maxLength": 80
},
"quantity": {
"type": "number",
"exclusiveMinimum": 0
},
"unit": {
"type": "string",
"maxLength": 20
},
"note": {
"type": "string",
"maxLength": 100
}
},
"required": [
"op"
],
"additionalProperties": false
}
},
"idempotency_key": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,64}$",
"description": "Optional. Reuse the same value if you retry this exact call after a timeout or error."
}
},
"required": [
"operations"
],
"additionalProperties": false
},
"output": {
"type": "object",
"properties": {
"results": {
"type": "array",
"items": {
"type": "object",
"properties": {
"op": {
"type": "string"
},
"item": {
"type": "string"
},
"status": {
"type": "string",
"enum": [
"ok",
"not_found",
"ambiguous",
"store_not_found"
],
"description": "store_not_found: the item exists (or was given) but the store does not; candidates lists the stores."
},
"store": {
"type": "string"
},
"candidates": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": [
"op",
"item",
"status"
],
"additionalProperties": false
}
},
"list_version": {
"type": "string"
},
"shopping_list_changed_since_handoff": {
"type": "boolean"
},
"notices": {
"type": "array",
"items": {
"type": "object",
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
}
},
"required": [
"code",
"message"
],
"additionalProperties": false
}
},
"replayed": {
"type": "boolean"
}
},
"required": [
"results",
"list_version",
"notices",
"replayed"
],
"additionalProperties": false
}
}create_instacart_link · Create Instacart Link
Write · scope dinner.write · roles owner, adult · readOnly false · destructive false · openWorld true
Sends the shopping list for a store (ingredient names and quantities only, no personal information) to Instacart and returns a link that opens the list on Instacart. The link is informational: Ulivo does not place orders, does not add items to the user's Instacart account, and does not charge anything. Ulivo may earn a commission from Instacart through this link; it does not affect which dinners are suggested. The same list returns the same link.
Input / output schema
{
"input": {
"type": "object",
"properties": {
"week": {
"default": "next",
"type": "string",
"pattern": "^(current|next|previous|\\d{4}-\\d{2}-\\d{2})$",
"description": "'current', 'next', 'previous', or any date (YYYY-MM-DD) inside the wanted plan week."
},
"store": {
"description": "Store whose items to send; default: the store with instacart_enabled, else the default store.",
"type": "string",
"maxLength": 100
},
"include_checked": {
"default": false,
"type": "boolean"
},
"title": {
"type": "string",
"maxLength": 60
},
"idempotency_key": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,64}$",
"description": "Optional. Reuse the same value if you retry this exact call after a timeout or error."
}
},
"additionalProperties": false
},
"output": {
"type": "object",
"properties": {
"url": {
"type": "string"
},
"store": {
"type": "string"
},
"item_count": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"items_sent": {
"type": "array",
"items": {
"type": "string"
}
},
"items_not_sent": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"reason": {
"type": "string",
"enum": [
"checked",
"have_it",
"other_store",
"unit_unsupported_sent_as_each"
]
}
},
"required": [
"name",
"reason"
],
"additionalProperties": false
}
},
"expires_at": {
"type": "string"
},
"cached": {
"type": "boolean"
},
"what_happens_next": {
"type": "string"
},
"commercial_disclosure": {
"type": "string"
},
"notices": {
"type": "array",
"items": {
"type": "object",
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
}
},
"required": [
"code",
"message"
],
"additionalProperties": false
}
},
"replayed": {
"type": "boolean"
}
},
"required": [
"url",
"item_count",
"cached",
"commercial_disclosure",
"notices",
"replayed"
],
"additionalProperties": false
}
}create_invite_code · Create Invite Code
Write · scope dinner.invite · roles owner · readOnly false · destructive false · openWorld false
Creates a one-time household invite code and link for another adult (18+) to join this household with their own Ulivo account, so they can see plans and give feedback from their own assistant. The code is returned to you to share yourself; nothing is sent. Valid for 7 days. Only the household owner can create invites. Requires Plus. To email the invite instead, use send_invite_email.
Input / output schema
{
"input": {
"type": "object",
"properties": {
"for_member": {
"description": "Existing adult profile name this person will be linked to (e.g. 'Alex'). Optional.",
"type": "string",
"maxLength": 100
},
"idempotency_key": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,64}$",
"description": "Optional. Reuse the same value if you retry this exact call after a timeout or error."
}
},
"additionalProperties": false
},
"output": {
"type": "object",
"properties": {
"code": {
"type": "string",
"pattern": "^[A-HJ-NP-Z2-9]{4}-[A-HJ-NP-Z2-9]{4}$"
},
"join_url": {
"type": "string"
},
"expires_at": {
"type": "string"
},
"for_member": {
"type": [
"string",
"null"
]
},
"instructions": {
"type": "string"
},
"notices": {
"type": "array",
"items": {
"type": "object",
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
}
},
"required": [
"code",
"message"
],
"additionalProperties": false
}
},
"replayed": {
"type": "boolean"
}
},
"required": [
"code",
"join_url",
"expires_at",
"notices",
"replayed"
],
"additionalProperties": false
}
}send_invite_email · Send Invite Email
Sensitive write · scope dinner.invite · roles owner · readOnly false · destructive true · openWorld true
Sends an email from Ulivo inviting another adult (18+) to join this household with their own account. The email contains the inviter's first name, the household name and a join link valid for 7 days, and nothing else about the household. Use only when the user explicitly asks to email an invite and has confirmed the recipient's email address. Only the household owner can send invites. Requires Plus. To share an invite without sending email, use create_invite_code.
Input / output schema
{
"input": {
"type": "object",
"properties": {
"email": {
"type": "string",
"maxLength": 254,
"format": "email",
"pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
},
"for_member": {
"description": "Existing adult profile to link (optional).",
"type": "string",
"maxLength": 100
},
"confirm_recipient": {
"type": "string",
"format": "email",
"pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$",
"description": "Repeat the exact recipient address the user confirmed; must equal email."
},
"idempotency_key": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,64}$",
"description": "Optional. Reuse the same value if you retry this exact call after a timeout or error."
}
},
"required": [
"email",
"confirm_recipient"
],
"additionalProperties": false
},
"output": {
"type": "object",
"properties": {
"invite_id": {
"type": "string"
},
"email": {
"type": "string"
},
"status": {
"type": "string",
"enum": [
"queued",
"sent",
"failed"
]
},
"expires_at": {
"type": "string"
},
"deduplicated": {
"type": "boolean"
},
"email_preview": {
"type": "object",
"properties": {
"from": {
"type": "string"
},
"subject": {
"type": "string"
},
"body_text": {
"type": "string"
}
},
"required": [
"from",
"subject",
"body_text"
],
"additionalProperties": false
},
"notices": {
"type": "array",
"items": {
"type": "object",
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
}
},
"required": [
"code",
"message"
],
"additionalProperties": false
}
},
"replayed": {
"type": "boolean"
}
},
"required": [
"invite_id",
"email",
"status",
"expires_at",
"notices",
"replayed"
],
"additionalProperties": false
}
}