docs: add OpenAPI documentation
This commit is contained in:
6
openapi/examples/AccountIn.yaml
Normal file
6
openapi/examples/AccountIn.yaml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
summary: Account registration
|
||||||
|
value:
|
||||||
|
{
|
||||||
|
"email": "ada@example.com",
|
||||||
|
"password": "FBR5h0L1ENA3edctgDIEnxSvFdR0",
|
||||||
|
}
|
||||||
45
openapi/examples/DipsOut.yaml
Normal file
45
openapi/examples/DipsOut.yaml
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
summary: Dip category search
|
||||||
|
value:
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": 3,
|
||||||
|
"name": "Muhammara",
|
||||||
|
"description": "Muhammara is a vibrant and flavorful dip or spread from the Middle East, particularly popular in Syrian and Turkish cuisine. It's made primarily from roasted red bell peppers, walnuts, breadcrumbs, and pomegranate molasses.",
|
||||||
|
"changedAt": "2025-08-08T16:24:44.673034Z",
|
||||||
|
"categories": [ "Dip" ],
|
||||||
|
"ingredients":
|
||||||
|
[
|
||||||
|
"Pomegranate molasses",
|
||||||
|
"Red bell peppers",
|
||||||
|
"Bread crumbs",
|
||||||
|
"Cumin",
|
||||||
|
"Chili flakes",
|
||||||
|
"Garlic",
|
||||||
|
"Walnuts",
|
||||||
|
"Lemon juice",
|
||||||
|
],
|
||||||
|
"steps":
|
||||||
|
[
|
||||||
|
"Roast whole bell peppers in an oven or air fryer and wait until blackened on the outside.",
|
||||||
|
"Put the peppers in a bowl cover them with to let steam and cool down",
|
||||||
|
"Remove core seeds, and skins",
|
||||||
|
"Combine all the ingredients in a food processor.",
|
||||||
|
"Process until mostly smooth but with a little texture remaining.",
|
||||||
|
"Taste and adjust flavor as needed (lemon for acidity, pomegranate molasses for sweetness)",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"name": "Hummus",
|
||||||
|
"description": "Hummus, is a Levantine dip, spread, or savory dish made from cooked, mashed chickpeas blended with tahini, lemon juice, and garlic.",
|
||||||
|
"changedAt": "2025-08-08T16:24:44.579213Z",
|
||||||
|
"categories": [ "Dip" ],
|
||||||
|
"ingredients": [ "Chickpeas", "Tahini", "Lemon juice", "Garlic" ],
|
||||||
|
"steps":
|
||||||
|
[
|
||||||
|
"Combine chickpeas, tahini, lemon juice, garlic, and salt in a food processor.",
|
||||||
|
"Blend until smooth, slowly adding cold water until you reach a creamy consistency.",
|
||||||
|
"Taste and adjust seasoning if needed.",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]
|
||||||
15
openapi/examples/HummusV1In.yaml
Normal file
15
openapi/examples/HummusV1In.yaml
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
summary: Hummus recipe
|
||||||
|
value:
|
||||||
|
{
|
||||||
|
"name": "Hummus",
|
||||||
|
"description": "Hummus, is a Levantine dip, spread, or savory dish made from cooked, mashed chickpeas blended with tahini, lemon juice, and garlic.",
|
||||||
|
"categories": [ "Dip", "Spread" ],
|
||||||
|
"ingredients":
|
||||||
|
[ "Chickpeas", "Tahini", "Olive oil", "Lemon juice", "Garlic" ],
|
||||||
|
"steps":
|
||||||
|
[
|
||||||
|
"Combine chickpeas, tahini, olive oil, lemon juice, garlic, and salt in a food processor.",
|
||||||
|
"Blend until smooth, slowly adding cold water until you reach a creamy consistency.",
|
||||||
|
"Taste and adjust seasoning if needed.",
|
||||||
|
],
|
||||||
|
}
|
||||||
17
openapi/examples/HummusV1Out.yaml
Normal file
17
openapi/examples/HummusV1Out.yaml
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
summary: Hummus recipe
|
||||||
|
value:
|
||||||
|
{
|
||||||
|
"id": 1729,
|
||||||
|
"name": "Hummus",
|
||||||
|
"description": "Hummus, is a Levantine dip, spread, or savory dish made from cooked, mashed chickpeas blended with tahini, lemon juice, and garlic.",
|
||||||
|
"changedAt": "2025-08-08T15:35:10.294411Z",
|
||||||
|
"categories": [ "Dip", "Spread" ],
|
||||||
|
"ingredients":
|
||||||
|
[ "Chickpeas", "Tahini", "Olive oil", "Lemon juice", "Garlic" ],
|
||||||
|
"steps":
|
||||||
|
[
|
||||||
|
"Combine chickpeas, tahini, olive oil, lemon juice, garlic, and salt in a food processor.",
|
||||||
|
"Blend until smooth, slowly adding cold water until you reach a creamy consistency.",
|
||||||
|
"Taste and adjust seasoning if needed.",
|
||||||
|
],
|
||||||
|
}
|
||||||
14
openapi/examples/HummusV2In.yaml
Normal file
14
openapi/examples/HummusV2In.yaml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
summary: Hummus recipe update
|
||||||
|
value:
|
||||||
|
{
|
||||||
|
"name": "Hummus",
|
||||||
|
"description": "Hummus, is a Levantine dip, spread, or savory dish made from cooked, mashed chickpeas blended with tahini, lemon juice, and garlic.",
|
||||||
|
"categories": [ "Dip", "Spread" ],
|
||||||
|
"ingredients": [ "Chickpeas", "Tahini", "Lemon juice", "Garlic" ],
|
||||||
|
"steps":
|
||||||
|
[
|
||||||
|
"Combine chickpeas, tahini, lemon juice, garlic, and salt in a food processor.",
|
||||||
|
"Blend until smooth, slowly adding cold water until you reach a creamy consistency.",
|
||||||
|
"Taste and adjust seasoning if needed.",
|
||||||
|
],
|
||||||
|
}
|
||||||
16
openapi/examples/HummusV2Out.yaml
Normal file
16
openapi/examples/HummusV2Out.yaml
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
summary: Hummus recipe update
|
||||||
|
value:
|
||||||
|
{
|
||||||
|
"id": 1729,
|
||||||
|
"name": "Hummus",
|
||||||
|
"description": "Hummus, is a Levantine dip, spread, or savory dish made from cooked, mashed chickpeas blended with tahini, lemon juice, and garlic.",
|
||||||
|
"changedAt": "2025-08-09T12:48:32.134821Z",
|
||||||
|
"categories": [ "Dip", "Spread" ],
|
||||||
|
"ingredients": [ "Chickpeas", "Tahini", "Lemon juice", "Garlic" ],
|
||||||
|
"steps":
|
||||||
|
[
|
||||||
|
"Combine chickpeas, tahini, lemon juice, garlic, and salt in a food processor.",
|
||||||
|
"Blend until smooth, slowly adding cold water until you reach a creamy consistency.",
|
||||||
|
"Taste and adjust seasoning if needed.",
|
||||||
|
],
|
||||||
|
}
|
||||||
24
openapi/index.html
Normal file
24
openapi/index.html
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Recipe API Reference</title>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="app"></div>
|
||||||
|
|
||||||
|
<!-- Load the Script -->
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/@scalar/api-reference"></script>
|
||||||
|
|
||||||
|
<!-- Initialize the Scalar API Reference -->
|
||||||
|
<script>
|
||||||
|
Scalar.createApiReference("#app", {
|
||||||
|
// The URL of the OpenAPI/Swagger document
|
||||||
|
url: "/recipe-openapi.yaml",
|
||||||
|
hideTestRequestButton: true,
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
1408
openapi/openapi-2025-02-13.schema.json
Normal file
1408
openapi/openapi-2025-02-13.schema.json
Normal file
File diff suppressed because it is too large
Load Diff
6
openapi/parameters/{recipeId}.yaml
Normal file
6
openapi/parameters/{recipeId}.yaml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
name: "recipeId"
|
||||||
|
in: "path"
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
$ref: "../schemas/Id.yaml"
|
||||||
|
description: "Unique identifier of the recipe"
|
||||||
23
openapi/paths/account-register.yaml
Normal file
23
openapi/paths/account-register.yaml
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
post:
|
||||||
|
tags:
|
||||||
|
- Account
|
||||||
|
summary: "Register an account"
|
||||||
|
operationId: "RegisterAccount"
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "../schemas/Account.yaml"
|
||||||
|
examples:
|
||||||
|
accountIn:
|
||||||
|
$ref: "../examples/AccountIn.yaml"
|
||||||
|
required: true
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: "OK"
|
||||||
|
"400":
|
||||||
|
description: "Bad Request"
|
||||||
|
content:
|
||||||
|
"application/json":
|
||||||
|
schema:
|
||||||
|
$ref: "../schemas/ProblemDetail.yaml"
|
||||||
0
openapi/paths/recipe-api-bundled.yaml
Normal file
0
openapi/paths/recipe-api-bundled.yaml
Normal file
50
openapi/paths/recipe-new.yaml
Normal file
50
openapi/paths/recipe-new.yaml
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
post:
|
||||||
|
tags:
|
||||||
|
- Recipe
|
||||||
|
summary: "Add a recipe"
|
||||||
|
operationId: "addRecipe"
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "../schemas/Recipe.yaml"
|
||||||
|
examples:
|
||||||
|
recipeIn:
|
||||||
|
$ref: "../examples/HummusV1In.yaml"
|
||||||
|
required: true
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: OK
|
||||||
|
content:
|
||||||
|
"application/json":
|
||||||
|
schema:
|
||||||
|
$ref: "../schemas/Recipe.yaml"
|
||||||
|
examples:
|
||||||
|
recipeOut:
|
||||||
|
$ref: "../examples/HummusV1Out.yaml"
|
||||||
|
400:
|
||||||
|
description: Bad Request
|
||||||
|
content:
|
||||||
|
"application/json":
|
||||||
|
schema:
|
||||||
|
$ref: "../schemas/ProblemDetail.yaml"
|
||||||
|
401:
|
||||||
|
description: Unauthorized
|
||||||
|
content:
|
||||||
|
"application/json":
|
||||||
|
schema:
|
||||||
|
$ref: "../schemas/ProblemDetail.yaml"
|
||||||
|
403:
|
||||||
|
description: Forbidden
|
||||||
|
content:
|
||||||
|
"application/json":
|
||||||
|
schema:
|
||||||
|
$ref: "../schemas/ProblemDetail.yaml"
|
||||||
|
404:
|
||||||
|
description: Not Found
|
||||||
|
content:
|
||||||
|
"application/json":
|
||||||
|
schema:
|
||||||
|
$ref: "../schemas/ProblemDetail.yaml"
|
||||||
|
security:
|
||||||
|
- httpBasic: [ ]
|
||||||
59
openapi/paths/recipe-search.yaml
Normal file
59
openapi/paths/recipe-search.yaml
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
get:
|
||||||
|
tags:
|
||||||
|
- Recipe
|
||||||
|
summary: "Find recipes"
|
||||||
|
operationId: "FindRecipes"
|
||||||
|
parameters:
|
||||||
|
- name: "category"
|
||||||
|
in: "query"
|
||||||
|
required: false
|
||||||
|
schema:
|
||||||
|
type: "string"
|
||||||
|
description: "Category name filter (equals, ignores case)"
|
||||||
|
- name: "recipe"
|
||||||
|
in: "query"
|
||||||
|
required: false
|
||||||
|
schema:
|
||||||
|
type: "string"
|
||||||
|
description: "Recipe name filter (contains, ignores case)"
|
||||||
|
- name: "limit"
|
||||||
|
in: "query"
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: "integer"
|
||||||
|
format: "int64"
|
||||||
|
minimum: 1
|
||||||
|
maximum: 100
|
||||||
|
description: "Maximum number of recipes to return"
|
||||||
|
- name: "offset"
|
||||||
|
in: "query"
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: "integer"
|
||||||
|
format: "int64"
|
||||||
|
minimum: 0
|
||||||
|
description: "Index into result set from where recipes will start to be returned"
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: OK
|
||||||
|
content:
|
||||||
|
"application/json":
|
||||||
|
schema:
|
||||||
|
type: "array"
|
||||||
|
items:
|
||||||
|
$ref: "../schemas/Recipe.yaml"
|
||||||
|
examples:
|
||||||
|
dipsOut:
|
||||||
|
$ref: "../examples/DipsOut.yaml"
|
||||||
|
400:
|
||||||
|
description: Bad Request
|
||||||
|
content:
|
||||||
|
"application/json":
|
||||||
|
schema:
|
||||||
|
$ref: "../schemas/ProblemDetail.yaml"
|
||||||
|
404:
|
||||||
|
description: Not Found
|
||||||
|
content:
|
||||||
|
"application/json":
|
||||||
|
schema:
|
||||||
|
$ref: "../schemas/ProblemDetail.yaml"
|
||||||
117
openapi/paths/recipe-{recipeId}.yaml
Normal file
117
openapi/paths/recipe-{recipeId}.yaml
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
get:
|
||||||
|
tags:
|
||||||
|
- Recipe
|
||||||
|
summary: "Get a recipe"
|
||||||
|
operationId: "GetRecipe"
|
||||||
|
parameters:
|
||||||
|
- $ref: "../parameters/{recipeId}.yaml"
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: OK
|
||||||
|
content:
|
||||||
|
"application/json":
|
||||||
|
schema:
|
||||||
|
$ref: "../schemas/Recipe.yaml"
|
||||||
|
examples:
|
||||||
|
recipeOut:
|
||||||
|
$ref: "../examples/HummusV1Out.yaml"
|
||||||
|
400:
|
||||||
|
description: Bad Request
|
||||||
|
content:
|
||||||
|
"application/json":
|
||||||
|
schema:
|
||||||
|
$ref: "../schemas/ProblemDetail.yaml"
|
||||||
|
404:
|
||||||
|
description: Not Found
|
||||||
|
content:
|
||||||
|
"application/json":
|
||||||
|
schema:
|
||||||
|
$ref: "../schemas/ProblemDetail.yaml"
|
||||||
|
put:
|
||||||
|
tags:
|
||||||
|
- Recipe
|
||||||
|
summary: "Update a recipe"
|
||||||
|
operationId: "UpdateRecipe"
|
||||||
|
parameters:
|
||||||
|
- $ref: "../parameters/{recipeId}.yaml"
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "../schemas/Recipe.yaml"
|
||||||
|
examples:
|
||||||
|
recipeIn:
|
||||||
|
$ref: "../examples/HummusV2In.yaml"
|
||||||
|
required: true
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: OK
|
||||||
|
content:
|
||||||
|
"application/json":
|
||||||
|
schema:
|
||||||
|
$ref: "../schemas/Recipe.yaml"
|
||||||
|
examples:
|
||||||
|
recipeOut:
|
||||||
|
$ref: "../examples/HummusV2Out.yaml"
|
||||||
|
400:
|
||||||
|
description: Bad Request
|
||||||
|
content:
|
||||||
|
"application/json":
|
||||||
|
schema:
|
||||||
|
$ref: "../schemas/ProblemDetail.yaml"
|
||||||
|
401:
|
||||||
|
description: Unauthorized
|
||||||
|
content:
|
||||||
|
"application/json":
|
||||||
|
schema:
|
||||||
|
$ref: "../schemas/ProblemDetail.yaml"
|
||||||
|
403:
|
||||||
|
description: Forbidden
|
||||||
|
content:
|
||||||
|
"application/json":
|
||||||
|
schema:
|
||||||
|
$ref: "../schemas/ProblemDetail.yaml"
|
||||||
|
404:
|
||||||
|
description: Not Found
|
||||||
|
content:
|
||||||
|
"application/json":
|
||||||
|
schema:
|
||||||
|
$ref: "../schemas/ProblemDetail.yaml"
|
||||||
|
security:
|
||||||
|
- httpBasic: [ ]
|
||||||
|
delete:
|
||||||
|
tags:
|
||||||
|
- Recipe
|
||||||
|
summary: "Remove a recipe"
|
||||||
|
operationId: "RemoveRecipe"
|
||||||
|
parameters:
|
||||||
|
- $ref: "../parameters/{recipeId}.yaml"
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: OK
|
||||||
|
400:
|
||||||
|
description: Bad Request
|
||||||
|
content:
|
||||||
|
"application/json":
|
||||||
|
schema:
|
||||||
|
$ref: "../schemas/ProblemDetail.yaml"
|
||||||
|
401:
|
||||||
|
description: Unauthorized
|
||||||
|
content:
|
||||||
|
"application/json":
|
||||||
|
schema:
|
||||||
|
$ref: "../schemas/ProblemDetail.yaml"
|
||||||
|
403:
|
||||||
|
description: Forbidden
|
||||||
|
content:
|
||||||
|
"application/json":
|
||||||
|
schema:
|
||||||
|
$ref: "../schemas/ProblemDetail.yaml"
|
||||||
|
404:
|
||||||
|
description: Not Found
|
||||||
|
content:
|
||||||
|
"application/json":
|
||||||
|
schema:
|
||||||
|
$ref: "../schemas/ProblemDetail.yaml"
|
||||||
|
security:
|
||||||
|
- httpBasic: [ ]
|
||||||
497
openapi/recipe-api-bundled.yaml
Normal file
497
openapi/recipe-api-bundled.yaml
Normal file
@@ -0,0 +1,497 @@
|
|||||||
|
openapi: 3.1.1
|
||||||
|
info:
|
||||||
|
title: Recipe API
|
||||||
|
description: Programmatic access to a database of recipes. Users can publish and find recipes.
|
||||||
|
version: 1.0.0
|
||||||
|
license:
|
||||||
|
name: MIT
|
||||||
|
url: https://opensource.org/licenses/MIT
|
||||||
|
servers:
|
||||||
|
- url: https://api.recipes.bitfield.eu/v1
|
||||||
|
security: []
|
||||||
|
tags:
|
||||||
|
- name: Recipe
|
||||||
|
description: Steps and ingredients for preparing a dish
|
||||||
|
- name: Account
|
||||||
|
description: Access to protected operations
|
||||||
|
paths:
|
||||||
|
/recipe/new:
|
||||||
|
post:
|
||||||
|
tags:
|
||||||
|
- Recipe
|
||||||
|
summary: Add a recipe
|
||||||
|
operationId: addRecipe
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Recipe'
|
||||||
|
examples:
|
||||||
|
recipeIn:
|
||||||
|
$ref: '#/components/examples/HummusV1In'
|
||||||
|
required: true
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: OK
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Recipe'
|
||||||
|
examples:
|
||||||
|
recipeOut:
|
||||||
|
$ref: '#/components/examples/HummusV1Out'
|
||||||
|
'400':
|
||||||
|
description: Bad Request
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ProblemDetail'
|
||||||
|
'401':
|
||||||
|
description: Unauthorized
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ProblemDetail'
|
||||||
|
'403':
|
||||||
|
description: Forbidden
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ProblemDetail'
|
||||||
|
'404':
|
||||||
|
description: Not Found
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ProblemDetail'
|
||||||
|
security:
|
||||||
|
- httpBasic: []
|
||||||
|
/recipe/search:
|
||||||
|
get:
|
||||||
|
tags:
|
||||||
|
- Recipe
|
||||||
|
summary: Find recipes
|
||||||
|
operationId: FindRecipes
|
||||||
|
parameters:
|
||||||
|
- name: category
|
||||||
|
in: query
|
||||||
|
required: false
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
description: Category name filter (equals, ignores case)
|
||||||
|
- name: recipe
|
||||||
|
in: query
|
||||||
|
required: false
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
description: Recipe name filter (contains, ignores case)
|
||||||
|
- name: limit
|
||||||
|
in: query
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
minimum: 1
|
||||||
|
maximum: 100
|
||||||
|
description: Maximum number of recipes to return
|
||||||
|
- name: offset
|
||||||
|
in: query
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
minimum: 0
|
||||||
|
description: Index into result set from where recipes will start to be returned
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: OK
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/Recipe'
|
||||||
|
examples:
|
||||||
|
dipsOut:
|
||||||
|
$ref: '#/components/examples/DipsOut'
|
||||||
|
'400':
|
||||||
|
description: Bad Request
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ProblemDetail'
|
||||||
|
'404':
|
||||||
|
description: Not Found
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ProblemDetail'
|
||||||
|
/recipe/{recipeId}:
|
||||||
|
get:
|
||||||
|
tags:
|
||||||
|
- Recipe
|
||||||
|
summary: Get a recipe
|
||||||
|
operationId: GetRecipe
|
||||||
|
parameters:
|
||||||
|
- $ref: '#/components/parameters/{recipeId}'
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: OK
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Recipe'
|
||||||
|
examples:
|
||||||
|
recipeOut:
|
||||||
|
$ref: '#/components/examples/HummusV1Out'
|
||||||
|
'400':
|
||||||
|
description: Bad Request
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ProblemDetail'
|
||||||
|
'404':
|
||||||
|
description: Not Found
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ProblemDetail'
|
||||||
|
put:
|
||||||
|
tags:
|
||||||
|
- Recipe
|
||||||
|
summary: Update a recipe
|
||||||
|
operationId: UpdateRecipe
|
||||||
|
parameters:
|
||||||
|
- $ref: '#/components/parameters/{recipeId}'
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Recipe'
|
||||||
|
examples:
|
||||||
|
recipeIn:
|
||||||
|
$ref: '#/components/examples/HummusV2In'
|
||||||
|
required: true
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: OK
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Recipe'
|
||||||
|
examples:
|
||||||
|
recipeOut:
|
||||||
|
$ref: '#/components/examples/HummusV2Out'
|
||||||
|
'400':
|
||||||
|
description: Bad Request
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ProblemDetail'
|
||||||
|
'401':
|
||||||
|
description: Unauthorized
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ProblemDetail'
|
||||||
|
'403':
|
||||||
|
description: Forbidden
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ProblemDetail'
|
||||||
|
'404':
|
||||||
|
description: Not Found
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ProblemDetail'
|
||||||
|
security:
|
||||||
|
- httpBasic: []
|
||||||
|
delete:
|
||||||
|
tags:
|
||||||
|
- Recipe
|
||||||
|
summary: Remove a recipe
|
||||||
|
operationId: RemoveRecipe
|
||||||
|
parameters:
|
||||||
|
- $ref: '#/components/parameters/{recipeId}'
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: OK
|
||||||
|
'400':
|
||||||
|
description: Bad Request
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ProblemDetail'
|
||||||
|
'401':
|
||||||
|
description: Unauthorized
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ProblemDetail'
|
||||||
|
'403':
|
||||||
|
description: Forbidden
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ProblemDetail'
|
||||||
|
'404':
|
||||||
|
description: Not Found
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ProblemDetail'
|
||||||
|
security:
|
||||||
|
- httpBasic: []
|
||||||
|
/account/register:
|
||||||
|
post:
|
||||||
|
tags:
|
||||||
|
- Account
|
||||||
|
summary: Register an account
|
||||||
|
operationId: RegisterAccount
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Account'
|
||||||
|
examples:
|
||||||
|
accountIn:
|
||||||
|
$ref: '#/components/examples/AccountIn'
|
||||||
|
required: true
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: OK
|
||||||
|
'400':
|
||||||
|
description: Bad Request
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ProblemDetail'
|
||||||
|
components:
|
||||||
|
securitySchemes:
|
||||||
|
httpBasic:
|
||||||
|
type: http
|
||||||
|
scheme: basic
|
||||||
|
schemas:
|
||||||
|
Id:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
NonBlankString:
|
||||||
|
type: string
|
||||||
|
pattern: ^(.|\s)*\S(.|\s)*$
|
||||||
|
DateTime:
|
||||||
|
type: string
|
||||||
|
format: date-time
|
||||||
|
Recipe:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
$ref: '#/components/schemas/Id'
|
||||||
|
readOnly: true
|
||||||
|
description: Unique identifier of the recipe
|
||||||
|
name:
|
||||||
|
$ref: '#/components/schemas/NonBlankString'
|
||||||
|
description: Name
|
||||||
|
description:
|
||||||
|
$ref: '#/components/schemas/NonBlankString'
|
||||||
|
description: Description
|
||||||
|
changedAt:
|
||||||
|
$ref: '#/components/schemas/DateTime'
|
||||||
|
readOnly: true
|
||||||
|
description: Last point in time when the recipe was changed
|
||||||
|
categories:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/NonBlankString'
|
||||||
|
description: Category names
|
||||||
|
ingredients:
|
||||||
|
type: array
|
||||||
|
minItems: 1
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/NonBlankString'
|
||||||
|
description: Step descriptions
|
||||||
|
steps:
|
||||||
|
type: array
|
||||||
|
minItems: 1
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/NonBlankString'
|
||||||
|
description: Ingredient names
|
||||||
|
required:
|
||||||
|
- name
|
||||||
|
- description
|
||||||
|
- categories
|
||||||
|
- ingredients
|
||||||
|
- steps
|
||||||
|
ProblemDetail:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
type:
|
||||||
|
type: string
|
||||||
|
description: URI reference that identifies the problem type.
|
||||||
|
format: uri
|
||||||
|
status:
|
||||||
|
type: integer
|
||||||
|
description: HTTP status code generated by the origin server for this occurrence of the problem.
|
||||||
|
format: int32
|
||||||
|
title:
|
||||||
|
type: string
|
||||||
|
description: Short, human-readable summary of the problem type. It should not change from occurrence to occurrence of the problem, except for purposes of localization.
|
||||||
|
detail:
|
||||||
|
type: string
|
||||||
|
description: Human-readable explanation specific to this occurrence of the problem.
|
||||||
|
instance:
|
||||||
|
type: string
|
||||||
|
description: URI reference that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced.
|
||||||
|
properties:
|
||||||
|
type: object
|
||||||
|
description: Map for additional, non-standard properties
|
||||||
|
required:
|
||||||
|
- title
|
||||||
|
Email:
|
||||||
|
type: string
|
||||||
|
format: email
|
||||||
|
description: Email address
|
||||||
|
Password:
|
||||||
|
type: string
|
||||||
|
format: password
|
||||||
|
minLength: 8
|
||||||
|
description: Password
|
||||||
|
Account:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
email:
|
||||||
|
$ref: '#/components/schemas/Email'
|
||||||
|
password:
|
||||||
|
$ref: '#/components/schemas/Password'
|
||||||
|
required:
|
||||||
|
- email
|
||||||
|
- password
|
||||||
|
examples:
|
||||||
|
HummusV1In:
|
||||||
|
summary: Hummus recipe
|
||||||
|
value:
|
||||||
|
name: Hummus
|
||||||
|
description: Hummus, is a Levantine dip, spread, or savory dish made from cooked, mashed chickpeas blended with tahini, lemon juice, and garlic.
|
||||||
|
categories:
|
||||||
|
- Dip
|
||||||
|
- Spread
|
||||||
|
ingredients:
|
||||||
|
- Chickpeas
|
||||||
|
- Tahini
|
||||||
|
- Olive oil
|
||||||
|
- Lemon juice
|
||||||
|
- Garlic
|
||||||
|
steps:
|
||||||
|
- Combine chickpeas, tahini, olive oil, lemon juice, garlic, and salt in a food processor.
|
||||||
|
- Blend until smooth, slowly adding cold water until you reach a creamy consistency.
|
||||||
|
- Taste and adjust seasoning if needed.
|
||||||
|
HummusV1Out:
|
||||||
|
summary: Hummus recipe
|
||||||
|
value:
|
||||||
|
id: 1729
|
||||||
|
name: Hummus
|
||||||
|
description: Hummus, is a Levantine dip, spread, or savory dish made from cooked, mashed chickpeas blended with tahini, lemon juice, and garlic.
|
||||||
|
changedAt: '2025-08-08T15:35:10.294411Z'
|
||||||
|
categories:
|
||||||
|
- Dip
|
||||||
|
- Spread
|
||||||
|
ingredients:
|
||||||
|
- Chickpeas
|
||||||
|
- Tahini
|
||||||
|
- Olive oil
|
||||||
|
- Lemon juice
|
||||||
|
- Garlic
|
||||||
|
steps:
|
||||||
|
- Combine chickpeas, tahini, olive oil, lemon juice, garlic, and salt in a food processor.
|
||||||
|
- Blend until smooth, slowly adding cold water until you reach a creamy consistency.
|
||||||
|
- Taste and adjust seasoning if needed.
|
||||||
|
DipsOut:
|
||||||
|
summary: Dip category search
|
||||||
|
value:
|
||||||
|
- id: 3
|
||||||
|
name: Muhammara
|
||||||
|
description: Muhammara is a vibrant and flavorful dip or spread from the Middle East, particularly popular in Syrian and Turkish cuisine. It's made primarily from roasted red bell peppers, walnuts, breadcrumbs, and pomegranate molasses.
|
||||||
|
changedAt: '2025-08-08T16:24:44.673034Z'
|
||||||
|
categories:
|
||||||
|
- Dip
|
||||||
|
ingredients:
|
||||||
|
- Pomegranate molasses
|
||||||
|
- Red bell peppers
|
||||||
|
- Bread crumbs
|
||||||
|
- Cumin
|
||||||
|
- Chili flakes
|
||||||
|
- Garlic
|
||||||
|
- Walnuts
|
||||||
|
- Lemon juice
|
||||||
|
steps:
|
||||||
|
- Roast whole bell peppers in an oven or air fryer and wait until blackened on the outside.
|
||||||
|
- Put the peppers in a bowl cover them with to let steam and cool down
|
||||||
|
- Remove core seeds, and skins
|
||||||
|
- Combine all the ingredients in a food processor.
|
||||||
|
- Process until mostly smooth but with a little texture remaining.
|
||||||
|
- Taste and adjust flavor as needed (lemon for acidity, pomegranate molasses for sweetness)
|
||||||
|
- id: 2
|
||||||
|
name: Hummus
|
||||||
|
description: Hummus, is a Levantine dip, spread, or savory dish made from cooked, mashed chickpeas blended with tahini, lemon juice, and garlic.
|
||||||
|
changedAt: '2025-08-08T16:24:44.579213Z'
|
||||||
|
categories:
|
||||||
|
- Dip
|
||||||
|
ingredients:
|
||||||
|
- Chickpeas
|
||||||
|
- Tahini
|
||||||
|
- Lemon juice
|
||||||
|
- Garlic
|
||||||
|
steps:
|
||||||
|
- Combine chickpeas, tahini, lemon juice, garlic, and salt in a food processor.
|
||||||
|
- Blend until smooth, slowly adding cold water until you reach a creamy consistency.
|
||||||
|
- Taste and adjust seasoning if needed.
|
||||||
|
HummusV2In:
|
||||||
|
summary: Hummus recipe update
|
||||||
|
value:
|
||||||
|
name: Hummus
|
||||||
|
description: Hummus, is a Levantine dip, spread, or savory dish made from cooked, mashed chickpeas blended with tahini, lemon juice, and garlic.
|
||||||
|
categories:
|
||||||
|
- Dip
|
||||||
|
- Spread
|
||||||
|
ingredients:
|
||||||
|
- Chickpeas
|
||||||
|
- Tahini
|
||||||
|
- Lemon juice
|
||||||
|
- Garlic
|
||||||
|
steps:
|
||||||
|
- Combine chickpeas, tahini, lemon juice, garlic, and salt in a food processor.
|
||||||
|
- Blend until smooth, slowly adding cold water until you reach a creamy consistency.
|
||||||
|
- Taste and adjust seasoning if needed.
|
||||||
|
HummusV2Out:
|
||||||
|
summary: Hummus recipe update
|
||||||
|
value:
|
||||||
|
id: 1729
|
||||||
|
name: Hummus
|
||||||
|
description: Hummus, is a Levantine dip, spread, or savory dish made from cooked, mashed chickpeas blended with tahini, lemon juice, and garlic.
|
||||||
|
changedAt: '2025-08-09T12:48:32.134821Z'
|
||||||
|
categories:
|
||||||
|
- Dip
|
||||||
|
- Spread
|
||||||
|
ingredients:
|
||||||
|
- Chickpeas
|
||||||
|
- Tahini
|
||||||
|
- Lemon juice
|
||||||
|
- Garlic
|
||||||
|
steps:
|
||||||
|
- Combine chickpeas, tahini, lemon juice, garlic, and salt in a food processor.
|
||||||
|
- Blend until smooth, slowly adding cold water until you reach a creamy consistency.
|
||||||
|
- Taste and adjust seasoning if needed.
|
||||||
|
AccountIn:
|
||||||
|
summary: Account registration
|
||||||
|
value:
|
||||||
|
email: ada@example.com
|
||||||
|
password: FBR5h0L1ENA3edctgDIEnxSvFdR0
|
||||||
|
parameters:
|
||||||
|
'{recipeId}':
|
||||||
|
name: recipeId
|
||||||
|
in: path
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Id'
|
||||||
|
description: Unique identifier of the recipe
|
||||||
32
openapi/recipe-api.yaml
Normal file
32
openapi/recipe-api.yaml
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
openapi: "3.1.1"
|
||||||
|
info:
|
||||||
|
title: "Recipe API"
|
||||||
|
description:
|
||||||
|
"Programmatic access to a database of recipes.
|
||||||
|
Users can publish and find recipes."
|
||||||
|
version: "1.0.0"
|
||||||
|
license:
|
||||||
|
name: MIT
|
||||||
|
url: https://opensource.org/licenses/MIT
|
||||||
|
servers:
|
||||||
|
- url: "https://api.recipes.bitfield.eu/v1"
|
||||||
|
tags:
|
||||||
|
- name: Recipe
|
||||||
|
description: "Steps and ingredients for preparing a dish"
|
||||||
|
- name: Account
|
||||||
|
description: "Access to protected operations"
|
||||||
|
security: [ ]
|
||||||
|
paths:
|
||||||
|
/recipe/new:
|
||||||
|
$ref: "./paths/recipe-new.yaml"
|
||||||
|
/recipe/search:
|
||||||
|
$ref: "./paths/recipe-search.yaml"
|
||||||
|
/recipe/{recipeId}:
|
||||||
|
$ref: "./paths/recipe-{recipeId}.yaml"
|
||||||
|
/account/register:
|
||||||
|
$ref: "./paths/account-register.yaml"
|
||||||
|
components:
|
||||||
|
securitySchemes:
|
||||||
|
httpBasic:
|
||||||
|
type: http
|
||||||
|
scheme: basic
|
||||||
8
openapi/redocly.yaml
Normal file
8
openapi/redocly.yaml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
extends:
|
||||||
|
- recommended
|
||||||
|
|
||||||
|
apis:
|
||||||
|
recipe-api@v1:
|
||||||
|
root: ./recipe-api.yaml
|
||||||
|
rules:
|
||||||
|
no-ambiguous-paths: error
|
||||||
9
openapi/schemas/Account.yaml
Normal file
9
openapi/schemas/Account.yaml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
type: "object"
|
||||||
|
properties:
|
||||||
|
email:
|
||||||
|
$ref: "./Email.yaml"
|
||||||
|
password:
|
||||||
|
$ref: "./Password.yaml"
|
||||||
|
required:
|
||||||
|
- email
|
||||||
|
- password
|
||||||
2
openapi/schemas/DateTime.yaml
Normal file
2
openapi/schemas/DateTime.yaml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
type: "string"
|
||||||
|
format: date-time
|
||||||
3
openapi/schemas/Email.yaml
Normal file
3
openapi/schemas/Email.yaml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
type: "string"
|
||||||
|
format: email
|
||||||
|
description: "Email address"
|
||||||
2
openapi/schemas/Id.yaml
Normal file
2
openapi/schemas/Id.yaml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
type: "integer"
|
||||||
|
format: int64
|
||||||
2
openapi/schemas/NonBlankString.yaml
Normal file
2
openapi/schemas/NonBlankString.yaml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
type: "string"
|
||||||
|
pattern: "^(.|\\s)*\\S(.|\\s)*$"
|
||||||
4
openapi/schemas/Password.yaml
Normal file
4
openapi/schemas/Password.yaml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
type: "string"
|
||||||
|
format: password
|
||||||
|
minLength: 8
|
||||||
|
description: "Password"
|
||||||
24
openapi/schemas/ProblemDetail.yaml
Normal file
24
openapi/schemas/ProblemDetail.yaml
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
type:
|
||||||
|
type: "string"
|
||||||
|
description: "URI reference that identifies the problem type."
|
||||||
|
format: "uri"
|
||||||
|
status:
|
||||||
|
type: "integer"
|
||||||
|
description: "HTTP status code generated by the origin server for this occurrence of the problem."
|
||||||
|
format: "int32"
|
||||||
|
title:
|
||||||
|
type: "string"
|
||||||
|
description: "Short, human-readable summary of the problem type. It should not change from occurrence to occurrence of the problem, except for purposes of localization."
|
||||||
|
detail:
|
||||||
|
type: "string"
|
||||||
|
description: "Human-readable explanation specific to this occurrence of the problem."
|
||||||
|
instance:
|
||||||
|
type: "string"
|
||||||
|
description: "URI reference that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced."
|
||||||
|
properties:
|
||||||
|
type: "object"
|
||||||
|
description: "Map for additional, non-standard properties"
|
||||||
|
required:
|
||||||
|
- title
|
||||||
39
openapi/schemas/Recipe.yaml
Normal file
39
openapi/schemas/Recipe.yaml
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
type: "object"
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
$ref: "./Id.yaml"
|
||||||
|
readOnly: true
|
||||||
|
description: "Unique identifier of the recipe"
|
||||||
|
name:
|
||||||
|
$ref: "./NonBlankString.yaml"
|
||||||
|
description: "Name"
|
||||||
|
description:
|
||||||
|
$ref: "./NonBlankString.yaml"
|
||||||
|
description: "Description"
|
||||||
|
changedAt:
|
||||||
|
$ref: "./DateTime.yaml"
|
||||||
|
readOnly: true
|
||||||
|
description: "Last point in time when the recipe was changed"
|
||||||
|
categories:
|
||||||
|
type: "array"
|
||||||
|
items:
|
||||||
|
$ref: "./NonBlankString.yaml"
|
||||||
|
description: "Category names"
|
||||||
|
ingredients:
|
||||||
|
type: "array"
|
||||||
|
minItems: 1
|
||||||
|
items:
|
||||||
|
$ref: "./NonBlankString.yaml"
|
||||||
|
description: "Step descriptions"
|
||||||
|
steps:
|
||||||
|
type: "array"
|
||||||
|
minItems: 1
|
||||||
|
items:
|
||||||
|
$ref: "./NonBlankString.yaml"
|
||||||
|
description: "Ingredient names"
|
||||||
|
required:
|
||||||
|
- name
|
||||||
|
- description
|
||||||
|
- categories
|
||||||
|
- ingredients
|
||||||
|
- steps
|
||||||
Reference in New Issue
Block a user