Auto-planning a vegan week at Jumbo — 5 dinners, one shopping list
This builds a vegan week meal plan by using Pepesto's /suggest endpoint filtered by the vegan tag, then prices each of 5 dinners at Jumbo.com using /products. The output is a per-recipe shopping list with estimated cost per meal.
Run this yourself
$ PEPESTO_API_KEY=your_key node jumbo-vegan-week-meal-plan.jsFull script: jumbo-vegan-week-meal-plan.js. You'll need an API key to run it — get one here.
Getting started
The API key arrives immediately.
const res = await fetch('https://s.pepesto.com/api/link', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email: 'mira@example.nl' }),
});
const { api_key } = await res.json();
// export PEPESTO_API_KEY=pepesto_live_...The first call — finding vegan recipes with /suggest
The /suggest endpoint searches the Pepesto recipe database by query. Put the dietary requirement directly in the query string — the API uses it to select appropriately tagged recipes from the database.
const suggestRes = await fetch('https://s.pepesto.com/api/suggest', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${process.env.PEPESTO_API_KEY}`,
},
body: JSON.stringify({
query: 'vegan dinner',
num_to_fetch: 5,
}),
});
const { recipes } = await suggestRes.json();
// recipes = [{ title, ingredients, steps, nutrition, kg_token }, ...]Each recipe comes back with a full ingredient list, steps, nutrition data, and a kg_token. The token is what gets passed to /products — it encodes the ingredient graph so the matcher can find the right Jumbo SKUs.
{
"title": "Ainsley Harriott Roasted Vegetable Couscous Bowl",
"ingredients": [
"200g couscous", "1 courgette (~250g)", "1 red pepper (~110g)",
"1 red onion (~150g)", "400g canned chickpeas", "olive oil",
"cumin", "smoked paprika", "salt", "black pepper", "lemon juice"
],
"nutrition": {
"calories": 1820,
"carbohydrates_grams": 280,
"protein_grams": 62,
"fat_grams": 38
},
"kg_token": "EjEKL0dyZWVrLXN0eWxlIGJha2VkIGZpc2ggd2l0aC..."
}Look up all five recipes at Jumbo in parallel:
async function fetchJumboProducts(kgToken) {
const res = await fetch('https://s.pepesto.com/api/products', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${process.env.PEPESTO_API_KEY}`,
},
body: JSON.stringify({
recipe_kg_tokens: [kgToken],
supermarket_domain: 'jumbo.com',
}),
});
const data = await res.json();
return data.items;
}
// All five lookups in parallel
const allItems = await Promise.all(recipes.map(r => fetchJumboProducts(r.kg_token)));
// Print each meal with its shopping list
recipes.forEach((recipe, i) => {
const items = allItems[i];
const costCents = items.reduce((sum, item) => {
if (!item.products?.length) return sum;
return sum + item.products[0].product.price.price;
}, 0);
console.log(`\nDay ${i + 1}: ${recipe.title}`);
console.log(`Estimated cost: €${(costCents / 100).toFixed(2)}\n`);
items.forEach(item => {
if (!item.products?.length) {
console.log(` • ${item.item_name} [no Jumbo match]`);
return;
}
const top = item.products[0].product;
const promo = top.price.promotion?.promo ? ' [aanbieding]' : '';
console.log(` • ${item.item_name} → ${top.product_name} €${(top.price.price / 100).toFixed(2)}${promo}`);
});
});What the data showed
The Jumbo catalog matching for vegan recipes was solid. Canned goods — AH Organic corn kernels, Akfa Tomato Puree 420g at €2.39, A Trade Mark Ketjap Manis Kentel No. 1 Sweet Soy Sauce at €2.99 — all matched cleanly. Al Fez Tahini 125g at €2.99 appeared in the Jumbo catalog for recipes that needed a tahini-based sauce.
Fresh produce matching was solid on staples (onions, courgette, peppers, garlic) but occasionally missed on more specific items like particular mushroom varieties. The Cooked Ham entry (Achterham Gegaard 175g at €2.08) is not relevant to vegan recipes — it came through because of an edge case in a recipe that had a ham-based sauce variation. Add a post-filter to check tags on matched products to catch these cases.
Estimated meal costs ranged from about €4.50 to €9.80 per recipe, depending on whether it relied on expensive fresh produce or cheap pantry staples. The weekly total for five dinners came in around €32.
Next steps
The natural extension is turning the shopping list into an actual Jumbo cart. Pass the session_token from each matched product into /api/session to get a checkout link. The session response would look like:
{
"session_id": "ses_9pMzVtLkRnQw3bXj"
}Open that link and the Jumbo basket is pre-filled. Pass the session tokens from the /products response directly — no additional state needed.
The result
A five-dinner vegan meal plan with a complete Jumbo shopping list, built in two API calls. The vegan tag filter is effective but not perfect — occasionally a recipe includes a borderline ingredient (honey, or bread that may contain eggs). Review recipe titles before finalising.
What else you could do?
Add a "no repeats" filter: track which recipes have appeared in the last four weeks and exclude them from suggestions so the plan rotates. Add a nutritional balance check — confirm the week has sufficient protein across all five meals using the nutrition field in the /suggest response. Compare Jumbo vs AH prices for the same week's recipes — some weeks one supermarket is significantly cheaper depending on promotions, and switching requires only changing the supermarket_domain.