---
title: "The recipe object — Tiny Plates recipe API"
description: "The recipe object the API returns, field by field: ingredients, instructions, times, servings, nutrition, dietary flags, allergen evidence and media."
url: "https://www.tinyplates.dev/docs/recipe-object"
---

# The recipe object

Recipes are scraped from sites that publish them however they like, then normalized into one object. This is that object.

## One shape, everywhere

[GET /search](https://www.tinyplates.dev/docs/api/search-recipes), [GET /popular](https://www.tinyplates.dev/docs/api/popular-recipes), [GET /recipes/{id}](https://www.tinyplates.dev/docs/api/get-recipe) and [GET /recipes](https://www.tinyplates.dev/docs/api/list-recipes) all return it. Search adds a `score`, popular adds a `popularityScore`; nothing else differs.

## Reading a recipe

There are two ways in, and they hold the same content.

* **Structured.** `ingredients` is parsed into quantities, units, names and preparation; `instructions` is numbered steps. Use this to compute with — scaling, shopping lists, filtering. A line's `group` is the section it sits under, and `groups` lists every section in order, the ingredients' first and then the steps'.
* **Flat.** `text.ingredients` and `text.instructions` are plain lines, in order, ready to render. Use this to display.

An ingredient's `display` is the line to show. It is written back from the structured fields in the recipe's own language, so a Swedish recipe stays Swedish even though `name` and `ingredientId` are canonical English. That is what makes “tomat”, “Tomate” and “tomato” groupable without translating anyone's recipe.

Every duration is `{ seconds }` — never “1 hr 20 mins”. Format it yourself and you can format it in any language.

## Absent means unknown

An optional field that is missing means the source did not say, not that the answer is zero or false. This matters most for `dietary`: `vegan: false` is a known no, while no `vegan` key at all means nobody has established it. A flag the site declared wins; the rest are inferred from the required ingredients.

The same is true of `nutrition`, whose `source` is always `provided`: the site published the figures in its structured data, retrieved when the page was crawled. The API does not compute nutrition. Its `basis` says whether the numbers are per serving, per recipe or per 100 g, so do not compare two recipes' nutrition without checking it.

## Allergen evidence

`allergens` always carries the same 16 keys: the EU’s 14 regulated allergens, plus separate US definitions for wheat and tree nuts. The [GET /vocabularies](https://www.tinyplates.dev/docs/api/vocabularies) response says which jurisdictions each key belongs to.

Each value is `true` when the recipe contains the allergen, counting optional lines and garnishes, and `false` when it does not. It says nothing about manufacturer cross-contact. The `disclaimer` key sits beside them.

Treat this as informational, not medical advice. Keep the returned `disclaimer` wherever you show allergen results, and tell users to verify ingredients and product labels before serving someone with an allergy.

```
{
  "celery": false,
  "crustaceans": false,
  "eggs": false,
  "fish": false,
  "gluten-cereals": false,
  "lupin": false,
  "milk": true,
  "molluscs": false,
  "mustard": false,
  "nuts-eu": false,
  "peanuts": true,
  "sesame": false,
  "soy": false,
  "sulphites": false,
  "tree-nuts-us": false,
  "wheat": false,
  "disclaimer": "Informational only; not medical advice. Verify ingredients and product labels before serving someone with an allergy."
}
```

## Every field

`allergens`objectoptional

`<allergen>`boolean

One key per allergen identifier from GET /vocabularies, such as "milk" or "gluten-cereals": true when the recipe contains it.

`disclaimer`string

The required informational-use warning.

Whether the recipe contains each EU and US regulated allergen: one true or false for each of the 16 allergen identifiers, keyed by identifier, beside the disclaimer. Informational only; verify product labels before serving someone with an allergy.

`author`objectoptional

Who wrote the recipe, and a link to them when the site published one.

`categories`string\[\]

Normalized category slugs from an open set, such as "pasta" or "soup". The value the \`category\` filter takes.

`courses`string\[\]

Course slugs from the closed list. The value the \`course\` filter takes.

`createdAt`string

When the recipe first entered the database. ISO 8601.

`cuisines`string\[\]

Cuisine slugs from the closed list. The value the \`cuisine\` filter takes.

`description`stringoptional

The recipe’s own summary.

`dietary`objectoptional

Dietary flags, declared by the site or inferred from the required ingredients. A declared flag wins; a missing flag is unknown, and false is a known no. An inferred \`glutenFree\` or \`dairyFree\` can disagree with \`allergens\` by design: the diet reads the required ingredients, so a dish is gluten-free once the optional pita is left out, while the allergen block counts every line and stays cautious.

`equipment`string\[\]optional

Equipment the recipe calls for, as words rather than slugs.

`groups`string\[\]

The section headers of the recipe: the distinct \`group\` values of the ingredients and then the steps, in the order they first appear. Empty when the recipe has no sections.

`id`string

The recipe id.

`ingredients[]`object\[\]

`display`string

The line to render. Equal to the source line until the structure and the source part company — a converted unit, an amount enrichment filled in.

`group`stringoptional

The section header the line sat under, such as "For the sauce".

`ingredientId`stringoptional

The canonical ingredient id, such as "chicken-thigh". Absent until the recipe has been enriched, or when the name could not be resolved. This is the value the \`ingredient\` filter of GET /recipes takes.

`localName`stringoptional

The ingredient as this recipe’s own language names it, when that differs from \`name\`.

`localPreparation`stringoptional

How the ingredient is prepared, in the recipe’s own words, such as "finhackade" where \`preparation\` says "finely chopped". Absent on an English recipe, where \`preparation\` already is the reader’s, and on a line that says nothing of the kind. \`display\` is written with this one.

`name`string

The canonical English name.

`note`stringoptional

Anything the parser understood but could not place, such as "(400 g)". Kept as the source wrote it, in the recipe’s language, and never translated.

`optional`boolean

Whether the recipe marks this ingredient as optional.

`original`string

The source line, verbatim. Rewriting a recipe — scaling it, converting its units — leaves this alone.

`preparation`stringoptional

How the ingredient is prepared, in English, such as "finely chopped". Read \`localPreparation\` for the words the recipe itself uses.

`quantity`objectoptional

`max`numberoptional

The top of a range.

`unit`stringoptional

One of the units listed by GET /vocabularies.

`value`number

The amount itself.

The amount. A range such as "2-3 tomatoes" is a value of 2 with a max of 3\. A value with no unit is a count of pieces.

`size`stringoptional

A size qualifier, such as "large".

One ingredient line, parsed. \`original\` is the line the site published; \`display\` is the same line written back from these fields, in the recipe’s own language.

`instructions[]`object\[\]

`duration`objectoptional

`seconds`integer

Seconds.

A length of time. Always seconds, never a formatted string.

`equipment`string\[\]optional

Equipment slugs the step calls for.

`group`stringoptional

The section the step sat under or, where the page named no section, the heading the step carried of its own.

`ingredients`string\[\]optional

Canonical ingredient ids the step uses.

`step`integer

The step number. Steps always run 1, 2, 3… in order.

`techniques`string\[\]optional

Technique slugs the step uses, such as "saute".

`temperature`objectoptional

An oven or pan temperature, with its unit as "C" or "F".

`text`string

The step text.

One step. The text is authoritative; everything else on a step comes from enrichment and may be absent.

`language`string

The language the recipe is written in, as a two-letter ISO 639-1 code.

`media[]`object\[\]

`alt`stringoptional

Alternative text.

`caption`stringoptional

A caption published with the item.

`id`string

Unique within the recipe.

`role`string

Where the item sits in the recipe.

`step`integeroptional

For role "step", the step number the item illustrates.

`type`string

"image" or "video".

`url`string

The file itself.

`variants`object\[\]optional

The same photo in other sizes or crops. Images only.

Images and videos. An image carries a \`role\` of hero, gallery, step or thumbnail; a video carries gallery or step. A recipe has at most one hero image.

`notes`string\[\]optional

What the writer added beside the method: storage, make-ahead, substitutions. One entry per note, in the order the page wrote them.

`nutrition`objectoptional

`basis`object

What the numbers are per. \`type\` is "serving", "recipe" or "100g"; \`servings\` is the serving count the site worked the numbers out on, which is not always the serving count the recipe is written for; \`description\` is the serving size the site named, such as "1 cup".

`calories`objectoptional

Energy, with its unit.

`carbohydrates`objectoptional

Carbohydrates.

`fat`objectoptional

Fat.

`fiber`objectoptional

Fibre.

`micronutrients`objectoptional

Anything else the source declared, keyed by nutrient slug.

`protein`objectoptional

Protein.

`saturatedFat`objectoptional

Saturated fat.

`sodium`objectoptional

Sodium.

`source`string

"provided": the site published these numbers itself, in the structured data the recipe was read from, so they are as current as the last read of that page.

`sugar`objectoptional

Sugar.

Nutrition as the site published it. \`basis\` says whether the numbers are per serving, per recipe or per 100 g. The API does not compute nutrition from the ingredients, so a recipe whose site publishes none has no nutrition object at all.

`rating`objectoptional

The rating the source published, with how many people rated it.

`servings`objectoptional

How much the recipe makes. "Serves 4-6" is a quantity of 4 with a max of 6; "Makes 24 cookies" is a quantity of 24 with a unit of "cookie".

`tags`string\[\]

The source site’s own keywords, cleaned but not mapped to any vocabulary.

`techniques`string\[\]optional

Techniques the recipe uses, as words rather than slugs.

`text`object

`ingredients`string\[\]

One line per ingredient.

`instructions`string\[\]

One line per step.

The recipe as plain lines: every ingredient’s \`display\` and every step’s \`text\`, in order. A convenience for rendering; nothing here is missing from the structured fields.

`times`object

`cook`objectoptional

`seconds`integer

Seconds.

A length of time. Always seconds, never a formatted string.

`inactive`objectoptional

`seconds`integer

Seconds.

A length of time. Always seconds, never a formatted string.

`prep`objectoptional

`seconds`integer

Seconds.

A length of time. Always seconds, never a formatted string.

`total`objectoptional

`seconds`integer

Seconds.

A length of time. Always seconds, never a formatted string.

Preparation, cooking, inactive and total time, each in seconds.

`title`string

The recipe title.

`updatedAt`string

When the recipe was last written. ISO 8601.

`url`string

The page the recipe was read from. One source URL is one recipe.

## A whole recipe

A real response from [GET /recipes/{id}](https://www.tinyplates.dev/docs/api/get-recipe).

```
{
  "recipe": {
    "allergens": {
      "celery": false,
      "crustaceans": false,
      "eggs": false,
      "fish": false,
      "gluten-cereals": false,
      "lupin": false,
      "milk": true,
      "molluscs": false,
      "mustard": false,
      "nuts-eu": false,
      "peanuts": true,
      "sesame": false,
      "soy": false,
      "sulphites": false,
      "tree-nuts-us": false,
      "wheat": false,
      "disclaimer": "Informational only; not medical advice. Verify ingredients and product labels before serving someone with an allergy."
    },
    "id": "6a9820e58f8122ec891b68a3",
    "author": {
      "name": "Lindsay Ostrom",
      "url": "https://pinchofyum.com/about"
    },
    "description": "This peanut butter dark chocolate hummus is a sweet alternative to traditional hummus. Perfect served on graham crackers as an afternoon snack!",
    "instructions": [
      {
        "group": "Hummus",
        "step": 1,
        "text": "Blend everything through milk in a food processor."
      },
      {
        "group": "Hummus",
        "step": 2,
        "text": "Add flour by the spoonful and blend until desired consistency is reached."
      },
      {
        "step": 3,
        "text": "Stir in dark chocolate."
      },
      {
        "step": 4,
        "text": "Chill before serving."
      }
    ],
    "language": "en",
    "media": [
      {
        "id": "hero",
        "role": "hero",
        "type": "image",
        "url": "https://pinchofyum.com/tachyon/2011/05/Peanut-Butter-Dark-Chocolate-Hummus.jpeg?fit=225%2C225",
        "variants": [
          {
            "url": "https://pinchofyum.com/tachyon/2011/05/Peanut-Butter-Dark-Chocolate-Hummus.jpeg?fit=195%2C195"
          },
          {
            "url": "https://pinchofyum.com/tachyon/2011/05/Peanut-Butter-Dark-Chocolate-Hummus.jpeg?fit=180%2C180"
          },
          {
            "url": "https://pinchofyum.com/tachyon/2011/05/Peanut-Butter-Dark-Chocolate-Hummus.jpeg"
          }
        ]
      }
    ],
    "notes": [
      "Keeps in an airtight container in the fridge for up to five days.",
      "Swap the peanut butter for almond butter to make it peanut free."
    ],
    "nutrition": {
      "basis": {
        "description": "¼ cup",
        "servings": 8,
        "type": "serving"
      },
      "calories": {
        "unit": "kcal",
        "value": 201
      },
      "carbohydrates": {
        "unit": "g",
        "value": 29.4
      },
      "cholesterol": {
        "unit": "mg",
        "value": 0.8
      },
      "fat": {
        "unit": "g",
        "value": 7.4
      },
      "fiber": {
        "unit": "g",
        "value": 3.3
      },
      "micronutrients": {
        "trans-fat": {
          "unit": "g",
          "value": 0
        }
      },
      "protein": {
        "unit": "g",
        "value": 5.6
      },
      "saturatedFat": {
        "unit": "g",
        "value": 2.5
      },
      "sodium": {
        "unit": "mg",
        "value": 76
      },
      "source": "provided",
      "sugar": {
        "unit": "g",
        "value": 16.9
      }
    },
    "rating": {
      "count": 1,
      "reviewCount": 1,
      "value": 5
    },
    "servings": {
      "max": 8,
      "original": "6-8",
      "quantity": 6
    },
    "times": {
      "cook": {
        "seconds": 600
      },
      "prep": {
        "seconds": 300
      },
      "total": {
        "seconds": 900
      }
    },
    "title": "Peanut Butter Dark Chocolate Hummus",
    "categories": [],
    "courses": [
      "dessert"
    ],
    "createdAt": "2026-09-02T13:13:09.089Z",
    "cuisines": [
      "american"
    ],
    "groups": [
      "Hummus"
    ],
    "ingredients": [
      {
        "display": "1 can white beans or chickpeas, rinsed",
        "name": "white beans or chickpeas",
        "optional": false,
        "original": "1 can white beans or chickpeas, rinsed",
        "preparation": "rinsed",
        "quantity": {
          "unit": "can",
          "value": 1
        }
      },
      {
        "display": "¼ cup peanut butter",
        "name": "peanut butter",
        "optional": false,
        "original": "¼ cup peanut butter",
        "quantity": {
          "unit": "cup",
          "value": 0.25
        }
      },
      {
        "display": "2 tbsp caramel sauce",
        "name": "caramel sauce",
        "optional": false,
        "original": "2 tbsp caramel sauce",
        "quantity": {
          "unit": "tbsp",
          "value": 2
        }
      },
      {
        "display": "2 tbsp maple syrup",
        "name": "maple syrup",
        "optional": false,
        "original": "2 tbsp maple syrup",
        "quantity": {
          "unit": "tbsp",
          "value": 2
        }
      },
      {
        "display": "¼ cup brown sugar",
        "name": "brown sugar",
        "optional": false,
        "original": "¼ cup brown sugar",
        "quantity": {
          "unit": "cup",
          "value": 0.25
        }
      },
      {
        "display": "pinch of cinnamon",
        "name": "pinch of cinnamon",
        "optional": false,
        "original": "pinch of cinnamon"
      },
      {
        "display": "¼ cup milk",
        "name": "milk",
        "optional": false,
        "original": "¼ cup milk",
        "quantity": {
          "unit": "cup",
          "value": 0.25
        }
      },
      {
        "display": "¼ cup flour",
        "name": "flour",
        "optional": false,
        "original": "¼ cup flour",
        "quantity": {
          "unit": "cup",
          "value": 0.25
        }
      },
      {
        "display": "chopped dark chocolate",
        "name": "chopped dark chocolate",
        "optional": false,
        "original": "chopped dark chocolate"
      }
    ],
    "tags": [
      "chocolate hummus",
      "peanut butter hummus",
      "peanut butter chocolate",
      "hummus recipe",
      "dessert hummus"
    ],
    "text": {
      "ingredients": [
        "1 can white beans or chickpeas, rinsed",
        "¼ cup peanut butter",
        "2 tbsp caramel sauce",
        "2 tbsp maple syrup",
        "¼ cup brown sugar",
        "pinch of cinnamon",
        "¼ cup milk",
        "¼ cup flour",
        "chopped dark chocolate"
      ],
      "instructions": [
        "Blend everything through milk in a food processor.",
        "Add flour by the spoonful and blend until desired consistency is reached.",
        "Stir in dark chocolate.",
        "Chill before serving."
      ]
    },
    "updatedAt": "2026-09-06T01:11:59.223Z",
    "url": "https://pinchofyum.com/pb-dark-chocolate-hummus"
  }
}
```
