{
  "openapi": "3.1.0",
  "info": {
    "title": "TipTopChef Dinner Suggestions API",
    "version": "1.0.0"
  },
  "servers": [{"url": "/", "description": "Host serving this specification"}],
  "paths": {
    "/api/v1/dinner-suggestions": {
      "post": {
        "operationId": "suggestDinners",
        "summary": "Get dinner suggestions for a planner",
        "security": [{"PartnerKey": []}],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {"schema": {"type": "object", "required": ["servings"], "properties": {"servings": {"type": "integer", "minimum": 1, "maximum": 12}, "maxMinutes": {"type": "integer", "minimum": 1, "maximum": 1440}, "limit": {"type": "integer", "minimum": 1, "maximum": 7, "default": 3}, "excludeRecipeIds": {"type": "array", "items": {"type": "string", "minLength": 1, "maxLength": 150}, "maxItems": 50, "default": []}}, "additionalProperties": false}, "example": {"servings": 4, "maxMinutes": 30, "limit": 1}}
          }
        },
        "responses": {
          "200": {
            "description": "Matching dinners, possibly an empty list",
            "content": {"application/json": {"schema": {"type": "object", "required": ["brand", "suggestions"], "properties": {"brand": {"type": "object", "required": ["name", "logoUrl", "homepageUrl", "credit"], "properties": {"name": {"type": "string"}, "logoUrl": {"type": "string", "format": "uri"}, "homepageUrl": {"type": "string", "format": "uri"}, "credit": {"type": "string"}}}, "suggestions": {"type": "array", "items": {"type": "object", "required": ["id", "title", "returningSpecial", "description", "estimatedMinutes", "extraTime", "servings", "recipeUrl", "photo", "ingredients"], "properties": {"id": {"type": "string", "minLength": 1, "maxLength": 150}, "title": {"type": "string"}, "returningSpecial": {"type": "boolean", "description": "Editorial pick featured in the rotating returning-special slot."}, "description": {"type": "string"}, "estimatedMinutes": {"type": "integer", "minimum": 1}, "extraTime": {"type": ["string", "null"]}, "servings": {"type": "integer", "minimum": 1, "maximum": 12}, "recipeUrl": {"type": "string", "format": "uri"}, "photo": {"type": "object", "required": ["url", "alt", "credit"], "properties": {"url": {"type": "string", "format": "uri"}, "alt": {"type": "string"}, "credit": {"type": ["object", "null"], "required": ["author", "license", "licenseUrl", "sourceUrl"], "properties": {"author": {"type": "string"}, "license": {"type": "string"}, "licenseUrl": {"type": "string", "format": "uri"}, "sourceUrl": {"type": "string", "format": "uri"}}}}}, "ingredients": {"type": "array", "items": {"type": "object", "required": ["name", "amount", "unit"], "properties": {"name": {"type": "string"}, "amount": {"type": "number"}, "unit": {"type": "string"}}}, "minItems": 1}}}, "maxItems": 7}}}}}
          },
          "400": {
            "description": "Invalid JSON or request fields",
            "content": {"application/json": {"schema": {"type": "object", "required": ["error"], "properties": {"error": {"type": "object", "required": ["code", "message"], "properties": {"code": {"type": "string"}, "message": {"type": "string"}}}}}}}
          },
          "401": {
            "description": "Missing or invalid key",
            "content": {"application/json": {"schema": {"type": "object", "required": ["error"], "properties": {"error": {"type": "object", "required": ["code", "message"], "properties": {"code": {"type": "string"}, "message": {"type": "string"}}}}}}},
            "headers": {"WWW-Authenticate": {"schema": {"type": "string", "example": "Bearer"}}}
          },
          "413": {
            "description": "Request exceeds 16 KiB",
            "content": {"application/json": {"schema": {"type": "object", "required": ["error"], "properties": {"error": {"type": "object", "required": ["code", "message"], "properties": {"code": {"type": "string"}, "message": {"type": "string"}}}}}}}
          },
          "415": {
            "description": "Expected application/json",
            "content": {"application/json": {"schema": {"type": "object", "required": ["error"], "properties": {"error": {"type": "object", "required": ["code", "message"], "properties": {"code": {"type": "string"}, "message": {"type": "string"}}}}}}}
          },
          "429": {
            "description": "Rate limit exceeded",
            "content": {"application/json": {"schema": {"type": "object", "required": ["error"], "properties": {"error": {"type": "object", "required": ["code", "message"], "properties": {"code": {"type": "string"}, "message": {"type": "string"}}}}}}},
            "headers": {"Retry-After": {"schema": {"type": "integer", "minimum": 1}, "description": "Seconds to wait before retrying"}}
          },
          "503": {
            "description": "Partner API unavailable",
            "content": {"application/json": {"schema": {"type": "object", "required": ["error"], "properties": {"error": {"type": "object", "required": ["code", "message"], "properties": {"code": {"type": "string"}, "message": {"type": "string"}}}}}}}
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "PartnerKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "Server-side partner API key"
      }
    }
  }
}
