Merran documentation API & integrations
Say what a recipe can't do without
const url = 'http://localhost:3000/api/recipes/lemon-chicken/needs';const options = { method: 'PUT', headers: { cookie: 'merran.session_token=<merran.session_token>', 'Content-Type': 'application/json' }, body: '{"foods":["mushrooms"]}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request PUT \ --url http://localhost:3000/api/recipes/lemon-chicken/needs \ --header 'Content-Type: application/json' \ --cookie merran.session_token=<merran.session_token> \ --data '{ "foods": [ "mushrooms" ] }'A food the household doesn’t like is usually left out of recipes, crossed off and not bought. One a recipe can’t do without rules that recipe out instead, as when tidy up marked it needed or, before tidy up, it’s in the recipe’s name. It isn’t an edit, so no version is kept. With an API key, it needs the recipes: write permission.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”The recipe’s id, or its slug.
Example
lemon-chickenThe recipe’s id, or its slug.
Request Bodyrequired
Section titled “Request Bodyrequired”For example, a stir fry that’s nothing without its mushrooms: someone who doesn’t like them can’t just leave them out.
object
Foods it can’t do without, replacing any said before. An empty list lets every dislike be left out again.
Foods tidy up marked as needed that it can do without after all: their lines are marked optional.
Example
{ "foods": [ "mushrooms" ]}Responses
Section titled “Responses”The recipe, with what it needs.
object
As given, or prep and cook added up.
Diet labels worked out from the ingredients, with the household’s corrections.
Where its photo is, in each size, or null. The links change with the photo, so they can be kept.
object
For the recipe page.
Cropped, for recipe cards.
Its photo was made by AI, in the household’s style. Making another replaces it; a real one always does.
Where the household corrected the labels the ingredients suggest.
object
Foods the household said it can’t do without: a dislike that’s usually left out of recipes rules this one out instead.
Per serving, when it’s known.
object
From the recipe’s site, worked out from USDA’s data, or estimated by AI.
Kcal.
Grams.
Grams.
Grams.
Grams.
Grams.
Milligrams.
Ingredient lines that couldn’t be counted.
The servings it’s for; it rescales when they change.
object
The line as written.
What it is to the dish, as tidy up marked it: needed, swappable or optional. A dislike is left out of lines that aren’t needed. None until marked.
object
Example
{ "id": "0199e8b0-5a10-7a01-8b00-000000000006", "slug": "lemon-chicken", "name": "Lemon Chicken", "description": "Crisp chicken thighs roasted with lemon, garlic and thyme.", "servings": 4, "totalMinutes": 50, "rating": 5, "tags": [ "chicken", "dinner" ], "diets": [ "gluten-free", "dairy-free", "egg-free", "nut-free" ], "photo": { "full": "/api/recipes/0199e8b0-5a10-7a01-8b00-000000000006/photo?size=full&v=4b1c2d3e", "card": "/api/recipes/0199e8b0-5a10-7a01-8b00-000000000006/photo?size=card&v=4b1c2d3e" }, "lastMadeAt": "2026-10-09T01:15:00.000Z", "createdAt": "2026-10-01T17:30:00.000Z", "updatedAt": "2026-10-15T18:30:00.000Z", "origin": "link", "photoByAi": false, "sourceUrl": "https://example.com/lemon-chicken", "yieldText": null, "prepMinutes": 10, "cookMinutes": 40, "notes": "Bone-in thighs work too: give them 10 minutes more.", "dietOverrides": {}, "needs": [], "nutrition": { "source": "calculated", "calories": 412, "protein": 31.5, "carbs": 6.2, "fat": 28.1, "fiber": 1.4, "sugar": 1.2, "sodium": 640, "missing": [], "servings": 4 }, "ingredients": [ { "id": "0199e8b0-5a10-7a01-8b00-000000000011", "section": null, "text": "2 lb chicken thighs", "quantity": 2, "quantityMax": null, "unit": "pound", "food": "chicken thighs", "note": null, "mark": "needed" }, { "id": "0199e8b0-5a10-7a01-8b00-000000000012", "section": null, "text": "1 tbsp olive oil", "quantity": 1, "quantityMax": null, "unit": "tablespoon", "food": "olive oil", "note": null, "mark": "optional" }, { "id": "0199e8b0-5a10-7a01-8b00-000000000013", "section": null, "text": "2 lemons, juiced", "quantity": 2, "quantityMax": null, "unit": null, "food": "lemons", "note": "juiced", "mark": "needed" }, { "id": "0199e8b0-5a10-7a01-8b00-000000000014", "section": null, "text": "4 cloves garlic, smashed", "quantity": 4, "quantityMax": null, "unit": "clove", "food": "garlic", "note": "smashed", "mark": "swappable" } ], "steps": [ { "id": "0199e8b0-5a10-7a01-8b00-000000000015", "section": null, "text": "Heat the oven to 425°F." }, { "id": "0199e8b0-5a10-7a01-8b00-000000000016", "section": null, "text": "Toss the chicken with the oil, lemon juice, garlic, salt and pepper." }, { "id": "0199e8b0-5a10-7a01-8b00-000000000017", "section": null, "text": "Roast skin side up for 40 minutes, until crisp." } ]}Not signed in.
object
object
object
Example
{ "error": { "code": "not_found", "message": "There's nothing here.", "fields": { "name": "Give it a name." } }}Not allowed.
object
object
object
Example
{ "error": { "code": "not_found", "message": "There's nothing here.", "fields": { "name": "Give it a name." } }}No such recipe.
object
object
object
Example
{ "error": { "code": "not_found", "message": "There's nothing here.", "fields": { "name": "Give it a name." } }}© 2026 Kyle Johnson. Documentation: CC BY 4.0. Merran: AGPL-3.0-or-later.