{
  "openapi": "3.1.0",
  "info": {
    "title": "TECNOPLAY STORE API pública",
    "version": "1.0.0",
    "description": "API pública de catálogo y solicitudes de cotización de TECNOPLAY STORE. Los datos de productos y precios son dinámicos.",
    "contact": {
      "url": "https://tecnoplaystore.win/developers/"
    }
  },
  "x-api-versioning": {
    "strategy": "URL path",
    "currentVersion": "v1",
    "canonicalBasePath": "/api/v1/public/web",
    "legacyBasePath": "/api/public/web",
    "legacyPolicy": "The legacy path remains available for compatibility and returns Deprecation: true plus a successor-version Link header."
  },
  "servers": [
    {
      "url": "https://tecnoplaystore.win",
      "description": "API pública"
    }
  ],
  "tags": [
    {
      "name": "Catálogo",
      "description": "Consulta de vitrinas y productos publicados"
    },
    {
      "name": "Solicitudes",
      "description": "Solicitudes de cotización o pedido"
    }
  ],
  "paths": {
    "/api/public/web": {
      "get": {
        "operationId": "listPublicStores",
        "summary": "Lista vitrinas públicas activas",
        "tags": ["Catálogo"],
        "responses": {
          "200": {
            "description": "Vitrinas activas",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": ["ok", "vitrinas"],
                  "properties": {
                    "ok": { "type": "boolean", "const": true },
                    "vitrinas": {
                      "type": "array",
                      "items": { "$ref": "#/components/schemas/StoreSummary" }
                    }
                  }
                }
              }
            }
          },
          "429": { "$ref": "#/components/responses/TooManyRequests" },
          "500": { "$ref": "#/components/responses/InternalError" }
        }
      }
    },
    "/api/public/web/by-host/{host}": {
      "get": {
        "operationId": "getStoreByHost",
        "summary": "Obtiene la vitrina asociada a un dominio",
        "tags": ["Catálogo"],
        "parameters": [
          {
            "name": "host",
            "in": "path",
            "required": true,
            "description": "Dominio público, por ejemplo tecnoplaystore.win",
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": {
            "description": "Vitrina pública",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/StoreResponse" }
              }
            }
          },
          "404": { "$ref": "#/components/responses/NotFound" }
          ,
          "429": { "$ref": "#/components/responses/TooManyRequests" },
          "500": { "$ref": "#/components/responses/InternalError" }
        }
      }
    },
    "/api/public/web/{slug}": {
      "get": {
        "operationId": "getStore",
        "summary": "Obtiene una vitrina pública y su catálogo inicial",
        "tags": ["Catálogo"],
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "description": "Slug, código o dominio de la vitrina",
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": {
            "description": "Vitrina pública",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/StoreResponse" }
              }
            }
          },
          "404": { "$ref": "#/components/responses/NotFound" }
          ,
          "429": { "$ref": "#/components/responses/TooManyRequests" },
          "500": { "$ref": "#/components/responses/InternalError" }
        }
      }
    },
    "/api/public/web/{slug}/productos": {
      "get": {
        "operationId": "listProducts",
        "summary": "Busca productos publicados",
        "tags": ["Catálogo"],
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": { "type": "string" }
          },
          {
            "name": "q",
            "in": "query",
            "description": "Texto de búsqueda",
            "schema": { "type": "string" }
          },
          {
            "name": "familia",
            "in": "query",
            "schema": { "type": "string" }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": { "type": "integer", "minimum": 1, "maximum": 200, "default": 15 }
          },
          {
            "name": "offset",
            "in": "query",
            "schema": { "type": "integer", "minimum": 0, "default": 0 }
          }
        ],
        "responses": {
          "200": {
            "description": "Página de productos",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": ["ok", "productos", "total"],
                  "properties": {
                    "ok": { "type": "boolean", "const": true },
                    "productos": {
                      "type": "array",
                      "items": { "$ref": "#/components/schemas/Product" }
                    },
                    "total": { "type": "integer" },
                    "limit": { "type": "integer" },
                    "offset": { "type": "integer" }
                  }
                }
              }
            }
          },
          "404": { "$ref": "#/components/responses/NotFound" }
          ,
          "429": { "$ref": "#/components/responses/TooManyRequests" },
          "500": { "$ref": "#/components/responses/InternalError" }
        }
      }
    },
    "/api/public/web/{slug}/solicitud": {
      "post": {
        "operationId": "createOrderRequest",
        "summary": "Registra una solicitud de cotización o pedido",
        "tags": ["Solicitudes"],
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/OrderRequest" },
              "example": {
                "nombre_cliente": "Ana López",
                "telefono": "9999-9999",
                "notas": "Consultar entrega en Tocoa",
                "items": [
                  { "ccproducto": "CEL-001", "cantidad": 1 }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Solicitud registrada",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/OrderResponse" }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "429": { "$ref": "#/components/responses/TooManyRequests" },
          "500": { "$ref": "#/components/responses/InternalError" }
        }
      }
    },
    "/api/public/web/sitemap.xml": {
      "get": {
        "operationId": "getPublicSitemap",
        "summary": "Obtiene el sitemap XML de vitrinas y productos",
        "tags": ["Catálogo"],
        "responses": {
          "200": {
            "description": "Sitemap XML",
            "content": {
              "application/xml": {
                "schema": { "type": "string" }
              }
            }
          },
          "429": { "$ref": "#/components/responses/TooManyRequests" },
          "500": { "$ref": "#/components/responses/InternalError" }
        }
      }
    },
    "/api/v1/public/web": {
      "$ref": "#/paths/~1api~1public~1web"
    },
    "/api/v1/public/web/by-host/{host}": {
      "$ref": "#/paths/~1api~1public~1web~1by-host~1{host}"
    },
    "/api/v1/public/web/{slug}": {
      "$ref": "#/paths/~1api~1public~1web~1{slug}"
    },
    "/api/v1/public/web/{slug}/productos": {
      "$ref": "#/paths/~1api~1public~1web~1{slug}~1productos"
    },
    "/api/v1/public/web/{slug}/solicitud": {
      "$ref": "#/paths/~1api~1public~1web~1{slug}~1solicitud"
    },
    "/api/v1/public/web/sitemap.xml": {
      "$ref": "#/paths/~1api~1public~1web~1sitemap.xml"
    }
  },
  "components": {
    "responses": {
      "BadRequest": {
        "description": "Solicitud inválida",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/ErrorResponse" }
          }
        }
      },
      "NotFound": {
        "description": "Vitrina o recurso no encontrado",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/ErrorResponse" }
          }
        }
      },
      "InternalError": {
        "description": "Error interno del servidor",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/ErrorResponse" }
          }
        }
      },
      "TooManyRequests": {
        "description": "Límite de solicitudes excedido",
        "headers": {
          "RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" },
          "RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" },
          "RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" },
          "Retry-After": { "$ref": "#/components/headers/RetryAfter" }
        },
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/ErrorResponse" }
          }
        }
      }
    },
    "headers": {
      "RateLimitLimit": {
        "description": "Límite de solicitudes en la ventana actual (RFC 9333).",
        "schema": { "type": "integer" }
      },
      "RateLimitRemaining": {
        "description": "Solicitudes restantes en la ventana actual (RFC 9333).",
        "schema": { "type": "integer" }
      },
      "RateLimitReset": {
        "description": "Segundos hasta el reinicio de la ventana (RFC 9333).",
        "schema": { "type": "integer" }
      },
      "RetryAfter": {
        "description": "Segundos que debe esperar el cliente después de un 429.",
        "schema": { "type": "integer" }
      }
    },
    "schemas": {
      "ErrorResponse": {
        "type": "object",
        "required": ["ok", "code", "message"],
        "properties": {
          "ok": { "type": "boolean", "const": false },
          "code": { "type": "string", "description": "Código estable para manejo programático." },
          "message": { "type": "string", "description": "Mensaje legible para personas." },
          "error": {
            "type": "string",
            "deprecated": true,
            "description": "Alias de compatibilidad; usa message."
          },
          "details": { "type": "object", "additionalProperties": true }
        },
        "additionalProperties": false
      },
      "StoreSummary": {
        "type": "object",
        "properties": {
          "slug": { "type": "string" },
          "marca": { "type": "string" },
          "codigo": { "type": ["string", "null"] },
          "plantilla_rubro": { "type": "string" },
          "dominio_publico": { "type": ["string", "null"] }
        }
      },
      "StoreResponse": {
        "type": "object",
        "required": ["ok", "slug", "marca", "productos"],
        "properties": {
          "ok": { "type": "boolean", "const": true },
          "slug": { "type": "string" },
          "marca": { "type": "string" },
          "eslogan": { "type": "string" },
          "meta_descripcion": { "type": "string" },
          "productos_total": { "type": "integer" },
          "productos": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/Product" }
          },
          "empresa": { "type": "object", "additionalProperties": true },
          "promociones": { "type": "array", "items": { "type": "object" } },
          "servicios": { "type": "array", "items": { "type": "object" } }
        }
      },
      "Product": {
        "type": "object",
        "required": ["ccproducto", "articulo"],
        "properties": {
          "ccproducto": { "type": "string" },
          "articulo": { "type": "string" },
          "categoria": { "type": "string" },
          "familia": { "type": "string" },
          "descripcion": { "type": "string" },
          "precio": { "type": ["number", "null"] },
          "existencias": { "type": ["number", "null"] },
          "imagen_url": { "type": ["string", "null"], "format": "uri-reference" }
        }
      },
      "OrderItem": {
        "type": "object",
        "required": ["ccproducto"],
        "properties": {
          "ccproducto": { "type": "string" },
          "cantidad": { "type": "number", "exclusiveMinimum": 0 },
          "precio": { "type": "number" }
        }
      },
      "OrderRequest": {
        "type": "object",
        "required": ["nombre_cliente", "items"],
        "properties": {
          "nombre_cliente": { "type": "string", "minLength": 1 },
          "telefono": { "type": "string" },
          "email": { "type": "string", "format": "email" },
          "notas": { "type": "string" },
          "canal": { "type": "string", "enum": ["web", "whatsapp"] },
          "items": {
            "type": "array",
            "minItems": 1,
            "items": { "$ref": "#/components/schemas/OrderItem" }
          }
        }
      },
      "OrderResponse": {
        "type": "object",
        "required": ["ok", "mensaje", "solicitud"],
        "properties": {
          "ok": { "type": "boolean", "const": true },
          "mensaje": { "type": "string" },
          "solicitud": {
            "type": "object",
            "properties": {
              "id": { "type": "integer" },
              "estado": { "type": "string" },
              "total_estimado": { "type": ["number", "null"] },
              "items": { "type": "array", "items": { "type": "object" } }
            }
          },
          "wa_url": { "type": ["string", "null"], "format": "uri" }
        }
      }
    }
  }
}
