Merran documentation API & integrations
Apply a suggestion
const url = 'http://localhost:3000/api/proposals/0199e8b0-5a10-7a01-8b00-000000000029/apply';const options = { method: 'POST', headers: { cookie: 'merran.session_token=<merran.session_token>', 'Content-Type': 'application/json' }, body: '{"sections":["steps","marks"]}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url http://localhost:3000/api/proposals/0199e8b0-5a10-7a01-8b00-000000000029/apply \ --header 'Content-Type: application/json' \ --cookie merran.session_token=<merran.session_token> \ --data '{ "sections": [ "steps", "marks" ] }'Changes to a recipe apply the sections picked, as one change that keeps a version of how it was; the rest are skipped. A section changed since it was suggested is refused rather than overwritten, and the error says which. The assistant’s other suggestions add what they say: a recipe, meals, things for the list, tastes, or a recipe from the web. With an API key, it needs the recipes: write permission.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”Example
0199e8b0-5a10-7a01-8b00-000000000029Request Bodyrequired
Section titled “Request Bodyrequired”object
For changes to a recipe: the sections to apply. The rest are skipped.
Example
{ "sections": [ "steps", "marks" ]}Responses
Section titled “Responses”Applied: the suggestion and the recipe.
object
object
object
What it changes, in a sentence.
The sections it changes, each applied or skipped on its own.
The cooking note it came from, for one made from a note.
What an assistant’s suggestion adds, by kind: recipe (a recipe, as the editor writes one), meals (meals for the plan), items (lines for the list), tastes to remember (avoid, diets, weeknightMinutes), a recipe page to import (url, name, site, photo, minutes, why), or a stand-in for an ingredient (ingredientId, insteadOf, lines, note, steps), which applying saves to the recipe. Null for changes to a recipe’s sections.
The assistant’s chat it came from, for one from the assistant.
A recipe’s sections, only the ones a suggestion changes. Ingredients and steps are editor lines.
object
object
object
object
The food Merran knows that the line is, as a food key; null when no one has said.
A recipe’s sections, only the ones a suggestion changes. Ingredients and steps are editor lines.
object
object
object
object
The food Merran knows that the line is, as a food key; null when no one has said.
The recipe it changed or made, if it did.
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
{ "proposal": { "id": "0199e8b0-5a10-7a01-8b00-000000000029", "kind": "tidy", "status": "applied", "resolvedAt": "2026-10-15T18:30:00.000Z", "recipe": { "id": "0199e8b0-5a10-7a01-8b00-000000000006", "slug": "lemon-chicken", "name": "Lemon Chicken" }, "summary": "Split a long step and marked the chicken as needed.", "sections": [ "steps", "marks" ], "note": null, "payload": null, "chat": null, "before": { "steps": [ "Rub the chicken with lemon and garlic, then roast it at 200°C for 40 minutes until golden. Enjoy!" ], "marks": [ { "line": "2 lb chicken thighs", "mark": null }, { "line": "2 lemons, juiced", "mark": null } ] }, "after": { "steps": [ "Rub the chicken with lemon and garlic.", "Roast at 200°C for 40 minutes, until golden." ], "marks": [ { "line": "2 lb chicken thighs", "mark": "needed" }, { "line": "2 lemons, juiced", "mark": "needed" } ] }, "createdAt": "2026-10-01T17:30:00.000Z" }, "recipe": { "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." } ] }}Nothing picked.
object
object
object
Example
{ "error": { "code": "not_found", "message": "There's nothing here.", "fields": { "name": "Give it a name." } }}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 suggestion, or its recipe is gone.
object
object
object
Example
{ "error": { "code": "not_found", "message": "There's nothing here.", "fields": { "name": "Give it a name." } }}Applied or dismissed already, or the recipe changed.
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.