{"openapi":"3.1.0","info":{"title":"Iron Tofu API","version":"0.1.0","description":"Read-only access to the vegan recipe collection. No authentication is needed."},"servers":[{"url":"https://irontofu.com/api/v1"}],"paths":{"/recipes":{"get":{"operationId":"listRecipes","summary":"Search and list recipes","parameters":[{"name":"q","in":"query","description":"Free-text search over title, description, ingredients, tags and cuisine.","schema":{"type":"string"}},{"name":"course","in":"query","schema":{"type":"string","enum":["breakfast","main","soup","salad","side","snack","dessert","drink","basic"]}},{"name":"cuisine","in":"query","description":"Cuisine name, case-insensitive.","schema":{"type":"string"}},{"name":"difficulty","in":"query","schema":{"type":"string","enum":["easy","medium","hard"]}},{"name":"max_minutes","in":"query","description":"Longest acceptable total time (prep + cook) in minutes.","schema":{"type":"integer","minimum":1}},{"name":"tag","in":"query","description":"Only recipes carrying every listed tag. Repeat the parameter or separate values with commas.","schema":{"type":"array","items":{"type":"string"}},"style":"form","explode":false},{"name":"ingredient","in":"query","description":"Only recipes using every listed ingredient. Repeat the parameter or separate values with commas.","schema":{"type":"array","items":{"type":"string"}},"style":"form","explode":false},{"name":"exclude","in":"query","description":"Only recipes using none of the listed ingredients. Repeat the parameter or separate values with commas.","schema":{"type":"array","items":{"type":"string"}},"style":"form","explode":false},{"name":"sort","in":"query","description":"Defaults to \"relevance\" when searching and \"newest\" otherwise.","schema":{"type":"string","enum":["relevance","newest","quickest","protein","title"]}},{"name":"page","in":"query","schema":{"type":"integer","minimum":1,"default":1}},{"name":"per_page","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":20}}],"responses":{"200":{"description":"A page of recipe summaries.","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/RecipeSummary"}},"meta":{"$ref":"#/components/schemas/PageMeta"}}}}}},"400":{"description":"A parameter is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/recipes/random":{"get":{"operationId":"getRandomRecipe","summary":"Get a random recipe, optionally limited by the same filters as the list","parameters":[{"name":"q","in":"query","description":"Free-text search over title, description, ingredients, tags and cuisine.","schema":{"type":"string"}},{"name":"course","in":"query","schema":{"type":"string","enum":["breakfast","main","soup","salad","side","snack","dessert","drink","basic"]}},{"name":"cuisine","in":"query","description":"Cuisine name, case-insensitive.","schema":{"type":"string"}},{"name":"difficulty","in":"query","schema":{"type":"string","enum":["easy","medium","hard"]}},{"name":"max_minutes","in":"query","description":"Longest acceptable total time (prep + cook) in minutes.","schema":{"type":"integer","minimum":1}},{"name":"tag","in":"query","description":"Only recipes carrying every listed tag. Repeat the parameter or separate values with commas.","schema":{"type":"array","items":{"type":"string"}},"style":"form","explode":false},{"name":"ingredient","in":"query","description":"Only recipes using every listed ingredient. Repeat the parameter or separate values with commas.","schema":{"type":"array","items":{"type":"string"}},"style":"form","explode":false},{"name":"exclude","in":"query","description":"Only recipes using none of the listed ingredients. Repeat the parameter or separate values with commas.","schema":{"type":"array","items":{"type":"string"}},"style":"form","explode":false},{"name":"servings","in":"query","description":"Scale ingredient quantities to this number of servings.","schema":{"type":"integer","minimum":1,"maximum":100}}],"responses":{"200":{"description":"A full recipe.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecipeResponse"}}}},"400":{"description":"A parameter is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No recipe matches the filters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/recipes/{slug}":{"get":{"operationId":"getRecipe","summary":"Get one recipe","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}},{"name":"servings","in":"query","description":"Scale ingredient quantities to this number of servings.","schema":{"type":"integer","minimum":1,"maximum":100}}],"responses":{"200":{"description":"A full recipe.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecipeResponse"}}}},"400":{"description":"A parameter is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No recipe has that slug.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/facets":{"get":{"operationId":"getFacets","summary":"List the courses, cuisines, difficulties and tags in use, with recipe counts","responses":{"200":{"description":"Filter values and how many recipes each one matches.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["courses","cuisines","difficulties","tags"],"properties":{"courses":{"type":"array","items":{"$ref":"#/components/schemas/FacetValue"}},"cuisines":{"type":"array","items":{"$ref":"#/components/schemas/FacetValue"}},"difficulties":{"type":"array","items":{"$ref":"#/components/schemas/FacetValue"}},"tags":{"type":"array","items":{"$ref":"#/components/schemas/FacetValue"}}}}}}}}}}}}},"components":{"schemas":{"RecipeSummary":{"type":"object","required":["slug","title","description","course","cuisine","tags","difficulty","prep_minutes","cook_minutes","total_minutes","servings","added","url","api_url","nutrition"],"properties":{"slug":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"course":{"type":"string","enum":["breakfast","main","soup","salad","side","snack","dessert","drink","basic"]},"cuisine":{"type":["string","null"]},"tags":{"type":"array","items":{"type":"string"}},"difficulty":{"type":"string","enum":["easy","medium","hard"]},"prep_minutes":{"type":"integer"},"cook_minutes":{"type":"integer"},"total_minutes":{"type":"integer"},"servings":{"type":"integer"},"added":{"type":"string","format":"date"},"url":{"type":"string","format":"uri","description":"The recipe's page on the site."},"api_url":{"type":"string","format":"uri"},"nutrition":{"$ref":"#/components/schemas/Nutrition"}}},"Recipe":{"type":"object","required":["slug","title","description","course","cuisine","tags","difficulty","prep_minutes","cook_minutes","total_minutes","servings","added","url","api_url","nutrition","ingredients","steps","notes"],"properties":{"slug":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"course":{"type":"string","enum":["breakfast","main","soup","salad","side","snack","dessert","drink","basic"]},"cuisine":{"type":["string","null"]},"tags":{"type":"array","items":{"type":"string"}},"difficulty":{"type":"string","enum":["easy","medium","hard"]},"prep_minutes":{"type":"integer"},"cook_minutes":{"type":"integer"},"total_minutes":{"type":"integer"},"servings":{"type":"integer"},"added":{"type":"string","format":"date"},"url":{"type":"string","format":"uri","description":"The recipe's page on the site."},"api_url":{"type":"string","format":"uri"},"nutrition":{"$ref":"#/components/schemas/Nutrition"},"ingredients":{"type":"array","items":{"$ref":"#/components/schemas/Ingredient"}},"steps":{"type":"array","items":{"type":"string"}},"notes":{"type":"array","items":{"type":"string"}}}},"Nutrition":{"type":"object","description":"Estimated nutrition for one serving, stated by the recipe or worked out from its ingredients.","required":["kcal","protein_g","carbs_g","fat_g","fibre_g"],"properties":{"kcal":{"type":"number"},"protein_g":{"type":"number"},"carbs_g":{"type":"number","description":"Total carbohydrate, fibre included."},"fat_g":{"type":"number"},"fibre_g":{"type":["number","null"]}}},"Ingredient":{"type":"object","required":["group","quantity","quantity_max","unit","name","note","metric","text"],"properties":{"group":{"type":["string","null"],"description":"Heading the ingredient sits under, such as \"Sauce\"."},"quantity":{"type":["number","null"]},"quantity_max":{"type":["number","null"],"description":"Upper bound when the quantity is a range."},"unit":{"type":["string","null"]},"name":{"type":"string"},"note":{"type":["string","null"],"description":"Preparation or other detail, such as \"finely chopped\"."},"metric":{"oneOf":[{"$ref":"#/components/schemas/Metric"},{"type":"null"}],"description":"The same amount in grams or millilitres. Null when the ingredient is already metric or has no quantity."},"text":{"type":"string","description":"The whole ingredient as one display line."}}},"Metric":{"type":"object","required":["quantity","quantity_max","unit","approximate"],"properties":{"quantity":{"type":"number"},"quantity_max":{"type":["number","null"]},"unit":{"type":"string","enum":["g","ml"]},"approximate":{"type":"boolean","description":"True when based on a typical size, such as one onion."}}},"RecipeResponse":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/Recipe"}}},"PageMeta":{"type":"object","required":["total","page","per_page","pages"],"properties":{"total":{"type":"integer"},"page":{"type":"integer"},"per_page":{"type":"integer"},"pages":{"type":"integer"}}},"FacetValue":{"type":"object","required":["value","count"],"properties":{"value":{"type":"string"},"count":{"type":"integer"}}},"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}