Pantry API

18 ops: list_locations, save_location, add_pantry_items, list_pantry, get_pantry_item, update_pantry_items, move_pantry_items, consume_pantry_items, discard_pantry_items, list_expiring, freeze_suggestions, get_raw_ingredients, set_par_levels, get_shopping_list, add_shopping_items, check_off_shopping

List pantry locations · POST /api/v1/list_locations · scope pantry:read or GET …?input=

The household's storage locations as a tree (e.g. Kitchen fridge › Door, Freezer, Garage freezer, Pantry cupboard, Spice rack, Counter), each with its id, path, type (fridge, freezer, pantry, counter, other: the type decides shelf life), how many items are in it and inside it, and how many expire within 7 days. Call it before adding items to reuse the household's own names.

curl -X POST https://getgutlog.com/api/v1/list_locations \  -H "Authorization: Bearer gutlog_…"

Save pantry locations · POST /api/v1/save_location · scope pantry:write

Create, rename, retype, nest or archive storage locations. A new one needs a name; its type defaults from the name ("Garage freezer" → freezer), then its parent. Archiving needs the location empty. You rarely need this: add_pantry_items creates the locations it is given by path. Batch: pass up to 200 entries; each succeeds or fails on its own (results[i].ok / results[i].error).

curl -X POST https://getgutlog.com/api/v1/save_location \  -H "Authorization: Bearer gutlog_…" \  -H "Content-Type: application/json" \  -d '{"locations":[{}]}'

Add pantry items · POST /api/v1/add_pantry_items · scope pantry:write

Record food the household has: from a receipt, barcode scans, or a fridge, freezer or pantry photo you read yourself (you list what you see; nothing is analyzed here). Per item: a name (resolved to a canonical ingredient), optional ingredient_id or barcode, quantity and unit, where it is (location path like "Kitchen fridge › Door", location_type, or nothing: the place FoodKeeper keeps it), state (fresh, opened, cooked, frozen, thawed), dates, the printed date and its kind, price and store. Returns each item with its estimated expiry (from the printed date or USDA FoodKeeper for its storage and state, with the rule used), how its shelf life was matched, any storage warning, the locations created, and the names that did not resolve (fix with update_pantry_items). Batch: pass up to 200 entries; each succeeds or fails on its own (results[i].ok / results[i].error).

curl -X POST https://getgutlog.com/api/v1/add_pantry_items \  -H "Authorization: Bearer gutlog_…" \  -H "Content-Type: application/json" \  -d '{"items":[{"name":"scrambled eggs"}]}'

List pantry items · POST /api/v1/list_pantry · scope pantry:read or GET …?input=

What is on hand, soonest expiry first. Filters: location_id (and everything inside it), location_type, ingredient_id, state, expiring_before (a day), q (name contains), status (active by default; consumed, discarded or all for history). Each item has its ingredient, quantity and unit, location path, state, dates, printed date, expiry (date, latest, days_left, source, rule, safety), freezable, price and provenance. `unresolved` counts items with no canonical ingredient.

curl -X POST https://getgutlog.com/api/v1/list_pantry \  -H "Authorization: Bearer gutlog_…"

Get a pantry item · POST /api/v1/get_pantry_item · scope pantry:read or GET …?input=

One item with its FoodKeeper shelf-life entry (days per storage, opened, thawed, freezer, tips) and its full history (added, used, moved, frozen, thawed, recounted, discarded: who, when, from which surface). Use it to explain an expiry date.

curl -X POST https://getgutlog.com/api/v1/get_pantry_item \  -H "Authorization: Bearer gutlog_…" \  -H "Content-Type: application/json" \  -d '{"item_id":"6f1c2e0a-4b7d-4c2e-9a51-0d3b8e7f9a10"}'

Update pantry items · POST /api/v1/update_pantry_items · scope pantry:write

Change items: resolve what it is (ingredient_id, barcode, foodkeeper_id), recount (quantity: how much is there now), change state (opened, cooked; freezing and thawing is move_pantry_items), dates, the printed date, an expiry you set yourself (expires_on; null returns to the estimate), price, store, notes. The expiry is re-estimated when the state or dates change. For food eaten use consume_pantry_items; thrown out, discard_pantry_items. Batch: pass up to 200 entries; each succeeds or fails on its own (results[i].ok / results[i].error).

curl -X POST https://getgutlog.com/api/v1/update_pantry_items \  -H "Authorization: Bearer gutlog_…" \  -H "Content-Type: application/json" \  -d '{"items":[{"item_id":"6f1c2e0a-4b7d-4c2e-9a51-0d3b8e7f9a10"}]}'

Move pantry items · POST /api/v1/move_pantry_items · scope pantry:write

Move items to another location (location_id, a path, or a type). Into a freezer the item becomes frozen from today; out of one, thawed from today; either way the expiry is re-estimated (e.g. chicken: 9 months frozen, then 1–2 days in the fridge after thawing). Batch: pass up to 200 entries; each succeeds or fails on its own (results[i].ok / results[i].error).

curl -X POST https://getgutlog.com/api/v1/move_pantry_items \  -H "Authorization: Bearer gutlog_…" \  -H "Content-Type: application/json" \  -d '{"items":[{"item_id":"6f1c2e0a-4b7d-4c2e-9a51-0d3b8e7f9a10"}]}'

Use pantry items · POST /api/v1/consume_pantry_items · scope pantry:write

Record food used: by item_id, or by ingredient_id or name (the soonest-expiring matching items are used first). quantity is optional (all of one item when omitted) and converts between units of the same kind (200 g from a 1 lb pack). Pass meal_id when it went into a logged meal. Items used up leave the pantry and can come back on get_shopping_list. Returns what was used and what is left; `short` when there was not enough. Batch: pass up to 200 entries; each succeeds or fails on its own (results[i].ok / results[i].error).

