API reference

Recipes

Read, write and delete recipes, with their ingredients parsed into something answerable.

Paths below are relative to https://recipejam.com/api/v1

GET /recipes

List recipes

Every recipe in the accounts your token can reach, most recently changed first.

Parameters

Field Type Notes
search string · query Matches ingredient lines, names and descriptions. Knows ingredient synonyms, so "aubergine" finds a recipe that says eggplant.
tag string · query Only recipes carrying this exact tag.
perPage integer · query 1 to 100. Defaults to 25. Anything larger is silently reduced to 100.
page integer · query Which page, from 1.
since string · query An ISO 8601 timestamp. Returns only what has changed since then, deleted records included, so a synced device can catch up without refetching everything. Url-encode it — a raw `+` in a query string arrives as a space.
deleted string · query `only` lists the wastebasket — what was deleted and can still be restored, each with a `deletedAt`. `include` lists both. Left out, you get the ordinary listing.

Response

200 with a page of Recipe objects in the pagination envelope.

  • A listing never carries steps or images — ask for one recipe to get those.
  • Search runs one term at a time. To require two ingredients, filter the second yourself.
GET /recipes/{recipe}

Get a recipe

One recipe in full, with its prep, method, cover and photographs.

Parameters

Field Type Notes
recipe string · path The id from a listing.

Response

200 with a single Recipe object under a `data` key.

POST /recipes

Create a recipe

Add a recipe to the account. It is private until you publish it.

Request body

Field Type Notes
name required string max 255 What the recipe is called.
description string, or null max 2000 A sentence or two.
isPublic boolean Defaults to false.
tags array of string each max 50 Short labels.
ingredients array of object Each entry needs a `name`, which is the line as written: "2 tbsp olive oil". Everything else on the line is worked out for you — do not send `parsed`, it is overwritten.
ingredients[].name required string max 255 The whole line, amount included.
equipment array of object Each entry needs a `name`.
notes array Free-form notes.
metadata object `servings`, `prepTime`, `cookTime`, each as written.
prepSteps array of object Work done before cooking starts. Each entry needs a `content`. Omit it if the recipe does not separate prep from method.
steps array of object The method. Each entry needs a `content`. Order is the order you send them.
steps[].content required string max 5000 One instruction. Same shape for `prepSteps[].content`.

Example request body

{
    "name": "Kimchi pancakes",
    "description": "Crisp at the edges.",
    "ingredients": [
        {
            "name": "200g kimchi"
        },
        {
            "name": "150g plain flour"
        },
        {
            "name": "1 egg"
        }
    ],
    "prepSteps": [
        {
            "content": "Chop the kimchi roughly."
        }
    ],
    "steps": [
        {
            "content": "Mix everything to a loose batter."
        },
        {
            "content": "Fry until crisp."
        }
    ],
    "tags": [
        "korean",
        "quick"
    ],
    "metadata": {
        "servings": "2",
        "cookTime": "15 minutes"
    }
}

Response

201 with a single Recipe object under a `data` key.

  • `prepSteps` and `steps` are separate sections and are written independently. Sending one never disturbs the other.
PATCH /recipes/{recipe} PUT

Update a recipe

Change one. Anything you leave out is left alone; a list you send replaces that list entirely.

Parameters

Field Type Notes
recipe string · path The recipe to change.

Request body

Field Type Notes
name string max 255 A new name.
description string, or null max 2000 A new description.
isPublic boolean Publish or unpublish.
tags array of string Replaces the whole tag list.
ingredients array of object Replaces every ingredient line. Send the complete list, not the one line you are changing.
prepSteps array of object Replaces the whole prep section. Sending `[]` removes it; leaving it out keeps it.
steps array of object Replaces the whole method. Sending `[]` removes it. The prep section is untouched either way.

Example request body

{
    "name": "Kimchi pancakes, properly",
    "tags": [
        "korean"
    ]
}

Response

200 with a single Recipe object under a `data` key.

  • PUT is accepted and does exactly the same thing. Despite the verb it is still a partial update — it does not blank the fields you leave out.
DELETE /recipes/{recipe}

Delete a recipe

Moves it to the bin. Recoverable for 30 days, then removed for good along with its photographs.

Parameters

Field Type Notes
recipe string · path The recipe to delete.

Response

204 with an empty body.

  • A recipe reached through a collection somebody shared with you can be read and edited, never deleted. That comes back 403.
  • It disappears from every collection and every book that held it, and from every listing — unless you ask for changes `since` a timestamp, which includes it so a synced device knows to drop it.
  • Its steps and photographs go with it and come back with it. The files stay on disk until the retention window closes.
