Skip to content
merran
GitHubInstall

Merran documentation API & integrations

Apply a suggestion

POST
/api/proposals/{proposalId}/apply
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.

proposalId
required
string

Example

0199e8b0-5a10-7a01-8b00-000000000029
Media typeapplication/json
object
sections

For changes to a recipe: the sections to apply. The rest are skipped.

Array<string>
Allowed values: ingredients steps tags description details marks foods notes

Example

{
"sections": [
"steps",
"marks"
]
}

Applied: the suggestion and the recipe.

Media typeapplication/json
object
proposal
required
object
id
required
string
kind
required
string
Allowed values: tidy note edit recipe meals list tastes import swap
status
required
string
Allowed values: pending applied dismissed
recipe
required
object
id
required
string
slug
required
string
name
required
string
summary
required

What it changes, in a sentence.

string
sections
required

The sections it changes, each applied or skipped on its own.

Array<string>
Allowed values: ingredients steps tags description details marks foods notes
note
required

The cooking note it came from, for one made from a note.

string | null
payload
required

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.

object | null
chat
required

The assistant’s chat it came from, for one from the assistant.

string | null
before
required

A recipe’s sections, only the ones a suggestion changes. Ingredients and steps are editor lines.

object
ingredients
Array<string>
steps
Array<string>
tags
Array<string>
description
string | null
details
object
servings
required
number | null
prepMinutes
required
number | null
cookMinutes
required
number | null
totalMinutes
required
number | null
marks
Array<object>
object
line
required
string
mark
required
string | null
Allowed values: needed swappable optional
foods
Array<object>
object
line
required
string
food
required

The food Merran knows that the line is, as a food key; null when no one has said.

string | null
notes
string | null
after
required

A recipe’s sections, only the ones a suggestion changes. Ingredients and steps are editor lines.

object
ingredients
Array<string>
steps
Array<string>
tags
Array<string>
description
string | null
details
object
servings
required
number | null
prepMinutes
required
number | null
cookMinutes
required
number | null
totalMinutes
required
number | null
marks
Array<object>
object
line
required
string
mark
required
string | null
Allowed values: needed swappable optional
foods
Array<object>
object
line
required
string
food
required

The food Merran knows that the line is, as a food key; null when no one has said.

string | null
notes
string | null
createdAt
required
string format: date-time
resolvedAt
required
string | null format: date-time
recipe
required
Any of:

The recipe it changed or made, if it did.

object
id
required
string
slug
required
string
name
required
string
description
required
string | null
servings
required
number | null
totalMinutes
required

As given, or prep and cook added up.

number | null
rating
required
number | null
tags
required
Array<string>
diets
required

Diet labels worked out from the ingredients, with the household’s corrections.

Array<string>
Allowed values: vegetarian vegan gluten-free dairy-free egg-free nut-free
photo
required

Where its photo is, in each size, or null. The links change with the photo, so they can be kept.

object
full
required

For the recipe page.

string
card
required

Cropped, for recipe cards.

string
lastMadeAt
required
string | null format: date-time
createdAt
required
string format: date-time
updatedAt
required
string format: date-time
origin
required
string
Allowed values: link video text photo manual assistant mealie paprika merran
photoByAi
required

Its photo was made by AI, in the household’s style. Making another replaces it; a real one always does.

boolean
sourceUrl
required
string | null
yieldText
required
string | null
prepMinutes
required
number | null
cookMinutes
required
number | null
notes
required
string | null
dietOverrides
required

Where the household corrected the labels the ingredients suggest.

object
vegetarian
boolean
vegan
boolean
gluten-free
boolean
dairy-free
boolean
egg-free
boolean
nut-free
boolean
needs
required

Foods the household said it can’t do without: a dislike that’s usually left out of recipes rules this one out instead.

Array<string>
nutrition
required

Per serving, when it’s known.

object
source
required

From the recipe’s site, worked out from USDA’s data, or estimated by AI.

string
Allowed values: site calculated estimate
calories

Kcal.

number
protein

Grams.

number
carbs

Grams.

number
fat

Grams.

number
fiber

Grams.

number
sugar

Grams.

number
sodium

Milligrams.

number
missing

Ingredient lines that couldn’t be counted.

Array<string>
servings

The servings it’s for; it rescales when they change.

number
ingredients
required
Array<object>
object
id
required
string
section
required
string | null
text
required

The line as written.

string
quantity
required
number | null
quantityMax
required
number | null
unit
required
string | null
food
required
string | null
note
required
string | null
mark
required

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.

string | null
Allowed values: needed swappable optional
steps
required
Array<object>
object
id
required
string
section
required
string | null
text
required
string

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.

Media typeapplication/json
object
error
required
object
code
required
string
message
required
string
fields
object
key
additional properties
string

Example

{
"error": {
"code": "not_found",
"message": "There's nothing here.",
"fields": {
"name": "Give it a name."
}
}
}

Not signed in.

Media typeapplication/json
object
error
required
object
code
required
string
message
required
string
fields
object
key
additional properties
string

Example

{
"error": {
"code": "not_found",
"message": "There's nothing here.",
"fields": {
"name": "Give it a name."
}
}
}

Not allowed.

Media typeapplication/json
object
error
required
object
code
required
string
message
required
string
fields
object
key
additional properties
string

Example

{
"error": {
"code": "not_found",
"message": "There's nothing here.",
"fields": {
"name": "Give it a name."
}
}
}

No such suggestion, or its recipe is gone.

Media typeapplication/json
object
error
required
object
code
required
string
message
required
string
fields
object
key
additional properties
string

Example

{
"error": {
"code": "not_found",
"message": "There's nothing here.",
"fields": {
"name": "Give it a name."
}
}
}

Applied or dismissed already, or the recipe changed.

Media typeapplication/json
object
error
required
object
code
required
string
message
required
string
fields
object
key
additional properties
string

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.