{
  "openapi": "3.0.3",
  "info": {
    "title": "CartaQR Connected API",
    "version": "1.0.0",
    "description": "API de solo lectura para sincronizar la carta pública y el menú del día de un restaurante."
  },
  "servers": [{"url": "https://cartaqrpro.es"}],
  "paths": {
    "/api/v1/connected/menu": {
      "get": {
        "summary": "Obtener la carta pública vigente",
        "security": [{"bearerAuth": []}],
        "parameters": [{"in": "header", "name": "If-None-Match", "required": false, "schema": {"type": "string"}}],
        "responses": {
          "200": {"description": "Carta vigente", "headers": {"ETag": {"schema": {"type": "string"}}, "X-CartaQR-Revision": {"schema": {"type": "string"}}}, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MenuResponse"}}}},
          "304": {"description": "La carta no ha cambiado"},
          "401": {"description": "API key ausente, incorrecta o revocada"},
          "403": {"description": "El restaurante no está activo"},
          "429": {"description": "Límite de solicitudes alcanzado"}
        }
      }
    }
  },
  "components": {
    "securitySchemes": {"bearerAuth": {"type": "http", "scheme": "bearer", "bearerFormat": "CartaQR API key"}},
    "schemas": {
      "MenuResponse": {
        "type": "object",
        "required": ["api_version", "restaurant", "daily_menu", "categories", "meta"],
        "properties": {
          "api_version": {"type": "string", "example": "1.0"},
          "restaurant": {"$ref": "#/components/schemas/Restaurant"},
          "daily_menu": {"nullable": true, "allOf": [{"$ref": "#/components/schemas/DailyMenu"}]},
          "categories": {"type": "array", "items": {"$ref": "#/components/schemas/Category"}},
          "meta": {"$ref": "#/components/schemas/Meta"}
        }
      },
      "Restaurant": {"type": "object", "properties": {"id": {"type": "integer"}, "name": {"type": "string"}, "slug": {"type": "string"}, "description": {"type": "string", "nullable": true}, "phone": {"type": "string", "nullable": true}, "whatsapp": {"type": "string", "nullable": true}, "address": {"type": "string", "nullable": true}, "city": {"type": "string", "nullable": true}, "logo_url": {"type": "string", "format": "uri", "nullable": true}, "cover_url": {"type": "string", "format": "uri", "nullable": true}, "public_url": {"type": "string", "format": "uri"}, "accent": {"type": "string"}, "availability": {"type": "object"}, "opening_hours": {"type": "object"}}},
      "DailyMenu": {"type": "object", "properties": {"id": {"type": "integer"}, "name": {"type": "string"}, "title": {"type": "string"}, "sections": {"type": "array", "items": {"type": "object"}}, "fixed_text": {"type": "string", "nullable": true}, "price": {"type": "number", "nullable": true}, "end_time": {"type": "string", "nullable": true}}},
      "Category": {"type": "object", "properties": {"id": {"type": "integer"}, "name": {"type": "string"}, "description": {"type": "string", "nullable": true}, "position": {"type": "integer"}, "image_url": {"type": "string", "format": "uri", "nullable": true}, "items": {"type": "array", "items": {"$ref": "#/components/schemas/MenuItem"}}}},
      "MenuItem": {"type": "object", "properties": {"id": {"type": "integer"}, "name": {"type": "string"}, "description": {"type": "string", "nullable": true}, "price": {"type": "number"}, "base_price": {"type": "number"}, "discounted_price": {"type": "number", "nullable": true}, "featured": {"type": "boolean"}, "labels": {"type": "array"}, "allergens": {"type": "array"}, "variants": {"type": "array"}, "extras": {"type": "array"}, "image_url": {"type": "string", "format": "uri"}, "image_urls": {"type": "array", "items": {"type": "string", "format": "uri"}}}},
      "Meta": {"type": "object", "properties": {"revision": {"type": "string"}, "generated_at": {"type": "string", "format": "date-time"}, "refresh_after_seconds": {"type": "integer", "example": 30}}}
    }
  }
}