POST /recipes/{recipe}/restore

Restore a recipe

Takes one back out of the bin, with the steps and photographs it went down with.

Parameters

Field Type Notes
recipe string · path The deleted recipe. Ordinary listings will not show it; find it with `since`, which reports it with a `deletedAt`.

Response

200 with a single Recipe object under a `data` key.

  • Only what was deleted with the recipe comes back. A photograph you removed on purpose a week earlier stays removed.
  • Past the retention window there is nothing left to restore and this answers 404, the same as an id that never existed.
  • It rejoins the collections and books it was in — membership survives the deletion, so a restore puts it back where it was rather than leaving you to file it again.
GET /recipes/{recipe}/reader

Read a recipe

The recipe already turned into pages: ingredients chunked, amounts linked into the method, timers parsed. Render these and hold no recipe logic of your own.

Parameters

Field Type Notes
recipe string · path The recipe to read.

Response

200 with a single reader object under a `data` key.

  • This is the same computation the website's own reader uses, so what you render matches what a cook sees on recipejam.com. Reimplementing the chunking or the ingredient linking on a client will drift from it, and the drift shows up as a wrong amount in somebody's kitchen.
  • A recipe with no ingredients, equipment or steps returns no pages at all — an empty `pages` array rather than a cover with nothing behind it.
  • Photograph URLs need your token, like every other image in this API.
  • Cache against `subject.updatedAt`. If it has not moved, neither have the pages.

Try these

The endpoints on this page, sent from your browser with your own token. Nothing is proxied through us.

Kept in this browser only, so it survives a reload. It is never sent to RecipeJam except as the header on the request you ask for.

The same request, as curl

The recipe object

Field Type Notes
id string Opaque identifier. The same one the app uses in its own URLs; never a database number.
name string What the recipe is called.
description string, or null A sentence or two about the dish.
isPublic boolean Whether the recipe answers on its public share link.
tags array of string Short labels. Empty rather than null when there are none.
ingredients array of ingredient One entry per line, in the order they are written. See below.
equipment array of object Each entry has a `name`.
notes array of object Free-form notes kept against the recipe.
metadata object Timings and yield as written: `servings`, `prepTime`, `cookTime`. Any of them may be absent.
source object Where it came from: `author`, `name`, `url`. Absent keys mean nobody recorded one.
links array Links the owner attached to the recipe.
prepSteps array of step Only on a single recipe, never in a listing.
steps array of step The method. Only on a single recipe.
coverImage image, or absent Only when the recipe has one.
images array of image Only on a single recipe.
createdAt string ISO 8601, with an offset.
updatedAt string ISO 8601, with an offset.

An ingredient line

Every ingredient carries both what was written and what the parser made of it. The parsed half is why this is worth calling rather than scraping — it is what makes "does this use pork" answerable without reading English.

Field Type Notes
name string The line exactly as the cook wrote it: "2 tbsp olive oil".
parsed object The parser's reading of that line. Never authoritative over `name`.
parsed.ingredient string, or null The ingredient in its display form: "Olive oil".
parsed.ingredient_key string, or null Its canonical identity: "oil". Two lines sharing a key mean the same thing.
parsed.ingredient_id integer, or null The catalogue row, where one is known.
parsed.written string, or null The words the line used for the ingredient, before generalising: "sesame oil".
parsed.quantity number, string, or null A whole number comes back as a number; anything else keeps its text ("2–3").
parsed.quantity_min number, or null The near end of a range. Equal to `quantity_max` when it is not a range.
parsed.quantity_max number, or null The far end of a range.
parsed.unit string, or null Normalised: "tbsp", "g", "ml".
parsed.size string, or null "large", "medium" — the word that sizes the thing rather than counting it.
parsed.additional string, or null What came after the ingredient: "finely chopped".
parsed.to_taste boolean True for "salt, to taste" and its kin.
parsed.confidence string `high`, `medium` or `low`. Treat anything below high as a guess.
parsed.raw string The line the parser was given, unchanged.
parsed.locale string The language it was read in.

A step

Field Type Notes
id string Opaque identifier.
sort integer Position within its own section, from 1.
content string The instruction.

An image

Field Type Notes
id string Opaque identifier.
width integer Of the stored original, in pixels.
height integer Of the stored original, in pixels.
links object One URL per size: `thumbnail`, `strip`, `small`, `medium`, `large`, plus `download`. Each is an application URL, authorised per request — not a storage URL, and never public because you hold it.