{"openapi":"3.1.0","info":{"title":"Groceryunit API","version":"0.1.0","description":"A fully local, multi-item grocery shopping-list price comparison calculator: best-value picks and a whole-list running total and savings, a single-item unit-price ranker, a cart running total, budget fit checking, price-per-serving, a bulk-vs-small worth-it decision factoring shelf life, unit normalization, general savings tips and a glossary.\n\nEvery operation is read-only or compute-only. The same tools are available over MCP (streamable HTTP) at https://groceryunit.connectorbay.com/mcp.","contact":{"name":"Unify Dynamics LLC","email":"hr@unifydynamics.com","url":"https://connectorbay.com/groceryunit/docs"},"termsOfService":"https://connectorbay.com/groceryunit/terms"},"servers":[{"url":"https://groceryunit.connectorbay.com"}],"externalDocs":{"url":"https://connectorbay.com/groceryunit/docs"},"security":[{},{"bearer":[]}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","description":"Optional. A Pro API key raises rate limits; no credentials are required."}},"schemas":{"Error":{"type":"object","properties":{"ok":{"const":false},"error":{"type":"object"}}}}},"paths":{"/v1/tools/compare_shopping_list":{"post":{"operationId":"compare_shopping_list","summary":"The main tool: for a whole shopping list (each item with 1+ size/price options), picks the best-value","description":"The main tool: for a whole shopping list (each item with 1+ size/price options), picks the best-value\n    option per item and totals the WHOLE LIST at those picks, compared against the total if each item had been\n    bought at its worst-value option — giving a whole-list total and total savings, not just one item's per-unit\n    price. Use for \"here's my grocery list with options for each item, what should I buy and what's my total\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"items":{"description":"1-50 items, each {\"name\": \"...\", \"options\": [{\"label\": \"...\", \"price\": 3.49, \"quantity\": 500, \"unit\": \"g\"}, ...]}. One option per item is fine (no comparison needed for it).","examples":[[{"name":"flour","options":[{"label":"1kg bag","price":2.49,"quantity":1,"unit":"kg"},{"label":"500g bag","price":1.49,"quantity":500,"unit":"g"}]},{"name":"milk","options":[{"label":"1L","price":1.2,"quantity":1,"unit":"l"}]}]],"items":{"additionalProperties":true,"type":"object"},"title":"Items","type":"array"}},"required":["items"],"title":"compare_shopping_listArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/price_per_unit":{"post":{"operationId":"price_per_unit","summary":"Ranks 2-10 price/size options for a SINGLE grocery item by unit price, with the saving of the best versus","description":"Ranks 2-10 price/size options for a SINGLE grocery item by unit price, with the saving of the best versus\n    the worst. A helper for one line of a list — for the whole list at once with a running total, use\n    compare_shopping_list. Use for \"500g for 1.49 or 1kg for 2.49, which is the better deal\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"options":{"description":"2-10 options for ONE item, each {\"label\": \"...\", \"price\": 3.49, \"quantity\": 500, \"unit\": \"g\"}.","examples":[[{"label":"Small","price":1.49,"quantity":500,"unit":"g"},{"label":"Large","price":2.49,"quantity":1,"unit":"kg"}]],"items":{"additionalProperties":true,"type":"object"},"title":"Options","type":"array"}},"required":["options"],"title":"price_per_unitArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/running_total":{"post":{"operationId":"running_total","summary":"Sums a cart of already-chosen items (price × quantity per line) into a subtotal, tax and total. Use for","description":"Sums a cart of already-chosen items (price × quantity per line) into a subtotal, tax and total. Use for\n    \"add up my cart: 2 milk at 1.20, 1 bread at 2.50, plus 7% tax\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"cart":{"description":"1-100 lines, each {\"name\": \"...\", \"price\": 3.49, \"quantity\": 2}. quantity defaults to 1.","items":{"additionalProperties":true,"type":"object"},"title":"Cart","type":"array"},"tax_pct":{"anyOf":[{"maximum":50,"minimum":0,"type":"number"},{"type":"null"}],"default":null,"description":"Sales tax percentage to apply to the subtotal, if any.","title":"Tax Pct"}},"required":["cart"],"title":"running_totalArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/budget_fit":{"post":{"operationId":"budget_fit","summary":"Checks a shopping list's best-value total against a budget, and if it's over, ranks which items would free","description":"Checks a shopping list's best-value total against a budget, and if it's over, ranks which items would free\n    up the most money if dropped. Use for \"does my grocery list fit a $50 budget, and if not what should I cut\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"items":{"description":"Same shape as compare_shopping_list's items.","items":{"additionalProperties":true,"type":"object"},"title":"Items","type":"array"},"budget":{"description":"Your budget for the list.","examples":[50],"exclusiveMinimum":0,"title":"Budget","type":"number"}},"required":["items","budget"],"title":"budget_fitArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/price_per_serving":{"post":{"operationId":"price_per_serving","summary":"Cost per serving (or per meal) of a package, for comparing very differently-sized items on a like-for-like","description":"Cost per serving (or per meal) of a package, for comparing very differently-sized items on a like-for-like\n    basis when planning meals or a budget. Use for \"what's the cost per serving of a $6.99 box that makes 8\n    servings\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"price":{"description":"Price of the package.","examples":[6.99],"exclusiveMinimum":0,"title":"Price","type":"number"},"quantity":{"description":"Package quantity (for reference).","examples":[1],"exclusiveMinimum":0,"title":"Quantity","type":"number"},"unit":{"description":"Unit of the package quantity.","examples":["kg"],"title":"Unit","type":"string"},"servings":{"description":"Number of servings/meals the package yields.","examples":[8],"exclusiveMinimum":0,"title":"Servings","type":"number"}},"required":["price","quantity","unit","servings"],"title":"price_per_servingArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/bulk_worth_it":{"post":{"operationId":"bulk_worth_it","summary":"Whether the bulk size is actually worth it: compares per-unit price AND estimates whether you'd use up the","description":"Whether the bulk size is actually worth it: compares per-unit price AND estimates whether you'd use up the\n    bulk size before it spoils, scaling from how fast you go through the small size. Use for \"is the family-size\n    pack worth it if it might go stale before we finish it\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"small_price":{"description":"Price of the small size.","exclusiveMinimum":0,"title":"Small Price","type":"number"},"small_qty":{"description":"Quantity of the small size.","exclusiveMinimum":0,"title":"Small Qty","type":"number"},"bulk_price":{"description":"Price of the bulk size.","exclusiveMinimum":0,"title":"Bulk Price","type":"number"},"bulk_qty":{"description":"Quantity of the bulk size.","exclusiveMinimum":0,"title":"Bulk Qty","type":"number"},"unit":{"description":"Unit shared by both sizes.","examples":["g","oz","count"],"title":"Unit","type":"string"},"days_until_used_up_if_small":{"description":"Roughly how many days it takes your household to use up the SMALL size.","exclusiveMinimum":0,"title":"Days Until Used Up If Small","type":"number"},"shelf_life_days":{"description":"How many days the product stays good for once opened/bought.","exclusiveMinimum":0,"title":"Shelf Life Days","type":"number"}},"required":["small_price","small_qty","bulk_price","bulk_qty","unit","days_until_used_up_if_small","shelf_life_days"],"title":"bulk_worth_itArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/normalize_unit":{"post":{"operationId":"normalize_unit","summary":"Converts a grocery package quantity to a standard base unit (kg for mass, litre for volume, item for count)","description":"Converts a grocery package quantity to a standard base unit (kg for mass, litre for volume, item for count)\n    for manual side-by-side comparison. Use for \"how many kg is 500g\", \"what's a dozen in item count\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"quantity":{"description":"Quantity.","examples":[500],"exclusiveMinimum":0,"title":"Quantity","type":"number"},"unit":{"description":"Grocery unit: g, kg, oz, lb, ml, l, fl oz, cup, count, dozen…","examples":["g"],"title":"Unit","type":"string"}},"required":["quantity","unit"],"title":"normalize_unitArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/savings_tips":{"post":{"operationId":"savings_tips","summary":"General, non-brand-specific grocery savings tips — unit pricing, store brands, bulk-buying caveats,","description":"General, non-brand-specific grocery savings tips — unit pricing, store brands, bulk-buying caveats,\n    seasonal produce, budget checking, loss leaders. Use for \"how can I save money grocery shopping\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{},"title":"savings_tipsArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/glossary":{"post":{"operationId":"glossary","summary":"Definitions of grocery shopping terms — unit price, PPU, running total, bulk unit, loss leader, shelf life,","description":"Definitions of grocery shopping terms — unit price, PPU, running total, bulk unit, loss leader, shelf life,\n    generic/store brand. Use for \"what does PPU mean\", \"what's a loss leader\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"term":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"A specific term to look up; omit to list all.","title":"Term"}},"title":"glossaryArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}}}}