{"openapi":"3.1.0","info":{"title":"RecipeBee Public API","version":"1.0.0","description":"Public, unauthenticated REST API for RecipeBee. Agents can search and\nread public recipes, categories, tags, and blog posts without an API key.\n\nAuthenticated product APIs (private recipes, meal plans, shopping lists)\nuse Laravel Sanctum and are documented separately. Remote MCP tools are\navailable at https://recipebee.app/mcp.\n\nVersioning: the public API is versioned in the URL path (`/api/v1`).\nDeprecated versions are announced with HTTP `Deprecation` and `Sunset`\nheaders and remain available for at least 12 months. Policy:\nhttps://recipebee.app/developers#versioning\n\nRate limits: responses include IETF `RateLimit`, `RateLimit-Limit`,\n`RateLimit-Remaining`, and `RateLimit-Reset` headers, plus legacy\n`X-RateLimit-*`. A 429 includes `Retry-After`.\n\nPagination: prefer cursor pagination (`cursor` + `data.meta.next_cursor`)\non list endpoints. Page-based `page` remains supported.\n","contact":{"name":"RecipeBee Support","email":"support@recipebee.app","url":"https://recipebee.app"},"license":{"name":"MIT","url":"https://opensource.org/licenses/MIT"}},"servers":[{"url":"https://recipebee.app","description":"Production"},{"url":"http://localhost:8000","description":"Local development"}],"tags":[{"name":"Discovery","description":"Machine-readable catalogs for agents"},{"name":"Recipes","description":"Public recipes"},{"name":"Categories","description":"Recipe categories"},{"name":"Tags","description":"Recipe tags"},{"name":"Cookbooks","description":"Public shared cookbooks"},{"name":"Blog","description":"Public blog posts"},{"name":"Health","description":"Service health"}],"paths":{"/api":{"get":{"operationId":"getApiCatalog","tags":["Discovery"],"summary":"List the public API catalog","description":"Returns the public RecipeBee REST catalog, OpenAPI locations, and MCP endpoint.","responses":{"200":{"description":"Public API catalog","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiCatalog"}}}}}}},"/api/v1":{"get":{"operationId":"getApiV1Catalog","tags":["Discovery"],"summary":"List the versioned public API catalog","description":"Same catalog as /api, scoped to the v1 namespace.","responses":{"200":{"description":"Public API catalog","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiCatalog"}}}}}}},"/api/openapi.json":{"get":{"operationId":"getOpenApiJson","tags":["Discovery"],"summary":"Download this OpenAPI specification as JSON","responses":{"200":{"description":"OpenAPI 3.1 document","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/openapi.yaml":{"get":{"operationId":"getOpenApiYaml","tags":["Discovery"],"summary":"Download this OpenAPI specification as YAML","responses":{"200":{"description":"OpenAPI 3.1 document","content":{"application/yaml":{"schema":{"type":"string"}}}}}}},"/api/v1/health":{"get":{"operationId":"getHealth","tags":["Health"],"summary":"Check API health","responses":{"200":{"description":"Service is healthy","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthStatus"}}}},"503":{"description":"Service is unhealthy"}}}},"/api/v1/health/ping":{"get":{"operationId":"pingHealth","tags":["Health"],"summary":"Lightweight ping","responses":{"200":{"description":"Service is reachable","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","example":"ok"},"timestamp":{"type":"string","format":"date-time"}}}}}}}}},"/api/v1/public/recipes":{"get":{"operationId":"listPublicRecipes","tags":["Recipes"],"summary":"List public recipes","description":"Paginated public recipes. No authentication required. Prefer cursor pagination (`cursor`) over `page`.","parameters":[{"name":"q","in":"query","description":"Search term applied to recipe title or slug","schema":{"type":"string","maxLength":160,"example":"chocolate chip"}},{"name":"per_page","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},{"name":"cursor","in":"query","description":"Opaque cursor from data.meta.next_cursor. When present, the response uses cursor pagination.","schema":{"type":"string"}},{"name":"page","in":"query","description":"Page number for offset pagination. Ignored when cursor is provided.","schema":{"type":"integer","minimum":1,"default":1}},{"name":"view","in":"query","description":"Use card for compact listing data","schema":{"type":"string","enum":["card","full"],"default":"full"}},{"name":"categories","in":"query","description":"Comma-separated category slugs (AND logic)","schema":{"type":"string","example":"breakfast,dessert"}},{"name":"tags","in":"query","description":"Comma-separated tag slugs (AND logic)","schema":{"type":"string","example":"gluten-free,quick-meal"}}],"responses":{"200":{"description":"Paginated public recipes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedRecipes"}}}}}}},"/api/v1/public/recipes/{slug}":{"get":{"operationId":"getPublicRecipe","tags":["Recipes"],"summary":"Get a public recipe","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","example":"butter-chicken-stuffed-buns-soft-fluffy"}}],"responses":{"200":{"description":"Public recipe","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiEnvelope"}}}},"404":{"description":"Recipe not found or not public"}}}},"/api/v1/categories":{"get":{"operationId":"listCategories","tags":["Categories"],"summary":"List recipe categories","parameters":[{"name":"tree","in":"query","schema":{"type":"boolean"}},{"name":"active_only","in":"query","schema":{"type":"boolean"}}],"responses":{"200":{"description":"Categories","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiEnvelope"}}}}}}},"/api/v1/tags":{"get":{"operationId":"listTags","tags":["Tags"],"summary":"List recipe tags","responses":{"200":{"description":"Tags","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiEnvelope"}}}}}}},"/api/v1/public/cookbooks/{slug}":{"get":{"operationId":"getPublicCookbook","tags":["Cookbooks"],"summary":"Get a public shared cookbook","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Public cookbook","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiEnvelope"}}}},"404":{"description":"Cookbook not found or not public"}}}},"/api/v1/blog-posts":{"get":{"operationId":"listBlogPosts","tags":["Blog"],"summary":"List public blog posts","responses":{"200":{"description":"Blog posts","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiEnvelope"}}}}}}}},"components":{"schemas":{"ApiCatalog":{"type":"object","required":["name","version","openapi","mcp","endpoints"],"properties":{"name":{"type":"string","example":"RecipeBee"},"version":{"type":"string","example":"v1"},"description":{"type":"string"},"openapi":{"type":"object","properties":{"json":{"type":"string","format":"uri"},"yaml":{"type":"string","format":"uri"}}},"mcp":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"transport":{"type":"string","example":"streamable-http"},"server_card":{"type":"string","format":"uri"}}},"endpoints":{"type":"array","items":{"type":"object","properties":{"method":{"type":"string"},"path":{"type":"string"},"description":{"type":"string"}}}}}},"HealthStatus":{"type":"object","properties":{"status":{"type":"string","example":"healthy"},"timestamp":{"type":"string","format":"date-time"}}},"ApiEnvelope":{"type":"object","properties":{"status":{"type":"string","example":"success"},"statusCode":{"type":"integer","example":200},"message":{"type":"string"},"data":{"description":"Endpoint-specific payload"},"timestamp":{"type":"string","format":"date-time"}}},"PaginatedRecipes":{"allOf":[{"$ref":"#/components/schemas/ApiEnvelope"},{"type":"object","properties":{"data":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PublicRecipeSummary"}},"meta":{"type":"object","properties":{"pagination":{"type":"string","enum":["page","cursor"]},"current_page":{"type":"integer"},"last_page":{"type":"integer"},"per_page":{"type":"integer"},"total":{"type":"integer"},"has_more":{"type":"boolean"},"next_cursor":{"type":"string","nullable":true},"prev_cursor":{"type":"string","nullable":true}}},"links":{"type":"object","properties":{"next":{"type":"string","format":"uri","nullable":true},"prev":{"type":"string","format":"uri","nullable":true}}}}}}}]},"PublicRecipeSummary":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"},"slug":{"type":"string"},"summary":{"type":"string"},"servings":{"type":"integer"},"prep_time_minutes":{"type":"integer"},"cook_time_minutes":{"type":"integer"},"is_public":{"type":"boolean","example":true},"hero_image":{"type":"object","nullable":true},"owner":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"}}}}}}}}