{ "openapi": "3.1.0", "info": { "title": "Doof API", "description": "Doof Backend API", "version": "1.0.0" }, "paths": { "/api/v1/recipes/parse": { "get": { "tags": [ "v1", "recipes" ], "summary": "Parse a recipe from a URL", "operationId": "parseRecipe", "parameters": [ { "name": "url", "in": "query", "required": true, "schema": { "type": "string", "title": "Url" } }, { "name": "user_id", "in": "cookie", "required": true, "schema": { "type": "integer", "title": "User Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "400": { "$ref": "#/components/responses/Problem400" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/recipes/ingredients/parse": { "get": { "tags": [ "v1", "ingredients" ], "summary": "Parse raw ingredient lines", "operationId": "parseIngredients", "parameters": [ { "name": "ingredients", "in": "query", "required": true, "schema": { "type": "array", "items": { "type": "string" }, "title": "Array of ingredients to parse" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/Ingredient" }, "title": "Response Parseingredients" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/products": { "post": { "tags": [ "v1", "products" ], "summary": "Create or fetch a product from a URL", "operationId": "createProduct", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProductUrl" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "anyOf": [ { "$ref": "#/components/schemas/Product" }, { "type": "null" } ], "title": "Response Createproduct" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/recipes": { "get": { "tags": [ "v1", "recipes" ], "summary": "List recipes (paginated)", "operationId": "listRecipes", "parameters": [ { "name": "q", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Optional case-insensitive name filter (matches recipe name with SQL LIKE).", "title": "Q" }, "description": "Optional case-insensitive name filter (matches recipe name with SQL LIKE)." }, { "name": "cursor", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Opaque cursor for pagination. Pass the value returned in nextCursor to fetch the next page.", "title": "Cursor" }, "description": "Opaque cursor for pagination. Pass the value returned in nextCursor to fetch the next page." }, { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 200, "minimum": 1, "description": "Maximum number of items to return (1-200).", "default": 50, "title": "Limit" }, "description": "Maximum number of items to return (1-200)." } ], "responses": { "200": { "description": "A page of recipes", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Page_Recipe_" }, "example": { "items": [ { "id": 1, "name": "Example Recipe", "link": "https://example.com/recipes/1", "serves": 4, "imageUrls": [], "ingredients": [] } ], "nextCursor": "2", "total": 1 } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } }, "post": { "tags": [ "v1", "recipes" ], "summary": "Create a new recipe (versioning semantics applied)", "operationId": "createRecipe", "parameters": [ { "name": "user_id", "in": "cookie", "required": true, "schema": { "type": "integer", "title": "User Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Recipe-Input" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "400": { "description": "Validation error", "content": { "application/problem+json": {}, "application/json": { "schema": { "$ref": "#/components/schemas/ProblemDetails" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/recipes/{recipe_id}": { "get": { "tags": [ "v1", "recipes" ], "summary": "Get a single recipe", "operationId": "getRecipe", "parameters": [ { "name": "recipe_id", "in": "path", "required": true, "schema": { "type": "integer", "title": "Recipe Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "404": { "description": "Recipe not found", "content": { "application/problem+json": {}, "application/json": { "schema": { "$ref": "#/components/schemas/ProblemDetails" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } }, "delete": { "tags": [ "v1", "recipes" ], "summary": "Soft-delete (hide) a recipe", "operationId": "deleteRecipe", "parameters": [ { "name": "recipe_id", "in": "path", "required": true, "schema": { "type": "integer", "title": "Recipe Id" } }, { "name": "user_id", "in": "cookie", "required": true, "schema": { "type": "integer", "title": "User Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "404": { "description": "Recipe not found", "content": { "application/problem+json": {}, "application/json": { "schema": { "$ref": "#/components/schemas/ProblemDetails" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } } }, "components": { "schemas": { "HTTPValidationError": { "properties": { "detail": { "items": { "$ref": "#/components/schemas/ValidationError" }, "type": "array", "title": "Detail" } }, "type": "object", "title": "HTTPValidationError" }, "ProblemDetails": { "properties": { "type": { "type": "string", "title": "Type", "default": "about:blank" }, "title": { "type": "string", "title": "Title" }, "status": { "type": "integer", "title": "Status" }, "detail": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Detail" }, "instance": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Instance" }, "errors": { "anyOf": [ { "type": "object" }, { "type": "null" } ], "title": "Errors" } }, "type": "object", "required": [ "title", "status" ], "title": "ProblemDetails" }, "ValidationError": { "properties": { "loc": { "items": { "anyOf": [ { "type": "string" }, { "type": "integer" } ] }, "type": "array", "title": "Location" }, "msg": { "type": "string", "title": "Message" }, "type": { "type": "string", "title": "Error Type" } }, "type": "object", "required": [ "loc", "msg", "type" ], "title": "ValidationError" } } } }