Portal
SandboxAPI v1Not signed inExternal user: —

Ingredients

Turn messy grocery text into stable ingredient IDs your app can store, match, and reason over.

What you can build

Grocery parsers, pantry add flows, shopping-list cleaners, and any UI that needs a consistent food identity instead of free-text matching.

1. Normalize raw ingredient text

Start with a line a user typed or scraped. Normalization parses quantity/unit and resolves a canonical ingredient when possible.

from foodapi import FoodAPI

client = FoodAPI(api_key="foodapi_sb_…")

normalized = client.ingredients.normalize("2 cloves garlic")
print(
    normalized.canonical_name,
    normalized.quantity,
    normalized.unit,
    normalized.ingredient_id,
    normalized.confidence,
    normalized.match_strategy,
)
{
  "raw_text": "2 cloves garlic",
  "canonical_name": "garlic",
  "quantity": 2.0,
  "unit": "clove",
  "confidence": 0.96,
  "match_strategy": "alias",
  "ingredient_id": "…"
}

ingredient_id is the stable handle for pantry, shopping, and reasoning. Treat free text as input only — persist the ID when you have one.

2. Inspect the canonical ingredient

When you need aliases, dietary flags, or ontology metadata, fetch the ingredient by id.

if normalized.ingredient_id is None:
    raise SystemExit("unresolved ingredient")

ingredient = client.ingredients.get(normalized.ingredient_id)
print(ingredient.canonical_name)
print(ingredient.dietary_flags)
print(ingredient.ontology)

3. Discover via search or filtered list

Use search for typeahead/autocomplete, or list when you want paginated catalog browsing with optional filters.

hits = client.ingredients.search("chickpea", limit=10)
for item in hits.results:
    print(item.id, item.canonical_name)

page = client.ingredients.list(
    search="oil",
    dietary_role="fat",
    limit=20,
)
for row in page.items:
    print(row.id, row.canonical_name, row.culinary_functions)

4. Use the ID in pantry or reasoning

Downstream FoodAPI calls expect canonical IDs — not the original string.

item = client.pantry.add(
    ingredient_id=normalized.ingredient_id,
    quantity=normalized.quantity,
    unit=normalized.unit,
)
print(item.id)  # pantry item id for FEASIBILITY reasoning

Production considerations

  • Handle unresolved rows: ingredient_id can be null when confidence/matching fails — keep the raw text for retry or manual pick.
  • Prefer ingredient_id everywhere you store inventory or preferences.
  • Ontology / dietary flags on get support client UX; dietary enforcement still belongs in Dietary intelligence / reasoning.

Next

Where does this ingredient go next?