curl -X POST https://getgutlog.com/api/v1/consume_pantry_items \  -H "Authorization: Bearer gutlog_…" \  -H "Content-Type: application/json" \  -d '{"items":[{}]}'

Throw out pantry items · POST /api/v1/discard_pantry_items · scope pantry:write

Record food thrown out, all or part, with a reason (expired, spoiled, freezer_burn, didnt_like, too_much, other) for waste tracking; pantry_summary totals it with its cost when the price is known. Batch: pass up to 200 entries; each succeeds or fails on its own (results[i].ok / results[i].error).

curl -X POST https://getgutlog.com/api/v1/discard_pantry_items \  -H "Authorization: Bearer gutlog_…" \  -H "Content-Type: application/json" \  -d '{"items":[{"item_id":"6f1c2e0a-4b7d-4c2e-9a51-0d3b8e7f9a10"}]}'

List expiring food · POST /api/v1/list_expiring · scope pantry:read or GET …?input=

Items expiring within `days` (default 7) and, by default, already past their date, soonest first, each with days_left and a suggested action: use, freeze (freezable, not frozen, 2 days or less left) or toss (past a use-by or the safe time for perishable food), with a one-line why. Past a best-by or a freezer quality date the action is use (check it), not toss. Use it to suggest what to cook first.

curl -X POST https://getgutlog.com/api/v1/list_expiring \  -H "Authorization: Bearer gutlog_…"

Suggest what to freeze · POST /api/v1/freeze_suggestions · scope pantry:read or GET …?input=

Items not frozen that FoodKeeper says freeze well and that expire within `days` (default 3), with how long each would keep if frozen today. Never items already past their date, nor thawed food that did not thaw in the fridge. Freeze them with move_pantry_items to a freezer.

curl -X POST https://getgutlog.com/api/v1/freeze_suggestions \  -H "Authorization: Bearer gutlog_…"

Get raw ingredients on hand · POST /api/v1/get_raw_ingredients · scope pantry:read or GET …?input=

The canonical ingredients on hand, deduplicated across items and locations: total amount (mass in g/kg, volume in ml/l, counts per unit), item ids, states, locations, soonest expiry and days left, soonest first; plus `unresolved` items with no ingredient. This is the list to plan meals or recipes from.

curl -X POST https://getgutlog.com/api/v1/get_raw_ingredients \  -H "Authorization: Bearer gutlog_…"

Set staple quantities · POST /api/v1/set_par_levels · scope pantry:write

Staples the household always wants on hand ("12 eggs", "1 gal milk", "2 cans tomatoes"), with an optional usual location and store. quantity 0 removes a staple. get_shopping_list adds staples below their level. Batch: pass up to 200 entries; each succeeds or fails on its own (results[i].ok / results[i].error).

curl -X POST https://getgutlog.com/api/v1/set_par_levels \  -H "Authorization: Bearer gutlog_…" \  -H "Content-Type: application/json" \  -d '{"levels":[{"name":"scrambled eggs","quantity":0}]}'

Get the shopping list · POST /api/v1/get_shopping_list · scope pantry:read or GET …?input=

What to buy: items added to the list, staples below their par level (with the amount missing), and items used up in the last `used_up_days` (default 14) that are not on hand. Each line has a key (check it off by key), source (manual, par, used_up) and why; `by_store` groups them by store when known.

curl -X POST https://getgutlog.com/api/v1/get_shopping_list \  -H "Authorization: Bearer gutlog_…"

Add to the shopping list · POST /api/v1/add_shopping_items · scope pantry:write

Put items on the shopping list (name, optional ingredient_id, quantity and unit, store, notes). Adding something already on the list adds to its quantity. Batch: pass up to 200 entries; each succeeds or fails on its own (results[i].ok / results[i].error).

curl -X POST https://getgutlog.com/api/v1/add_shopping_items \  -H "Authorization: Bearer gutlog_…" \  -H "Content-Type: application/json" \  -d '{"items":[{"name":"scrambled eggs"}]}'

Check off shopping items · POST /api/v1/check_off_shopping_items · scope pantry:write

Mark list lines bought (or removed). By id, or key/name for a suggested line. Bought items go into the pantry (add_to_pantry, default true) at the staple's usual location or where FoodKeeper keeps them, with today's purchase date and any printed date, price and store you give. Batch: pass up to 200 entries; each succeeds or fails on its own (results[i].ok / results[i].error).

curl -X POST https://getgutlog.com/api/v1/check_off_shopping_items \  -H "Authorization: Bearer gutlog_…" \  -H "Content-Type: application/json" \  -d '{"items":[{}]}'

Pantry summary · POST /api/v1/pantry_summary · scope pantry:read or GET …?input=

Counts on hand by location and state, how many are expired and expiring this week, unresolved items, and this month's use and waste: items thrown out, their cost when known, reasons and the foods most often thrown out.

curl -X POST https://getgutlog.com/api/v1/pantry_summary \  -H "Authorization: Bearer gutlog_…"

get_shelf_life

readno credential needed

Look up shelf life · POST /api/v1/get_shelf_life · scope pantry:read or GET …?input=

How long a food keeps in the pantry, fridge and freezer, sealed, opened and after thawing, from USDA FoodKeeper (public domain), by name, ingredient_id or foodkeeper_id. Days as {min, max} or a marker: package_date, indefinitely, when_ripe, not_recommended. Use the returned foodkeeper_id to pin an item's shelf life. Needs no account.

curl -X POST https://getgutlog.com/api/v1/get_shelf_life \  -H "Authorization: Bearer gutlog_…"