What fits — and what replaces what.
A curated food graph connects ingredients through six relationship types: substitutes with a quality score, flavor pairings, functional similarity. Every recommendation comes with reasons — plus precise unit conversion via density and piece weight.
Six relationship types.
Relationships are data, not guesses: curated edges in the food graph, each with a score and reasons.
substitutesWellFull substitute — works in the recipe
substitutesPartiallyPartial substitute — with limitations
pairsWellWithPairs well in flavor
sameFamilyAsSame family (e.g. hard cheese)
functionallySimilarToFunctionally similar — same role in the dish
oftenUsedWithOften used together
Explainable by design.
Every suggestion carries a score and its reasons. Your app can show why pecorino replaces parmesan — building trust with end users and making results debuggable.
{ "ingredientId": "pecorino", "score": 0.93,
"quality": "well", "reasons": ["sameFamilyAs", "flavor"] }
Units that are correct.
Weight ↔ volume ↔ pieces, converted via the specific ingredient's density and piece weight — 1 tbsp of butter simply isn't 1 tbsp of flour. Every conversion declares its precision class:
Not meaningfully convertible? Then the API says so — instead of delivering fake precision.
Endpoints in this module.
Substitutes with quality score (partial matches optional)
Flavor pairings + frequent co-usage
Similar ingredients (family + functional)
Unit conversion via density & piece weight
What it looks like.
curl "https://api.foodoracle.app/v1/ingredients/parmesan/substitutes" \ -H "X-API-Key: fo_live_..."
{
"substitutes": [
{ "ingredientId": "pecorino", "score": 0.93, "quality": "well" }
]
}
Responses shown abbreviated — full schemas in the API reference.
Deterministic. No LLM.
Every answer comes from a curated ingredient library and fixed rules — reproducible, explainable, in milliseconds. Same request, same result. No hallucinations.