{
  "openapi": "3.1.0",
  "info": {
    "title": "Market Winerim API",
    "version": "0.20-pre",
    "summary": "API SaaS para inteligencia de mercado agregada y anonimizada del vino en restauracion.",
    "description": "Contrato operativo de Market Winerim. El frontend publico vive en market.winerim.wine; la API productiva prevista vive en api.market.winerim.wine. Mientras no exista ingesta first-party consentida, los datos comerciales deben tratarse como demo/mock o agregados de desarrollo."
  },
  "servers": [
    {
      "url": "https://api.market.winerim.wine",
      "description": "API productiva prevista"
    },
    {
      "url": "https://market.winerim.wine",
      "description": "Frontend publico con endpoints estaticos demo"
    },
    {
      "url": "http://localhost:4181",
      "description": "Backend local Node"
    }
  ],
  "tags": [
    {
      "name": "Health",
      "description": "Liveness, readiness y planes publicos."
    },
    {
      "name": "Market",
      "description": "Lectura comercial de benchmarks, presencia, demanda, gaps y exportaciones."
    },
    {
      "name": "Analyst",
      "description": "Preguntas tipo analista, historial y briefs."
    },
    {
      "name": "Reports",
      "description": "Solicitudes de informes a medida."
    },
    {
      "name": "Pilots",
      "description": "Pilotos comerciales Cellaria de 90 dias con scoping, informe y watchlists."
    },
    {
      "name": "Ops",
      "description": "Operativa interna con scope market:admin."
    },
    {
      "name": "Ingest",
      "description": "Ingesta interna Winerim -> Market. Requiere Postgres y scope market:ingest."
    }
  ],
  "security": [
    {
      "ApiKeyAuth": []
    }
  ],
  "paths": {
    "/v1/health": {
      "get": {
        "tags": [
          "Health"
        ],
        "operationId": "getHealth",
        "summary": "Liveness basico de la API.",
        "security": [],
        "responses": {
          "200": {
            "description": "Proceso vivo."
          }
        }
      }
    },
    "/v1/ready": {
      "get": {
        "tags": [
          "Health"
        ],
        "operationId": "getReady",
        "summary": "Readiness productivo.",
        "description": "En produccion valida entorno, CORS, Postgres y migraciones antes de abrir trafico.",
        "security": [],
        "responses": {
          "200": {
            "description": "Servicio listo."
          },
          "503": {
            "description": "Servicio no listo."
          }
        }
      }
    },
    "/v1/openapi.json": {
      "get": {
        "tags": [
          "Health"
        ],
        "operationId": "getOpenApi",
        "summary": "Contrato OpenAPI publico de Market Winerim.",
        "security": [],
        "responses": {
          "200": {
            "description": "Documento OpenAPI JSON.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          }
        }
      }
    },
    "/v1/billing/plans": {
      "get": {
        "tags": [
          "Health"
        ],
        "operationId": "listBillingPlans",
        "summary": "Lista planes comerciales disponibles.",
        "security": [],
        "responses": {
          "200": {
            "description": "Planes y moneda."
          }
        }
      }
    },
    "/v1/market/overview": {
      "get": {
        "tags": [
          "Market"
        ],
        "operationId": "getMarketOverview",
        "summary": "Snapshot principal de Market.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Region"
          },
          {
            "$ref": "#/components/parameters/Segment"
          },
          {
            "$ref": "#/components/parameters/Period"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonObject"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/v1/market/presence": {
      "get": {
        "tags": [
          "Market"
        ],
        "operationId": "listPresence",
        "summary": "Presencia de vinos, categorias o referencias en carta.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Search"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonObject"
          }
        }
      }
    },
    "/v1/market/demand": {
      "get": {
        "tags": [
          "Market"
        ],
        "operationId": "getDemand",
        "summary": "Demanda agregada, gaps y senales de rotacion.",
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonObject"
          }
        }
      }
    },
    "/v1/market/opportunities": {
      "get": {
        "tags": [
          "Market"
        ],
        "operationId": "listOpportunities",
        "summary": "Oportunidades filtradas por tipo de comprador.",
        "parameters": [
          {
            "$ref": "#/components/parameters/BuyerType"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonObject"
          }
        }
      }
    },
    "/v1/market/pricing-benchmark": {
      "get": {
        "tags": [
          "Market"
        ],
        "operationId": "getPricingBenchmark",
        "summary": "Benchmark de PVP y posicionamiento.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Search"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonObject"
          }
        }
      }
    },
    "/v1/market/rotation-benchmark": {
      "get": {
        "tags": [
          "Market"
        ],
        "operationId": "getRotationBenchmark",
        "summary": "Benchmark de rotacion/demanda por categoria.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Search"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonObject"
          }
        }
      }
    },
    "/v1/market/stock-risk": {
      "get": {
        "tags": [
          "Market"
        ],
        "operationId": "getStockRisk",
        "summary": "Oportunidades y riesgos agregados de stock.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Search"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonObject"
          }
        }
      }
    },
    "/v1/market/assortment-gaps": {
      "get": {
        "tags": [
          "Market"
        ],
        "operationId": "getAssortmentGaps",
        "summary": "Huecos de surtido por zona, categoria o posicionamiento.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Search"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonObject"
          }
        }
      }
    },
    "/v1/market/trends": {
      "get": {
        "tags": [
          "Market"
        ],
        "operationId": "getTrends",
        "summary": "Tendencias agregadas por categoria, zona o periodo.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "$ref": "#/components/parameters/Period"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonObject"
          }
        }
      }
    },
    "/v1/market/indices": {
      "get": {
        "tags": [
          "Market"
        ],
        "operationId": "getCellariaIndices",
        "summary": "Indices comerciales Cellaria con n, cobertura y confianza.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Search"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonObject"
          }
        }
      }
    },
    "/v1/market/watchlists": {
      "get": {
        "tags": [
          "Market"
        ],
        "operationId": "listCellariaWatchlists",
        "summary": "Watchlists y alertas comerciales por tipo de comprador.",
        "parameters": [
          {
            "$ref": "#/components/parameters/BuyerType"
          },
          {
            "$ref": "#/components/parameters/Search"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonObject"
          }
        }
      },
      "post": {
        "tags": [
          "Market"
        ],
        "operationId": "createCellariaWatchlist",
        "summary": "Crea una watchlist comercial para el cliente autenticado.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WatchlistCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "$ref": "#/components/responses/JsonObject"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          }
        }
      }
    },
    "/v1/market/watchlists/{watchlist_id}": {
      "get": {
        "tags": [
          "Market"
        ],
        "operationId": "getCellariaWatchlist",
        "summary": "Detalle de una watchlist del cliente autenticado.",
        "parameters": [
          {
            "$ref": "#/components/parameters/WatchlistId"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonObject"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "patch": {
        "tags": [
          "Market"
        ],
        "operationId": "updateCellariaWatchlist",
        "summary": "Actualiza estado, cadencia o filtros de una watchlist.",
        "parameters": [
          {
            "$ref": "#/components/parameters/WatchlistId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WatchlistPatch"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonObject"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/v1/market/watchlists/{watchlist_id}/evaluation": {
      "get": {
        "tags": [
          "Market"
        ],
        "operationId": "evaluateCellariaWatchlist",
        "summary": "Evalua una watchlist contra el snapshot Market actual.",
        "parameters": [
          {
            "$ref": "#/components/parameters/WatchlistId"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonObject"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/v1/market/watchlists/{watchlist_id}/observations": {
      "get": {
        "tags": [
          "Market"
        ],
        "operationId": "listCellariaWatchlistObservations",
        "summary": "Lista observaciones historicas de una watchlist.",
        "parameters": [
          {
            "$ref": "#/components/parameters/WatchlistId"
          },
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonObject"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "post": {
        "tags": [
          "Market"
        ],
        "operationId": "createCellariaWatchlistObservation",
        "summary": "Evalua y guarda una observacion historica de una watchlist.",
        "parameters": [
          {
            "$ref": "#/components/parameters/WatchlistId"
          }
        ],
        "responses": {
          "201": {
            "$ref": "#/components/responses/JsonObject"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/v1/market/watchlists/{watchlist_id}/alerts": {
      "get": {
        "tags": [
          "Market"
        ],
        "operationId": "listCellariaWatchlistAlerts",
        "summary": "Lista alertas accionables de una watchlist.",
        "parameters": [
          {
            "$ref": "#/components/parameters/WatchlistId"
          },
          {
            "$ref": "#/components/parameters/Status"
          },
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonObject"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "post": {
        "tags": [
          "Market"
        ],
        "operationId": "createCellariaWatchlistAlert",
        "summary": "Crea una alerta si el ultimo cambio de la watchlist es material.",
        "parameters": [
          {
            "$ref": "#/components/parameters/WatchlistId"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonObject"
          },
          "201": {
            "$ref": "#/components/responses/JsonObject"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/v1/market/watchlists/{watchlist_id}/changes": {
      "get": {
        "tags": [
          "Market"
        ],
        "operationId": "getCellariaWatchlistChanges",
        "summary": "Compara las dos ultimas observaciones de una watchlist.",
        "parameters": [
          {
            "$ref": "#/components/parameters/WatchlistId"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonObject"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/v1/market/alerts": {
      "get": {
        "tags": [
          "Market"
        ],
        "operationId": "listCellariaAlerts",
        "summary": "Lista alertas accionables del cliente autenticado.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Status"
          },
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonObject"
          }
        }
      }
    },
    "/v1/market/alerts/{alert_id}": {
      "get": {
        "tags": [
          "Market"
        ],
        "operationId": "getCellariaAlert",
        "summary": "Detalle de una alerta del cliente autenticado.",
        "parameters": [
          {
            "$ref": "#/components/parameters/AlertId"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonObject"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "patch": {
        "tags": [
          "Market"
        ],
        "operationId": "updateCellariaAlert",
        "summary": "Actualiza estado o accion recomendada de una alerta.",
        "parameters": [
          {
            "$ref": "#/components/parameters/AlertId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WatchlistAlertPatch"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonObject"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/v1/market/compare": {
      "get": {
        "tags": [
          "Market"
        ],
        "operationId": "compareCellariaWines",
        "summary": "Comparador agregado multi-vino o multi-bodega.",
        "parameters": [
          {
            "name": "wines",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Lista separada por comas de vinos o bodegas a comparar."
          },
          {
            "$ref": "#/components/parameters/Search"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonObject"
          }
        }
      }
    },
    "/v1/market/export": {
      "get": {
        "tags": [
          "Market"
        ],
        "operationId": "exportMarketCsv",
        "summary": "Export CSV de presencia, pricing, demanda, oportunidades, stock, gaps, calidad, indices, watchlists o comparador.",
        "parameters": [
          {
            "name": "scope",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "presence",
                "pricing",
                "demand",
                "opportunities",
                "stock-risk",
                "gaps",
                "quality",
                "indices",
                "watchlists",
                "compare"
              ]
            }
          },
          {
            "$ref": "#/components/parameters/Search"
          }
        ],
        "responses": {
          "200": {
            "description": "CSV.",
            "content": {
              "text/csv": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/v1/market/data-quality": {
      "get": {
        "tags": [
          "Market"
        ],
        "operationId": "getDataQuality",
        "summary": "Readiness, privacy gates y blockers de dato.",
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonObject"
          }
        }
      }
    },
    "/v1/market/data-contract": {
      "get": {
        "tags": [
          "Market"
        ],
        "operationId": "getDataContract",
        "summary": "Contrato de datos Winerim -> Market.",
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonObject"
          }
        }
      }
    },
    "/v1/market/usage": {
      "get": {
        "tags": [
          "Market"
        ],
        "operationId": "getOwnUsage",
        "summary": "Consumo y billing preview del cliente autenticado.",
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonObject"
          }
        }
      }
    },
    "/v1/market/ask": {
      "post": {
        "tags": [
          "Analyst"
        ],
        "operationId": "askMarketAnalyst",
        "summary": "Pregunta al analista Market.",
        "description": "Devuelve respuesta ejecutiva, evidencia, plan de consulta, paquete de datos recomendado y plantilla de solicitud de informe a medida.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MarketAskRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Respuesta Market Analyst con data pack recomendado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MarketAskResponse"
                }
              }
            }
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          }
        }
      }
    },
    "/v1/market/ask/examples": {
      "get": {
        "tags": [
          "Analyst"
        ],
        "operationId": "listMarketAskExamples",
        "summary": "Ejemplos de preguntas comerciales.",
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonObject"
          }
        }
      }
    },
    "/v1/market/report-packages": {
      "get": {
        "tags": [
          "Reports"
        ],
        "operationId": "listMarketReportPackages",
        "summary": "Catalogo de paquetes de datos e informes vendibles.",
        "description": "Devuelve los paquetes comerciales que convierten una pregunta natural en entregable: fit de mercado, benchmark de PVP, rotacion/stock, ruta comercial o briefing.",
        "parameters": [
          {
            "name": "buyer_type",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "winery",
                "distributor",
                "importer"
              ]
            },
            "description": "Filtra paquetes por tipo de comprador. Si se omite, usa el buyer_type de la API key."
          }
        ],
        "responses": {
          "200": {
            "description": "Paquetes disponibles para el cliente.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReportPackagesResponse"
                }
              }
            }
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          }
        }
      }
    },
    "/v1/market/answers": {
      "get": {
        "tags": [
          "Analyst"
        ],
        "operationId": "listMarketAnswers",
        "summary": "Historial server-side de respuestas Market Analyst del cliente.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonObject"
          }
        }
      }
    },
    "/v1/market/answers/{answer_id}": {
      "get": {
        "tags": [
          "Analyst"
        ],
        "operationId": "getMarketAnswer",
        "summary": "Detalle de una respuesta guardada.",
        "parameters": [
          {
            "$ref": "#/components/parameters/AnswerId"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonObject"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/v1/market/answers/{answer_id}/brief.md": {
      "get": {
        "tags": [
          "Analyst"
        ],
        "operationId": "downloadMarketAnswerBrief",
        "summary": "Descarga una respuesta guardada como brief Markdown.",
        "parameters": [
          {
            "$ref": "#/components/parameters/AnswerId"
          }
        ],
        "responses": {
          "200": {
            "description": "Brief Markdown.",
            "content": {
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/v1/market/report-requests": {
      "get": {
        "tags": [
          "Reports"
        ],
        "operationId": "listMarketReportRequests",
        "summary": "Lista solicitudes custom del cliente autenticado.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonObject"
          },
          "503": {
            "$ref": "#/components/responses/DatabaseRequired"
          }
        }
      },
      "post": {
        "tags": [
          "Reports"
        ],
        "operationId": "createMarketReportRequest",
        "summary": "Crea una solicitud de informe a medida.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReportRequestCreate"
              }
            }
          }
        },
        "responses": {
          "202": {
            "$ref": "#/components/responses/JsonObject"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "503": {
            "$ref": "#/components/responses/DatabaseRequired"
          }
        }
      }
    },
    "/v1/market/report-requests/{request_id}": {
      "get": {
        "tags": [
          "Reports"
        ],
        "operationId": "getMarketReportRequest",
        "summary": "Detalle de una solicitud custom del cliente.",
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonObject"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/v1/ops/summary": {
      "get": {
        "tags": [
          "Ops"
        ],
        "operationId": "getOpsSummary",
        "summary": "Resumen interno de clientes, uso, billing preview, informes y snapshot.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Month"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonObject"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "503": {
            "$ref": "#/components/responses/DatabaseRequired"
          }
        }
      }
    },
    "/v1/ops/clients": {
      "get": {
        "tags": [
          "Ops"
        ],
        "operationId": "listOpsClients",
        "summary": "Auditoria interna de clientes y key prefixes sin secretos.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Status"
          },
          {
            "$ref": "#/components/parameters/BuyerType"
          },
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonObject"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "503": {
            "$ref": "#/components/responses/DatabaseRequired"
          }
        }
      }
    },
    "/v1/ops/clients/{client_id_or_uuid}": {
      "get": {
        "tags": [
          "Ops"
        ],
        "operationId": "getOpsClient",
        "summary": "Detalle operativo de un cliente.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientIdOrUuid"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonObject"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/v1/ops/usage": {
      "get": {
        "tags": [
          "Ops"
        ],
        "operationId": "getOpsUsage",
        "summary": "Auditoria interna de consumo mensual.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Month"
          },
          {
            "$ref": "#/components/parameters/ClientIdQuery"
          },
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonObject"
          },
          "503": {
            "$ref": "#/components/responses/DatabaseRequired"
          }
        }
      }
    },
    "/v1/ops/usage/clients/{client_id_or_uuid}": {
      "get": {
        "tags": [
          "Ops"
        ],
        "operationId": "getOpsClientUsage",
        "summary": "Consumo interno de un cliente concreto.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientIdOrUuid"
          },
          {
            "$ref": "#/components/parameters/Month"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonObject"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/v1/ops/billing-preview": {
      "get": {
        "tags": [
          "Ops"
        ],
        "operationId": "getOpsBillingPreview",
        "summary": "Forecast interno de facturacion por cliente.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Month"
          },
          {
            "$ref": "#/components/parameters/ClientIdQuery"
          },
          {
            "$ref": "#/components/parameters/Status"
          },
          {
            "$ref": "#/components/parameters/BuyerType"
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Format"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonOrCsv"
          },
          "503": {
            "$ref": "#/components/responses/DatabaseRequired"
          }
        }
      }
    },
    "/v1/ops/billing-preview/clients/{client_id_or_uuid}": {
      "get": {
        "tags": [
          "Ops"
        ],
        "operationId": "getOpsClientBillingPreview",
        "summary": "Forecast interno de facturacion para un cliente.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientIdOrUuid"
          },
          {
            "$ref": "#/components/parameters/Month"
          },
          {
            "$ref": "#/components/parameters/Format"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonOrCsv"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/v1/ops/report-requests": {
      "get": {
        "tags": [
          "Ops"
        ],
        "operationId": "listOpsReportRequests",
        "summary": "Cola interna de solicitudes de informes custom.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Status"
          },
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonObject"
          },
          "503": {
            "$ref": "#/components/responses/DatabaseRequired"
          }
        }
      }
    },
    "/v1/ops/report-requests/{request_id}": {
      "get": {
        "tags": [
          "Ops"
        ],
        "operationId": "getOpsReportRequest",
        "summary": "Detalle interno de una solicitud custom.",
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonObject"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "patch": {
        "tags": [
          "Ops"
        ],
        "operationId": "updateOpsReportRequest",
        "summary": "Actualiza estado, prioridad, asignacion, presupuesto o resolucion interna.",
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReportRequestPatch"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonObject"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/v1/ingest/restaurants": {
      "post": {
        "tags": [
          "Ingest"
        ],
        "operationId": "ingestRestaurants",
        "summary": "Ingiere restaurantes anonimizados.",
        "requestBody": {
          "$ref": "#/components/requestBodies/IngestPayload"
        },
        "responses": {
          "202": {
            "$ref": "#/components/responses/JsonObject"
          },
          "503": {
            "$ref": "#/components/responses/DatabaseRequired"
          }
        }
      }
    },
    "/v1/ingest/menus/{menu_id}/wine-list-snapshot": {
      "post": {
        "tags": [
          "Ingest"
        ],
        "operationId": "ingestWineListSnapshot",
        "summary": "Ingiere snapshot de carta.",
        "parameters": [
          {
            "$ref": "#/components/parameters/MenuId"
          }
        ],
        "requestBody": {
          "$ref": "#/components/requestBodies/IngestPayload"
        },
        "responses": {
          "202": {
            "$ref": "#/components/responses/JsonObject"
          }
        }
      }
    },
    "/v1/ingest/menus/{menu_id}/market-snapshot": {
      "post": {
        "tags": [
          "Ingest"
        ],
        "operationId": "ingestMarketSnapshot",
        "summary": "Ingiere snapshot agregado Market.",
        "parameters": [
          {
            "$ref": "#/components/parameters/MenuId"
          }
        ],
        "requestBody": {
          "$ref": "#/components/requestBodies/IngestPayload"
        },
        "responses": {
          "202": {
            "$ref": "#/components/responses/JsonObject"
          }
        }
      }
    },
    "/v1/ingest/menus/{menu_id}/wine-variants-snapshot": {
      "post": {
        "tags": [
          "Ingest"
        ],
        "operationId": "ingestWineVariantsSnapshot",
        "summary": "Ingiere formatos/PVP/coste.",
        "parameters": [
          {
            "$ref": "#/components/parameters/MenuId"
          }
        ],
        "requestBody": {
          "$ref": "#/components/requestBodies/IngestPayload"
        },
        "responses": {
          "202": {
            "$ref": "#/components/responses/JsonObject"
          }
        }
      }
    },
    "/v1/ingest/menus/{menu_id}/stock-snapshot": {
      "post": {
        "tags": [
          "Ingest"
        ],
        "operationId": "ingestStockSnapshot",
        "summary": "Ingiere stock actual.",
        "parameters": [
          {
            "$ref": "#/components/parameters/MenuId"
          }
        ],
        "requestBody": {
          "$ref": "#/components/requestBodies/IngestPayload"
        },
        "responses": {
          "202": {
            "$ref": "#/components/responses/JsonObject"
          }
        }
      }
    },
    "/v1/ingest/menus/{menu_id}/stock-movements": {
      "post": {
        "tags": [
          "Ingest"
        ],
        "operationId": "ingestStockMovements",
        "summary": "Ingiere movimientos de stock.",
        "parameters": [
          {
            "$ref": "#/components/parameters/MenuId"
          }
        ],
        "requestBody": {
          "$ref": "#/components/requestBodies/IngestPayload"
        },
        "responses": {
          "202": {
            "$ref": "#/components/responses/JsonObject"
          }
        }
      }
    },
    "/v1/ingest/menus/{menu_id}/sales-events": {
      "post": {
        "tags": [
          "Ingest"
        ],
        "operationId": "ingestSalesEvents",
        "summary": "Ingiere ventas confirmadas.",
        "parameters": [
          {
            "$ref": "#/components/parameters/MenuId"
          }
        ],
        "requestBody": {
          "$ref": "#/components/requestBodies/IngestPayload"
        },
        "responses": {
          "202": {
            "$ref": "#/components/responses/JsonObject"
          }
        }
      }
    },
    "/v1/ingest/menus/{menu_id}/margin-signals": {
      "post": {
        "tags": [
          "Ingest"
        ],
        "operationId": "ingestMarginSignals",
        "summary": "Ingiere senales de Margenes.",
        "description": "Debe aceptar payload con header de run aunque items este vacio.",
        "parameters": [
          {
            "$ref": "#/components/parameters/MenuId"
          }
        ],
        "requestBody": {
          "$ref": "#/components/requestBodies/IngestPayload"
        },
        "responses": {
          "202": {
            "$ref": "#/components/responses/JsonObject"
          }
        }
      }
    },
    "/v1/ingest/menus/{menu_id}/interaction-events": {
      "post": {
        "tags": [
          "Ingest"
        ],
        "operationId": "ingestInteractionEvents",
        "summary": "Ingiere interacciones de carta digital.",
        "parameters": [
          {
            "$ref": "#/components/parameters/MenuId"
          }
        ],
        "requestBody": {
          "$ref": "#/components/requestBodies/IngestPayload"
        },
        "responses": {
          "202": {
            "$ref": "#/components/responses/JsonObject"
          }
        }
      }
    },
    "/v1/ingest/distributors/{distributor_id}/catalog-snapshot": {
      "post": {
        "tags": [
          "Ingest"
        ],
        "operationId": "ingestDistributorCatalogSnapshot",
        "summary": "Ingiere catalogo de distribuidor.",
        "parameters": [
          {
            "$ref": "#/components/parameters/DistributorId"
          }
        ],
        "requestBody": {
          "$ref": "#/components/requestBodies/IngestPayload"
        },
        "responses": {
          "202": {
            "$ref": "#/components/responses/JsonObject"
          }
        }
      }
    },
    "/v1/market/pilots": {
      "get": {
        "tags": [
          "Pilots"
        ],
        "operationId": "listMarketPilots",
        "summary": "Lista pilotos Cellaria del cliente autenticado.",
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonObject"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      },
      "post": {
        "tags": [
          "Pilots"
        ],
        "operationId": "createMarketPilot",
        "summary": "Crea un piloto Cellaria de 90 dias.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "portfolio_scope"
                ],
                "properties": {
                  "title": {
                    "type": "string"
                  },
                  "buyer_type": {
                    "type": "string",
                    "enum": [
                      "winery",
                      "distributor",
                      "importer",
                      "analyst"
                    ]
                  },
                  "market": {
                    "type": "object",
                    "additionalProperties": true
                  },
                  "portfolio_scope": {
                    "type": "string"
                  },
                  "competitor_set": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "period": {
                    "type": "string",
                    "example": "90d"
                  },
                  "deliverables": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "contact_email": {
                    "type": "string"
                  },
                  "partner_ref": {
                    "type": "string"
                  },
                  "notes": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "$ref": "#/components/responses/JsonObject"
          },
          "400": {
            "$ref": "#/components/responses/JsonObject"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/v1/market/pilots/{pilot_id}": {
      "get": {
        "tags": [
          "Pilots"
        ],
        "operationId": "getMarketPilot",
        "summary": "Obtiene un piloto Cellaria.",
        "parameters": [
          {
            "name": "pilot_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Identificador del piloto Cellaria."
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonObject"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/JsonObject"
          }
        }
      },
      "patch": {
        "tags": [
          "Pilots"
        ],
        "operationId": "updateMarketPilot",
        "summary": "Actualiza estado o scoping de un piloto Cellaria.",
        "parameters": [
          {
            "name": "pilot_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Identificador del piloto Cellaria."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/JsonObject"
          },
          "400": {
            "$ref": "#/components/responses/JsonObject"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/JsonObject"
          }
        }
      }
    },
    "/v1/market/pilots/{pilot_id}/report-request": {
      "post": {
        "tags": [
          "Pilots"
        ],
        "operationId": "createMarketPilotReportRequest",
        "summary": "Convierte un piloto Cellaria en solicitud de informe accionable.",
        "parameters": [
          {
            "name": "pilot_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Identificador del piloto Cellaria."
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": true
              }
            }
          }
        },
        "responses": {
          "202": {
            "$ref": "#/components/responses/JsonObject"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/JsonObject"
          }
        }
      }
    },
    "/v1/market/pilots/{pilot_id}/watchlists/bootstrap": {
      "post": {
        "tags": [
          "Pilots"
        ],
        "operationId": "bootstrapMarketPilotWatchlists",
        "summary": "Crea watchlists iniciales para seguimiento del piloto.",
        "parameters": [
          {
            "name": "pilot_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Identificador del piloto Cellaria."
          }
        ],
        "responses": {
          "201": {
            "$ref": "#/components/responses/JsonObject"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/JsonObject"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key",
        "description": "API key de Market. Las claves se guardan hasheadas en servidor y nunca se devuelven completas."
      }
    },
    "parameters": {
      "Region": {
        "name": "region",
        "in": "query",
        "schema": {
          "type": "string"
        },
        "description": "Region comercial o geografica. Ejemplo: madrid."
      },
      "Segment": {
        "name": "segment",
        "in": "query",
        "schema": {
          "type": "string"
        },
        "description": "Segmento de restaurante cuando exista cobertura suficiente."
      },
      "Period": {
        "name": "period",
        "in": "query",
        "schema": {
          "type": "string",
          "default": "90"
        },
        "description": "Ventana temporal. Ejemplo: 30, 60, 90, 180."
      },
      "Search": {
        "name": "search",
        "in": "query",
        "schema": {
          "type": "string"
        }
      },
      "BuyerType": {
        "name": "buyer_type",
        "in": "query",
        "schema": {
          "type": "string",
          "enum": [
            "winery",
            "distributor",
            "importer",
            "analyst",
            "internal"
          ]
        }
      },
      "Limit": {
        "name": "limit",
        "in": "query",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 500
        }
      },
      "Month": {
        "name": "month",
        "in": "query",
        "schema": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}$"
        },
        "description": "Mes en formato YYYY-MM."
      },
      "Status": {
        "name": "status",
        "in": "query",
        "schema": {
          "type": "string"
        }
      },
      "Format": {
        "name": "format",
        "in": "query",
        "schema": {
          "type": "string",
          "enum": [
            "json",
            "csv"
          ]
        }
      },
      "ClientIdQuery": {
        "name": "client_id",
        "in": "query",
        "schema": {
          "type": "string"
        }
      },
      "ClientIdOrUuid": {
        "name": "client_id_or_uuid",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      },
      "AnswerId": {
        "name": "answer_id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      },
      "RequestId": {
        "name": "request_id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      },
      "WatchlistId": {
        "name": "watchlist_id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      },
      "AlertId": {
        "name": "alert_id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      },
      "MenuId": {
        "name": "menu_id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      },
      "DistributorId": {
        "name": "distributor_id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      }
    },
    "requestBodies": {
      "IngestPayload": {
        "required": true,
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/IngestPayload"
            }
          }
        }
      }
    },
    "responses": {
      "JsonObject": {
        "description": "Respuesta JSON.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/GenericObject"
            }
          }
        }
      },
      "JsonOrCsv": {
        "description": "Respuesta JSON por defecto o CSV con format=csv.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/GenericObject"
            }
          },
          "text/csv": {
            "schema": {
              "type": "string"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "API key ausente o invalida.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Forbidden": {
        "description": "Scope insuficiente.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "BadRequest": {
        "description": "Payload invalido.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "NotFound": {
        "description": "Recurso no encontrado.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "MethodNotAllowed": {
        "description": "Metodo HTTP no permitido.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "DatabaseRequired": {
        "description": "Endpoint requiere MARKET_DATABASE_URL/Postgres.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    },
    "schemas": {
      "GenericObject": {
        "type": "object",
        "additionalProperties": true
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          },
          "message": {
            "type": "string"
          }
        },
        "additionalProperties": true
      },
      "MarketAskRequest": {
        "type": "object",
        "required": [
          "question"
        ],
        "properties": {
          "question": {
            "type": "string",
            "examples": [
              "¿Qué tal se vende Rioja en Madrid?"
            ]
          },
          "region": {
            "type": "string"
          },
          "period": {
            "type": "string"
          },
          "filters": {
            "type": "object",
            "additionalProperties": true
          }
        },
        "additionalProperties": true
      },
      "MarketAskResponse": {
        "type": "object",
        "required": [
          "schema_version",
          "answer_id",
          "question",
          "answer",
          "query_plan",
          "data_pack"
        ],
        "properties": {
          "schema_version": {
            "type": "string",
            "examples": [
              "market_answer_v0.19"
            ]
          },
          "answer_id": {
            "type": "string"
          },
          "question": {
            "type": "string"
          },
          "intent": {
            "type": "string"
          },
          "filters": {
            "type": "object",
            "additionalProperties": true
          },
          "answer": {
            "type": "string"
          },
          "confidence": {
            "type": "number"
          },
          "evidence": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "query_plan": {
            "type": "object",
            "description": "Plan tecnico-comercial: entidades detectadas, endpoints recomendados, datasets y privacidad.",
            "additionalProperties": true
          },
          "data_pack": {
            "type": "object",
            "description": "Paquete recomendado para convertir la respuesta en entregable a medida.",
            "additionalProperties": true
          },
          "report_request_template": {
            "type": "object",
            "description": "Payload sugerido para POST /v1/market/report-requests.",
            "additionalProperties": true
          },
          "billing": {
            "type": "object",
            "additionalProperties": true
          }
        },
        "additionalProperties": true
      },
      "ReportPackage": {
        "type": "object",
        "required": [
          "id",
          "intent",
          "name",
          "buyers",
          "starting_quote_cents",
          "required_datasets",
          "recommended_endpoints"
        ],
        "properties": {
          "id": {
            "type": "string",
            "examples": [
              "wine_fit_report"
            ]
          },
          "intent": {
            "type": "string",
            "examples": [
              "wine_performance"
            ]
          },
          "name": {
            "type": "string"
          },
          "summary": {
            "type": "string"
          },
          "buyers": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "package_type": {
            "type": "string"
          },
          "starting_quote_cents": {
            "type": "integer",
            "minimum": 0
          },
          "currency": {
            "type": "string"
          },
          "delivery_sla": {
            "type": "string"
          },
          "recommended_endpoints": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "required_datasets": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "deliverables": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sample_questions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "privacy_gate": {
            "type": "string"
          }
        },
        "additionalProperties": true
      },
      "ReportPackagesResponse": {
        "type": "object",
        "required": [
          "schema_version",
          "packages"
        ],
        "properties": {
          "schema_version": {
            "type": "string",
            "examples": [
              "market_report_packages_v0.20"
            ]
          },
          "generated_at": {
            "type": "string"
          },
          "buyer_type": {
            "type": "string"
          },
          "packages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ReportPackage"
            }
          }
        },
        "additionalProperties": true
      },
      "ReportRequestCreate": {
        "type": "object",
        "required": [
          "question"
        ],
        "properties": {
          "title": {
            "type": "string"
          },
          "question": {
            "type": "string"
          },
          "requested_scope": {
            "type": "string"
          },
          "region": {
            "type": "string"
          },
          "wine_or_category": {
            "type": "string"
          },
          "period": {
            "type": "string"
          },
          "priority": {
            "type": "string",
            "enum": [
              "low",
              "normal",
              "high"
            ]
          },
          "contact_email": {
            "type": "string"
          },
          "notes": {
            "type": "string"
          }
        },
        "additionalProperties": true
      },
      "ReportRequestPatch": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "submitted",
              "scoping",
              "quoted",
              "in_progress",
              "delivered",
              "rejected"
            ]
          },
          "priority": {
            "type": "string",
            "enum": [
              "low",
              "normal",
              "high"
            ]
          },
          "notes": {
            "type": "string"
          },
          "internal_notes": {
            "type": "string"
          },
          "assigned_to": {
            "type": "string"
          },
          "quoted_amount_cents": {
            "type": "integer",
            "minimum": 0
          },
          "resolution_payload": {
            "type": "object",
            "additionalProperties": true
          }
        },
        "additionalProperties": false
      },
      "WatchlistCreate": {
        "type": "object",
        "required": [
          "title"
        ],
        "properties": {
          "title": {
            "type": "string"
          },
          "subject": {
            "type": "string"
          },
          "buyer_type": {
            "type": "string",
            "enum": [
              "winery",
              "distributor",
              "importer",
              "analyst"
            ]
          },
          "filters": {
            "type": "object",
            "additionalProperties": true
          },
          "metrics": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "cadence": {
            "type": "string",
            "enum": [
              "daily",
              "weekly",
              "monthly"
            ]
          },
          "trigger_rule": {
            "type": "string"
          },
          "last_signal": {
            "type": "string"
          }
        },
        "additionalProperties": true
      },
      "WatchlistPatch": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "paused",
              "archived"
            ]
          },
          "cadence": {
            "type": "string",
            "enum": [
              "daily",
              "weekly",
              "monthly"
            ]
          },
          "trigger_rule": {
            "type": "string"
          },
          "filters": {
            "type": "object",
            "additionalProperties": true
          },
          "metrics": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "additionalProperties": false
      },
      "WatchlistAlertPatch": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "new",
              "acknowledged",
              "converted_to_report",
              "dismissed"
            ]
          },
          "recommended_action": {
            "type": "string"
          }
        },
        "additionalProperties": false
      },
      "IngestPayload": {
        "type": "object",
        "required": [
          "schema_version",
          "generated_at"
        ],
        "properties": {
          "schema_version": {
            "type": "string"
          },
          "generated_at": {
            "type": "string"
          },
          "source_name": {
            "type": "string"
          },
          "lineage": {
            "type": "object",
            "additionalProperties": true
          },
          "items": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "rows": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          }
        },
        "additionalProperties": true
      }
    }
  }
}
