Skip to content
merran
GitHubInstall

Merran documentation API & integrations

Tidy up a recipe

POST
/api/recipes/{recipe}/tidy
curl --request POST \
--url http://localhost:3000/api/recipes/lemon-chicken/tidy \
--header 'Content-Type: application/json' \
--cookie merran.session_token=<merran.session_token> \
--data '{ "sections": [ "steps", "tags", "marks" ] }'

AI tidies the recipe: consistent ingredient lines, short clear steps, tags from the household’s own, a description and servings and times when they’re missing, and marks on what it can do without. Nothing changes yet: the suggestion waits in the Review queue, in place of any earlier one for the recipe, and comes back here. Null when there’s nothing to change. Uses the household’s model for tidying, and counts towards its AI spend. With an API key, it needs the recipes: write permission.

recipe
required

The recipe’s id, or its slug.

string

Example

lemon-chicken

The recipe’s id, or its slug.

Media typeapplication/json
object
sections

What to tidy; every section when left out.

Array<string>
<= 7 items
Allowed values: ingredients steps tags description details marks foods

Example

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

Its suggestion, or null.

Media typeapplication/json
object
proposal
required
Any of:
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

Example

{
"proposal": {
"id": "0199e8b0-5a10-7a01-8b00-000000000029",
"kind": "tidy",
"status": "pending",
"resolvedAt": null,
"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"
}
}

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 recipe.

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."
}
}
}

The model can’t do it.

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."
}
}
}

This month’s AI limit is reached, or the AI is busy.

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."
}
}
}

The AI provider failed.

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.