{"openapi":"3.1.0","info":{"title":"Tiny Plates API","version":"2.0.0","description":"Read API for the recipe database. Recipes are scraped from the web, then normalized into a canonical model with structured ingredients, numbered steps, times in seconds, servings, nutrition, media and classification.\n\nDocumentation lives in the developer portal, where you also create a key.\n\nAuthentication: API keys are optional today and will become required. Send the key as an Authorization: Bearer header. Each account may make 500 requests per day, counted across all of its keys."},"paths":{"/health":{"get":{"tags":["health"],"operationId":"health.check","parameters":[],"security":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["status"],"properties":{"status":{"type":"string","enum":["ok"]}},"additionalProperties":false}}}},"400":{"description":"The request did not match the expected schema","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpApiDecodeError"}}}}},"description":"Health check that verifies the API is running."}},"/pantry":{"get":{"tags":["pantry"],"operationId":"pantry.list","parameters":[{"name":"ingredients","in":"query","schema":{"type":"string"},"required":true},{"name":"language","in":"query","schema":{"type":"string"},"required":false},{"name":"limit","in":"query","schema":{"type":"string"},"required":false},{"name":"maxMissing","in":"query","schema":{"type":"string"},"required":false},{"name":"offset","in":"query","schema":{"type":"string"},"required":false}],"security":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["pagination","recipes"],"properties":{"pagination":{"$ref":"#/components/schemas/Pagination"},"recipes":{"type":"array","items":{"$ref":"#/components/schemas/PantryRecipe"}}},"additionalProperties":false}}}},"400":{"description":"The request did not match the expected schema","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/HttpApiDecodeError"},{"$ref":"#/components/schemas/InvalidParameterError"}]}}}},"401":{"description":"ApiKeyDisabledError","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ApiKeyDisabledError"},{"$ref":"#/components/schemas/ApiKeyExpiredError"},{"$ref":"#/components/schemas/ApiKeyRequiredError"},{"$ref":"#/components/schemas/InvalidApiKeyError"}]}}}},"429":{"description":"ApiKeyRateLimitedError","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyRateLimitedError"}}}},"500":{"description":"InternalError","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}},"description":"What you can cook from what you have. `ingredients` is the pantry: 1 to 20 comma-separated ingredient names or canonical ids. Only recipes that use at least one of them are returned, best covered first, and each carries the pantry ingredients it uses and the ingredients you are missing. `maxMissing` narrows that to recipes you are short no more than that many ingredients for — `maxMissing=0` is what you can cook right now.","summary":"Rank recipes by how much of them your pantry covers."}},"/popular":{"get":{"tags":["popular"],"operationId":"popular.list","parameters":[{"name":"language","in":"query","schema":{"type":"string"},"required":false},{"name":"limit","in":"query","schema":{"type":"string"},"required":false},{"name":"offset","in":"query","schema":{"type":"string"},"required":false}],"security":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["pagination","recipes"],"properties":{"pagination":{"$ref":"#/components/schemas/Pagination"},"recipes":{"type":"array","items":{"$ref":"#/components/schemas/PopularRecipe"}}},"additionalProperties":false}}}},"400":{"description":"The request did not match the expected schema","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpApiDecodeError"}}}},"401":{"description":"ApiKeyDisabledError","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ApiKeyDisabledError"},{"$ref":"#/components/schemas/ApiKeyExpiredError"},{"$ref":"#/components/schemas/ApiKeyRequiredError"},{"$ref":"#/components/schemas/InvalidApiKeyError"}]}}}},"429":{"description":"ApiKeyRateLimitedError","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyRateLimitedError"}}}},"500":{"description":"InternalError","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}},"description":"The most popular recipes first. Ranking favours recipes that are both well rated and rated by a lot of people, so a single five-star review will not outrank a long-standing favourite."}},"/recipes":{"get":{"tags":["recipes"],"operationId":"recipes.list","parameters":[{"name":"category","in":"query","schema":{"type":"string"},"required":false},{"name":"course","in":"query","schema":{"type":"string"},"required":false},{"name":"cuisine","in":"query","schema":{"type":"string"},"required":false},{"name":"diet","in":"query","schema":{"type":"string"},"required":false},{"name":"equipment","in":"query","schema":{"type":"string"},"required":false},{"name":"excludeIngredients","in":"query","schema":{"type":"string"},"required":false},{"name":"ingredient","in":"query","schema":{"type":"string"},"required":false},{"name":"ingredients","in":"query","schema":{"type":"string"},"required":false},{"name":"language","in":"query","schema":{"type":"string"},"required":false},{"name":"limit","in":"query","schema":{"type":"string"},"required":false},{"name":"maxCalories","in":"query","schema":{"type":"string"},"required":false},{"name":"maxCookMinutes","in":"query","schema":{"type":"string"},"required":false},{"name":"maxSodium","in":"query","schema":{"type":"string"},"required":false},{"name":"maxTotalMinutes","in":"query","schema":{"type":"string"},"required":false},{"name":"minFiber","in":"query","schema":{"type":"string"},"required":false},{"name":"minProtein","in":"query","schema":{"type":"string"},"required":false},{"name":"nutrition","in":"query","schema":{"type":"string"},"required":false},{"name":"offset","in":"query","schema":{"type":"string"},"required":false},{"name":"time","in":"query","schema":{"type":"string"},"required":false}],"security":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["pagination","recipes"],"properties":{"pagination":{"$ref":"#/components/schemas/Pagination"},"recipes":{"type":"array","items":{"$ref":"#/components/schemas/Recipe"}}},"additionalProperties":false}}}},"400":{"description":"The request did not match the expected schema","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/HttpApiDecodeError"},{"$ref":"#/components/schemas/InvalidParameterError"}]}}}},"401":{"description":"ApiKeyDisabledError","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ApiKeyDisabledError"},{"$ref":"#/components/schemas/ApiKeyExpiredError"},{"$ref":"#/components/schemas/ApiKeyRequiredError"},{"$ref":"#/components/schemas/InvalidApiKeyError"}]}}}},"429":{"description":"ApiKeyRateLimitedError","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyRateLimitedError"}}}},"500":{"description":"InternalError","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}},"description":"Paginated list of recipes, newest first. Filter by `cuisine`, `course`, `category`, `diet`, `equipment` (all listed equipment), `ingredient` (a canonical ingredient id such as \"chicken-thigh\"), `ingredients` (all required names or IDs), `language`, `maxCookMinutes`, `maxTotalMinutes`, `time`, `maxCalories`, `maxSodium`, `minFiber`, `minProtein` and `nutrition` (presets: high-fiber, high-protein, low-calorie, low-sodium). The nutrition filters read the per-serving figures a recipe was published with; a recipe without them does not match. Allowed values for the closed vocabularies come from /vocabularies.","summary":"Filter recipes by classification, ingredients, cooking time, total-time presets and per-serving nutrition."}},"/recipes/{id}":{"get":{"tags":["recipes"],"operationId":"recipes.byId","parameters":[{"name":"id","in":"path","schema":{"type":"string"},"required":true},{"name":"servings","in":"query","schema":{"type":"string"},"required":false},{"name":"units","in":"query","schema":{"type":"string"},"required":false}],"security":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["recipe"],"properties":{"conversion":{"type":"object","required":["system","unweighed"],"properties":{"system":{"type":"string","enum":["imperial","metric"]},"unweighed":{"type":"array","items":{"type":"string"},"description":"Ingredients measured by volume that could not be weighed, because no density is known for them. Their quantities are still in a volume unit."}},"additionalProperties":false},"nutritionTotals":{"$ref":"#/components/schemas/NutritionTotals"},"recipe":{"$ref":"#/components/schemas/Recipe"}},"additionalProperties":false}}}},"400":{"description":"The request did not match the expected schema","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/HttpApiDecodeError"},{"$ref":"#/components/schemas/InvalidParameterError"}]}}}},"401":{"description":"ApiKeyDisabledError","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ApiKeyDisabledError"},{"$ref":"#/components/schemas/ApiKeyExpiredError"},{"$ref":"#/components/schemas/ApiKeyRequiredError"},{"$ref":"#/components/schemas/InvalidApiKeyError"}]}}}},"404":{"description":"RecipeNotFoundError","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecipeNotFoundError"}}}},"429":{"description":"ApiKeyRateLimitedError","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyRateLimitedError"}}}},"500":{"description":"InternalError","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}},"description":"Retrieve a single recipe by its id. `servings` rewrites every quantity for that many servings: ranges scale with them, an ingredient with no quantity is left alone, and `original` still holds the line the source published. Per-serving nutrition does not change, because more servings of the same food is the same plate. `units` rewrites the recipe in metric or imperial units, converting oven temperatures too and weighing a volume when the density of the ingredient is known; ingredients it could not weigh come back in `conversion.unweighed`."}},"/":{"get":{"tags":["root"],"operationId":"root.index","parameters":[],"security":[],"responses":{"200":{"description":"a string","content":{"text/plain":{"schema":{"type":"string"}}}},"400":{"description":"The request did not match the expected schema","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpApiDecodeError"}}}}},"description":"What this API is and where to read about it, as plain text. Needs no API key."}},"/search":{"get":{"tags":["search"],"operationId":"search.search","parameters":[{"name":"query","in":"query","schema":{"type":"string"},"required":true},{"name":"fields","in":"query","schema":{"type":"string"},"required":false},{"name":"language","in":"query","schema":{"type":"string"},"required":false},{"name":"limit","in":"query","schema":{"type":"string"},"required":false}],"security":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["results"],"properties":{"results":{"type":"array","items":{"$ref":"#/components/schemas/SearchResult"}}},"additionalProperties":false}}}},"400":{"description":"The request did not match the expected schema","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/HttpApiDecodeError"},{"$ref":"#/components/schemas/SearchQueryRequiredError"}]}}}},"401":{"description":"ApiKeyDisabledError","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ApiKeyDisabledError"},{"$ref":"#/components/schemas/ApiKeyExpiredError"},{"$ref":"#/components/schemas/ApiKeyRequiredError"},{"$ref":"#/components/schemas/InvalidApiKeyError"}]}}}},"429":{"description":"ApiKeyRateLimitedError","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyRateLimitedError"}}}},"500":{"description":"InternalError","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}},"description":"Search recipes by name, ingredients and description. Matches on meaning as well as wording, so a search for \"creamy pasta\" also finds carbonara. Use the \"fields\" parameter to return only the fields you need."}},"/shopping-list":{"get":{"tags":["shoppingList"],"operationId":"shoppingList.build","parameters":[{"name":"recipes","in":"query","schema":{"type":"string"},"required":true}],"security":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["items","recipes"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/ShoppingItem"}},"recipes":{"type":"array","items":{"type":"object","required":["id","servings","title"],"properties":{"id":{"type":"string"},"servings":{"type":"number"},"title":{"type":"string"}},"additionalProperties":false}}},"additionalProperties":false}}}},"400":{"description":"The request did not match the expected schema","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/HttpApiDecodeError"},{"$ref":"#/components/schemas/InvalidParameterError"}]}}}},"401":{"description":"ApiKeyDisabledError","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ApiKeyDisabledError"},{"$ref":"#/components/schemas/ApiKeyExpiredError"},{"$ref":"#/components/schemas/ApiKeyRequiredError"},{"$ref":"#/components/schemas/InvalidApiKeyError"}]}}}},"429":{"description":"ApiKeyRateLimitedError","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyRateLimitedError"}}}},"500":{"description":"InternalError","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}},"description":"One shopping list for several recipes. `recipes` is a comma-separated list of recipe ids, each optionally followed by a colon and the servings to cook — `66d0a1b2c3d4e5f6a7b8c9d0:6,66d0a1b2c3d4e5f6a7b8c9d1`. Quantities are scaled to those servings and then added up wherever they can be: grams to grams, cloves to cloves. Amounts that cannot be added, such as two cloves of garlic and 10 g of garlic, stay separate lines.","summary":"Consolidate several recipes into one list, grouped by aisle."}},"/ingredients":{"get":{"tags":["ingredients"],"operationId":"ingredients.list","parameters":[{"name":"limit","in":"query","schema":{"type":"string"},"required":false}],"security":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["ingredients"],"properties":{"ingredients":{"type":"array","items":{"$ref":"#/components/schemas/Ingredient"}}},"additionalProperties":false}}}},"400":{"description":"The request did not match the expected schema","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/HttpApiDecodeError"},{"$ref":"#/components/schemas/InvalidParameterError"}]}}}},"401":{"description":"ApiKeyDisabledError","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ApiKeyDisabledError"},{"$ref":"#/components/schemas/ApiKeyExpiredError"},{"$ref":"#/components/schemas/ApiKeyRequiredError"},{"$ref":"#/components/schemas/InvalidApiKeyError"}]}}}},"429":{"description":"ApiKeyRateLimitedError","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyRateLimitedError"}}}},"500":{"description":"InternalError","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}},"description":"The canonical ingredient vocabulary, most used first. Use an id as the `ingredient` filter of /recipes."}},"/vocabularies":{"get":{"tags":["ingredients"],"operationId":"ingredients.vocabularies","parameters":[],"security":[],"responses":{"200":{"description":"The closed vocabularies recipes are classified with. Use these values in the list filters.","content":{"application/json":{"schema":{"type":"object","required":["allergens","courses","cuisines","diets","units"],"properties":{"allergens":{"type":"array","items":{"type":"string"}},"courses":{"type":"array","items":{"type":"string"}},"cuisines":{"type":"array","items":{"type":"string"}},"diets":{"type":"array","items":{"type":"string"}},"units":{"type":"array","items":{"type":"string"}}},"additionalProperties":false,"description":"The closed vocabularies recipes are classified with. Use these values in the list filters."}}}},"400":{"description":"The request did not match the expected schema","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpApiDecodeError"}}}},"401":{"description":"ApiKeyDisabledError","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ApiKeyDisabledError"},{"$ref":"#/components/schemas/ApiKeyExpiredError"},{"$ref":"#/components/schemas/ApiKeyRequiredError"},{"$ref":"#/components/schemas/InvalidApiKeyError"}]}}}},"429":{"description":"ApiKeyRateLimitedError","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyRateLimitedError"}}}}},"description":"The closed lists recipes are classified with: cuisines, courses, diets, allergens and units."}},"/status":{"get":{"tags":["status"],"operationId":"status.read","parameters":[],"security":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["pages","recipes","sites"],"properties":{"pages":{"$ref":"#/components/schemas/PageStatusCounts"},"recipes":{"type":"number"},"sites":{"type":"number"}},"additionalProperties":false}}}},"400":{"description":"The request did not match the expected schema","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpApiDecodeError"}}}},"401":{"description":"ApiKeyDisabledError","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ApiKeyDisabledError"},{"$ref":"#/components/schemas/ApiKeyExpiredError"},{"$ref":"#/components/schemas/ApiKeyRequiredError"},{"$ref":"#/components/schemas/InvalidApiKeyError"}]}}}},"429":{"description":"ApiKeyRateLimitedError","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyRateLimitedError"}}}},"500":{"description":"InternalError","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}},"description":"How much data the API is serving: the number of recipes and sites available, and how far collection has progressed across the pages they came from."}},"/substitutions":{"get":{"tags":["substitutions"],"operationId":"substitutions.list","parameters":[{"name":"ingredients","in":"query","schema":{"type":"string"},"required":true}],"security":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","required":["substitutions","unknown"],"properties":{"substitutions":{"type":"array","items":{"type":"object","required":["ingredient","options"],"properties":{"ingredient":{"type":"string"},"options":{"type":"array","items":{"$ref":"#/components/schemas/Substitution"}}},"additionalProperties":false}},"unknown":{"type":"array","items":{"type":"string"},"description":"The ingredients asked about that nothing is known to substitute for. Nothing is suggested for them, rather than something plausible that would not work."}},"additionalProperties":false}}}},"400":{"description":"The request did not match the expected schema","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/HttpApiDecodeError"},{"$ref":"#/components/schemas/InvalidParameterError"}]}}}},"401":{"description":"ApiKeyDisabledError","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ApiKeyDisabledError"},{"$ref":"#/components/schemas/ApiKeyExpiredError"},{"$ref":"#/components/schemas/ApiKeyRequiredError"},{"$ref":"#/components/schemas/InvalidApiKeyError"}]}}}},"429":{"description":"ApiKeyRateLimitedError","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyRateLimitedError"}}}},"500":{"description":"InternalError","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}},"description":"What to use instead of an ingredient. `ingredients` is a comma-separated list of ingredient names or canonical ids. Each option says how much to use for one unit of the original, how to handle it, and what it cannot be used for. Ingredients nothing is known to substitute for come back in `unknown` rather than with a plausible guess.","summary":"What to use instead, in what amount, and when not to."}}},"components":{"schemas":{"HttpApiDecodeError":{"type":"object","required":["issues","message","_tag"],"properties":{"issues":{"type":"array","items":{"$ref":"#/components/schemas/Issue"}},"message":{"type":"string"},"_tag":{"type":"string","enum":["HttpApiDecodeError"]}},"additionalProperties":false,"description":"The request did not match the expected schema"},"Issue":{"type":"object","required":["_tag","path","message"],"properties":{"_tag":{"type":"string","enum":["Pointer","Unexpected","Missing","Composite","Refinement","Transformation","Type","Forbidden"],"description":"The tag identifying the type of parse issue"},"path":{"type":"array","items":{"$ref":"#/components/schemas/PropertyKey"},"description":"The path to the property where the issue occurred"},"message":{"type":"string","description":"A descriptive message explaining the issue"}},"additionalProperties":false,"description":"Represents an error encountered while parsing a value to match the schema"},"PropertyKey":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"object","required":["_tag","key"],"properties":{"_tag":{"type":"string","enum":["symbol"]},"key":{"type":"string"}},"additionalProperties":false,"description":"an object to be decoded into a globally shared symbol"}]},"Pagination":{"type":"object","required":["limit","offset","total"],"properties":{"limit":{"type":"number"},"offset":{"type":"number"},"total":{"type":"number"}},"additionalProperties":false,"description":"Offset pagination. `limit` is capped at 100."},"PantryRecipe":{"type":"object","required":["id","instructions","language","media","times","title","categories","courses","createdAt","cuisines","ingredients","tags","text","updatedAt","url","coverage","matchedIngredients","missingIngredients"],"properties":{"id":{"type":"string"},"allergens":{"type":"array","items":{"$ref":"#/components/schemas/Allergen"}},"author":{"$ref":"#/components/schemas/Author"},"description":{"$ref":"#/components/schemas/NonEmptyTrimmedString"},"dietary":{"$ref":"#/components/schemas/Dietary"},"instructions":{"type":"array","minItems":1,"items":{"$ref":"#/components/schemas/RecipeInstruction"}},"language":{"$ref":"#/components/schemas/Language"},"media":{"type":"array","items":{"$ref":"#/components/schemas/RecipeMedia"}},"nutrition":{"$ref":"#/components/schemas/Nutrition"},"rating":{"$ref":"#/components/schemas/Rating"},"servings":{"$ref":"#/components/schemas/Servings"},"times":{"$ref":"#/components/schemas/RecipeTimes"},"title":{"$ref":"#/components/schemas/NonEmptyTrimmedString"},"categories":{"type":"array","items":{"type":"string"}},"courses":{"type":"array","items":{"type":"string"}},"createdAt":{"$ref":"#/components/schemas/Date"},"cuisines":{"type":"array","items":{"type":"string"}},"equipment":{"type":"array","items":{"type":"string"}},"ingredients":{"type":"array","minItems":1,"items":{"$ref":"#/components/schemas/RecipeIngredient"}},"tags":{"type":"array","items":{"type":"string"}},"techniques":{"type":"array","items":{"type":"string"}},"text":{"$ref":"#/components/schemas/RecipeText"},"updatedAt":{"$ref":"#/components/schemas/Date"},"url":{"type":"string"},"coverage":{"type":"number","description":"The share of this recipe's ingredients your pantry covers, from 0 to 1, rounded to two decimals. Higher comes first."},"matchedIngredients":{"type":"array","items":{"type":"string"},"description":"The recipe ingredients your pantry covers, as the recipe names them."},"missingIngredients":{"type":"array","items":{"type":"string"},"description":"The recipe ingredients your pantry does not cover, as the recipe names them."}},"additionalProperties":false,"description":"A recipe together with what your pantry covers and what it does not. Ingredient names are the recipe's own, in its own language."},"Allergen":{"type":"string","enum":["celery","crustaceans","eggs","fish","gluten","lupin","milk","molluscs","mustard","peanuts","sesame","soy","sulphites","tree-nuts"]},"Author":{"type":"object","required":["name"],"properties":{"name":{"$ref":"#/components/schemas/NonEmptyTrimmedString"},"url":{"$ref":"#/components/schemas/Url"}},"additionalProperties":false},"NonEmptyTrimmedString":{"type":"string","description":"a non empty string","title":"nonEmptyString","pattern":"^\\S[\\s\\S]*\\S$|^\\S$|^$","minLength":1},"Url":{"type":"string","description":"a string matching the pattern ^https?:\\/\\/\\S+$","pattern":"^https?:\\/\\/\\S+$"},"Dietary":{"type":"object","required":["source"],"properties":{"dairyFree":{"type":"boolean"},"glutenFree":{"type":"boolean"},"pescatarian":{"type":"boolean"},"source":{"type":"string","enum":["declared","inferred"]},"vegan":{"type":"boolean"},"vegetarian":{"type":"boolean"}},"additionalProperties":false},"RecipeInstruction":{"type":"object","required":["step","text"],"properties":{"duration":{"$ref":"#/components/schemas/Duration"},"equipment":{"type":"array","items":{"$ref":"#/components/schemas/Slug"}},"group":{"$ref":"#/components/schemas/NonEmptyTrimmedString"},"ingredients":{"type":"array","items":{"type":"string","description":"a string matching the pattern ^[a-z0-9]+(-[a-z0-9]+)*$","pattern":"^[a-z0-9]+(-[a-z0-9]+)*$"}},"step":{"type":"integer","description":"a positive number","title":"positive","exclusiveMinimum":0},"techniques":{"type":"array","items":{"$ref":"#/components/schemas/Slug"}},"temperature":{"$ref":"#/components/schemas/Temperature"},"text":{"$ref":"#/components/schemas/NonEmptyTrimmedString"}},"additionalProperties":false},"Duration":{"type":"object","required":["seconds"],"properties":{"seconds":{"$ref":"#/components/schemas/NonNegativeInt"}},"additionalProperties":false},"NonNegativeInt":{"type":"integer","description":"an integer","title":"int","minimum":0},"Slug":{"type":"string","description":"a string matching the pattern ^[a-z0-9]+(-[a-z0-9]+)*$","pattern":"^[a-z0-9]+(-[a-z0-9]+)*$"},"Temperature":{"type":"object","required":["unit","value"],"properties":{"unit":{"type":"string","enum":["C","F"]},"value":{"type":"number"}},"additionalProperties":false},"Language":{"type":"string","description":"a string matching the pattern ^[a-z]{2}$","pattern":"^[a-z]{2}$"},"RecipeMedia":{"anyOf":[{"$ref":"#/components/schemas/ImageMedia"},{"$ref":"#/components/schemas/VideoMedia"}]},"ImageMedia":{"type":"object","required":["id","role","type","url"],"properties":{"alt":{"$ref":"#/components/schemas/NonEmptyTrimmedString"},"caption":{"$ref":"#/components/schemas/NonEmptyTrimmedString"},"id":{"$ref":"#/components/schemas/Trimmed","description":"a non empty string","title":"nonEmptyString","minLength":1},"license":{"$ref":"#/components/schemas/NonEmptyTrimmedString"},"sourceUrl":{"$ref":"#/components/schemas/Url"},"step":{"type":"integer","description":"a positive number","title":"positive","exclusiveMinimum":0},"height":{"type":"integer","description":"a positive number","title":"positive","exclusiveMinimum":0},"role":{"type":"string","enum":["gallery","hero","step","thumbnail"]},"type":{"type":"string","enum":["image"]},"url":{"$ref":"#/components/schemas/Url"},"variants":{"type":"array","items":{"$ref":"#/components/schemas/ImageVariant"}},"width":{"type":"integer","description":"a positive number","title":"positive","exclusiveMinimum":0}},"additionalProperties":false},"Trimmed":{"type":"string","description":"a string with no leading or trailing whitespace","title":"trimmed","pattern":"^\\S[\\s\\S]*\\S$|^\\S$|^$"},"ImageVariant":{"type":"object","required":["url"],"properties":{"height":{"type":"integer","description":"a positive number","title":"positive","exclusiveMinimum":0},"url":{"$ref":"#/components/schemas/Url"},"width":{"type":"integer","description":"a positive number","title":"positive","exclusiveMinimum":0}},"additionalProperties":false},"VideoMedia":{"type":"object","required":["id","role","type","url"],"properties":{"alt":{"$ref":"#/components/schemas/NonEmptyTrimmedString"},"caption":{"$ref":"#/components/schemas/NonEmptyTrimmedString"},"id":{"$ref":"#/components/schemas/Trimmed","description":"a non empty string","title":"nonEmptyString","minLength":1},"license":{"$ref":"#/components/schemas/NonEmptyTrimmedString"},"sourceUrl":{"$ref":"#/components/schemas/Url"},"step":{"type":"integer","description":"a positive number","title":"positive","exclusiveMinimum":0},"duration":{"$ref":"#/components/schemas/Duration"},"embedUrl":{"$ref":"#/components/schemas/Url"},"provider":{"$ref":"#/components/schemas/NonEmptyTrimmedString"},"role":{"type":"string","enum":["gallery","step"]},"thumbnailUrl":{"$ref":"#/components/schemas/Url"},"type":{"type":"string","enum":["video"]},"url":{"$ref":"#/components/schemas/Url"},"videoId":{"$ref":"#/components/schemas/NonEmptyTrimmedString"}},"additionalProperties":false},"Nutrition":{"type":"object","required":["basis","source"],"properties":{"basis":{"type":"object","required":["type"],"properties":{"servings":{"$ref":"#/components/schemas/Positive"},"type":{"type":"string","enum":["100g","recipe","serving"]}},"additionalProperties":false},"calories":{"$ref":"#/components/schemas/NutrientValue"},"carbohydrates":{"$ref":"#/components/schemas/NutrientValue"},"cholesterol":{"$ref":"#/components/schemas/NutrientValue"},"fat":{"$ref":"#/components/schemas/NutrientValue"},"fiber":{"$ref":"#/components/schemas/NutrientValue"},"micronutrients":{"type":"object","required":[],"properties":{},"patternProperties":{"":{"$ref":"#/components/schemas/NutrientValue"}},"propertyNames":{"$ref":"#/components/schemas/Slug"}},"protein":{"$ref":"#/components/schemas/NutrientValue"},"saturatedFat":{"$ref":"#/components/schemas/NutrientValue"},"sodium":{"$ref":"#/components/schemas/NutrientValue"},"source":{"type":"string","enum":["calculated","provided"]},"sugar":{"$ref":"#/components/schemas/NutrientValue"}},"additionalProperties":false},"Positive":{"type":"number","description":"a positive number","title":"positive","exclusiveMinimum":0},"NutrientValue":{"type":"object","required":["unit","value"],"properties":{"unit":{"$ref":"#/components/schemas/NutrientUnit"},"value":{"$ref":"#/components/schemas/NonNegative"}},"additionalProperties":false},"NutrientUnit":{"type":"string","enum":["g","kcal","mg","µg"]},"NonNegative":{"type":"number","description":"a non-negative number","title":"nonNegative","minimum":0},"Rating":{"type":"object","required":["count","value"],"properties":{"best":{"$ref":"#/components/schemas/Positive"},"count":{"$ref":"#/components/schemas/NonNegativeInt"},"reviewCount":{"$ref":"#/components/schemas/NonNegativeInt"},"value":{"$ref":"#/components/schemas/NonNegative"},"worst":{"$ref":"#/components/schemas/NonNegative"}},"additionalProperties":false},"Servings":{"type":"object","required":["original"],"properties":{"max":{"$ref":"#/components/schemas/Positive"},"original":{"$ref":"#/components/schemas/NonEmptyTrimmedString"},"quantity":{"$ref":"#/components/schemas/Positive"},"unit":{"$ref":"#/components/schemas/NonEmptyTrimmedString"}},"additionalProperties":false},"RecipeTimes":{"type":"object","required":[],"properties":{"cook":{"$ref":"#/components/schemas/Duration"},"inactive":{"$ref":"#/components/schemas/Duration"},"prep":{"$ref":"#/components/schemas/Duration"},"total":{"$ref":"#/components/schemas/Duration"}},"additionalProperties":false},"Date":{"type":"string","description":"a string to be decoded into a Date"},"RecipeIngredient":{"type":"object","required":["display","name","optional"],"properties":{"display":{"$ref":"#/components/schemas/NonEmptyTrimmedString"},"group":{"$ref":"#/components/schemas/NonEmptyTrimmedString"},"localName":{"$ref":"#/components/schemas/NonEmptyTrimmedString"},"ingredientId":{"type":"string","description":"a string matching the pattern ^[a-z0-9]+(-[a-z0-9]+)*$","pattern":"^[a-z0-9]+(-[a-z0-9]+)*$"},"name":{"$ref":"#/components/schemas/NonEmptyTrimmedString"},"note":{"$ref":"#/components/schemas/NonEmptyTrimmedString"},"optional":{"type":"boolean"},"preparation":{"$ref":"#/components/schemas/NonEmptyTrimmedString"},"quantity":{"$ref":"#/components/schemas/Quantity"},"size":{"$ref":"#/components/schemas/NonEmptyTrimmedString"}},"additionalProperties":false},"Quantity":{"type":"object","required":["value"],"properties":{"max":{"$ref":"#/components/schemas/NonNegative"},"unit":{"$ref":"#/components/schemas/Unit"},"value":{"$ref":"#/components/schemas/NonNegative"}},"additionalProperties":false},"Unit":{"type":"string","enum":["g","kg","lb","oz","cl","cup","dl","fl-oz","gallon","l","ml","pint","quart","tbsp","tsp","bag","bottle","box","bunch","can","clove","cube","dash","drop","handful","head","jar","leaf","package","piece","pinch","scoop","sheet","slice","sprig","stalk","stick"]},"RecipeText":{"type":"object","required":["ingredients","instructions"],"properties":{"ingredients":{"type":"array","items":{"type":"string"}},"instructions":{"type":"array","items":{"type":"string"}}},"additionalProperties":false,"description":"The recipe as lines of text: each ingredient's `display` line and each step's `text`, in order. A convenience for rendering; everything here is also in the structured fields."},"InvalidParameterError":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["message"],"properties":{"message":{"type":"string"}},"additionalProperties":false}},"additionalProperties":false},"ApiKeyDisabledError":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["message"],"properties":{"message":{"type":"string","enum":["This API key has been disabled."]}},"additionalProperties":false}},"additionalProperties":false},"ApiKeyExpiredError":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["message"],"properties":{"message":{"type":"string","enum":["This API key has expired."]}},"additionalProperties":false}},"additionalProperties":false},"ApiKeyRequiredError":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["message"],"properties":{"message":{"type":"string","enum":["An API key is required. Pass it as an Authorization: Bearer header."]}},"additionalProperties":false}},"additionalProperties":false},"InvalidApiKeyError":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["message"],"properties":{"message":{"type":"string","enum":["Invalid API key."]}},"additionalProperties":false}},"additionalProperties":false},"ApiKeyRateLimitedError":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["message"],"properties":{"message":{"type":"string","enum":["Rate limit exceeded for this API key. Try again later."]}},"additionalProperties":false}},"additionalProperties":false},"InternalError":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["message"],"properties":{"message":{"type":"string","enum":["Something went wrong. Please try again."]}},"additionalProperties":false}},"additionalProperties":false},"PopularRecipe":{"type":"object","required":["id","instructions","language","media","times","title","categories","courses","createdAt","cuisines","ingredients","tags","text","updatedAt","url","popularityScore"],"properties":{"id":{"type":"string"},"allergens":{"type":"array","items":{"$ref":"#/components/schemas/Allergen"}},"author":{"$ref":"#/components/schemas/Author"},"description":{"$ref":"#/components/schemas/NonEmptyTrimmedString"},"dietary":{"$ref":"#/components/schemas/Dietary"},"instructions":{"type":"array","minItems":1,"items":{"$ref":"#/components/schemas/RecipeInstruction"}},"language":{"$ref":"#/components/schemas/Language"},"media":{"type":"array","items":{"$ref":"#/components/schemas/RecipeMedia"}},"nutrition":{"$ref":"#/components/schemas/Nutrition"},"rating":{"$ref":"#/components/schemas/Rating"},"servings":{"$ref":"#/components/schemas/Servings"},"times":{"$ref":"#/components/schemas/RecipeTimes"},"title":{"$ref":"#/components/schemas/NonEmptyTrimmedString"},"categories":{"type":"array","items":{"type":"string"}},"courses":{"type":"array","items":{"type":"string"}},"createdAt":{"$ref":"#/components/schemas/Date"},"cuisines":{"type":"array","items":{"type":"string"}},"equipment":{"type":"array","items":{"type":"string"}},"ingredients":{"type":"array","minItems":1,"items":{"$ref":"#/components/schemas/RecipeIngredient"}},"tags":{"type":"array","items":{"type":"string"}},"techniques":{"type":"array","items":{"type":"string"}},"text":{"$ref":"#/components/schemas/RecipeText"},"updatedAt":{"$ref":"#/components/schemas/Date"},"url":{"type":"string"},"popularityScore":{"type":"number","description":"How popular this recipe is relative to the others in the response. Higher comes first."}},"additionalProperties":false,"description":"A recipe together with the score it was ranked by. Compare scores against each other rather than reading them as an absolute rating."},"Recipe":{"type":"object","required":["id","instructions","language","media","times","title","categories","courses","createdAt","cuisines","ingredients","tags","text","updatedAt","url"],"properties":{"id":{"type":"string"},"allergens":{"type":"array","items":{"$ref":"#/components/schemas/Allergen"}},"author":{"$ref":"#/components/schemas/Author"},"description":{"$ref":"#/components/schemas/NonEmptyTrimmedString"},"dietary":{"$ref":"#/components/schemas/Dietary"},"instructions":{"type":"array","minItems":1,"items":{"$ref":"#/components/schemas/RecipeInstruction"}},"language":{"$ref":"#/components/schemas/Language"},"media":{"type":"array","items":{"$ref":"#/components/schemas/RecipeMedia"}},"nutrition":{"$ref":"#/components/schemas/Nutrition"},"rating":{"$ref":"#/components/schemas/Rating"},"servings":{"$ref":"#/components/schemas/Servings"},"times":{"$ref":"#/components/schemas/RecipeTimes"},"title":{"$ref":"#/components/schemas/NonEmptyTrimmedString"},"categories":{"type":"array","items":{"type":"string"}},"courses":{"type":"array","items":{"type":"string"}},"createdAt":{"$ref":"#/components/schemas/Date"},"cuisines":{"type":"array","items":{"type":"string"}},"equipment":{"type":"array","items":{"type":"string"}},"ingredients":{"type":"array","minItems":1,"items":{"$ref":"#/components/schemas/RecipeIngredient"}},"tags":{"type":"array","items":{"type":"string"}},"techniques":{"type":"array","items":{"type":"string"}},"text":{"$ref":"#/components/schemas/RecipeText"},"updatedAt":{"$ref":"#/components/schemas/Date"},"url":{"type":"string"}},"additionalProperties":false,"description":"A recipe in the canonical model. Ingredients carry a canonical `ingredientId` once the recipe has been enriched, and a `display` line written in the recipe's own language. Times are in seconds. `cuisines`, `courses`, `categories`, allergens and units come from the closed lists served by /vocabularies and are the values the list filters take."},"NutritionTotals":{"type":"object","required":["perRecipe","perServing","servings"],"properties":{"perRecipe":{"$ref":"#/components/schemas/Nutrition"},"perServing":{"$ref":"#/components/schemas/Nutrition"},"servings":{"type":"number"}},"additionalProperties":false,"description":"The same nutrition told twice: for one serving, which is what recipes are compared on, and for the whole recipe, which is what the cook is making. Present only when the recipe carries nutrition and says how many servings it makes. Scaling the recipe changes the whole-recipe figures and leaves the per-serving ones alone."},"RecipeNotFoundError":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["message"],"properties":{"message":{"type":"string","enum":["Recipe not found."]}},"additionalProperties":false}},"additionalProperties":false},"SearchResult":{"type":"object","required":["id","instructions","language","media","times","title","categories","courses","createdAt","cuisines","ingredients","tags","text","updatedAt","url","score"],"properties":{"id":{"type":"string"},"allergens":{"type":"array","items":{"$ref":"#/components/schemas/Allergen"}},"author":{"$ref":"#/components/schemas/Author"},"description":{"$ref":"#/components/schemas/NonEmptyTrimmedString"},"dietary":{"$ref":"#/components/schemas/Dietary"},"instructions":{"type":"array","minItems":1,"items":{"$ref":"#/components/schemas/RecipeInstruction"}},"language":{"$ref":"#/components/schemas/Language"},"media":{"type":"array","items":{"$ref":"#/components/schemas/RecipeMedia"}},"nutrition":{"$ref":"#/components/schemas/Nutrition"},"rating":{"$ref":"#/components/schemas/Rating"},"servings":{"$ref":"#/components/schemas/Servings"},"times":{"$ref":"#/components/schemas/RecipeTimes"},"title":{"$ref":"#/components/schemas/NonEmptyTrimmedString"},"categories":{"type":"array","items":{"type":"string"}},"courses":{"type":"array","items":{"type":"string"}},"createdAt":{"$ref":"#/components/schemas/Date"},"cuisines":{"type":"array","items":{"type":"string"}},"equipment":{"type":"array","items":{"type":"string"}},"ingredients":{"type":"array","minItems":1,"items":{"$ref":"#/components/schemas/RecipeIngredient"}},"tags":{"type":"array","items":{"type":"string"}},"techniques":{"type":"array","items":{"type":"string"}},"text":{"$ref":"#/components/schemas/RecipeText"},"updatedAt":{"$ref":"#/components/schemas/Date"},"url":{"type":"string"},"score":{"type":"number","description":"How well this recipe matches the query, relative to the others in the response. Higher comes first."}},"additionalProperties":false,"description":"A matching recipe and its relevance score. When the \"fields\" query parameter is used, only the requested fields and \"id\" are present."},"SearchQueryRequiredError":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["message"],"properties":{"message":{"type":"string","enum":["The query parameter is required."]}},"additionalProperties":false}},"additionalProperties":false},"ShoppingItem":{"type":"object","required":["category","display","name","recipeIds"],"properties":{"category":{"type":"string","enum":["bakery","dairy","drinks","frozen","meat","other","pantry","produce","seafood","spices"],"description":"The aisle to find it in."},"display":{"type":"string","description":"The line as a reader would write it, such as \"6 onion\"."},"name":{"type":"string"},"quantity":{"$ref":"#/components/schemas/Quantity"},"recipeIds":{"type":"array","items":{"type":"string"},"description":"The recipes that asked for it."}},"additionalProperties":false},"Ingredient":{"type":"object","required":["aliases","id","names","recipeCount"],"properties":{"aliases":{"type":"object","required":[],"properties":{},"additionalProperties":{"type":"array","items":{"type":"string"}}},"id":{"type":"string"},"names":{"type":"object","required":[],"properties":{},"additionalProperties":{"type":"string"}},"recipeCount":{"type":"number"}},"additionalProperties":false,"description":"A canonical ingredient. `names` holds the English name; `aliases` holds every spelling seen, per language."},"PageStatusCounts":{"type":"object","required":["discovered","extracted","extracting","failed","fetched","fetching"],"properties":{"discovered":{"type":"number"},"extracted":{"type":"number"},"extracting":{"type":"number"},"failed":{"type":"number"},"fetched":{"type":"number"},"fetching":{"type":"number"}},"additionalProperties":false},"Substitution":{"type":"object","required":["ingredient","ratio"],"properties":{"caution":{"type":"string","description":"What this swap cannot be used for. Present when the substitute changes the dish in a way the cook has to know about."},"ingredient":{"type":"string"},"note":{"type":"string","description":"How to prepare or handle the substitute."},"ratio":{"type":"number","description":"How much substitute to use for one unit of the original: 0.75 means three quarters as much."}},"additionalProperties":false}},"securitySchemes":{"BearerAuth":{"scheme":"bearer","type":"http"}}},"security":[{},{"BearerAuth":[]}],"tags":[{"name":"health"},{"name":"pantry"},{"name":"popular"},{"name":"recipes"},{"name":"root"},{"name":"search"},{"name":"shoppingList"},{"name":"ingredients"},{"name":"status"},{"name":"substitutions"}],"servers":[{"description":"Production.","url":"https://api.tinyplates.dev"},{"description":"Local development.","url":"http://localhost:6891"}]}