openapi: 3.1.0
info:
  title: API Vendizap
  version: "1.0.0"
  summary: Integre seu sistema ERP com o Vendizap utilizando a API oficial.
  description: |
    # Introdução

    A API do Vendizap permite uma integração com qualquer plataforma que consiga
    fazer requisições **HTTP**. Nela é possível realizar os cadastros que existem
    dentro da plataforma, além de atualização de estoque e recebimento de pedidos
    através de webhook.

    # Autenticação

    Para o [Vendizap](https://vendizap.com) identificar qual é o usuário que está
    se comunicando com a API, é necessário que este usuário configure e ative uma
    integração no submenu **Integrações** do menu **Configurar** do Vendizap.
    Nesta tela será fornecido um **Id** e um **Secret** que serão utilizados em
    todas as requisições como forma de identificação e autenticação do usuário,
    respectivamente. Esses dados deverão ser enviados no header como no exemplo
    abaixo:

    ## Header

    ```
    X-Auth-Id: 4754521
    X-Auth-Secret: ChpATl7F?Wi5jmfZnQy1LgJXeq0a8V%@
    User-Agent: NomeDoSeuSistema/1.0
    ```

    > _"Lembrando que os dados acima não são válidos, são apenas um exemplo."_

    ### User-Agent

    Envie sempre o header `User-Agent` informando o **nome do sistema** que
    está integrando com a API (e, de preferência, a versão). Esse header é
    utilizado para identificar a origem das requisições, facilitar o suporte
    e diagnosticar problemas de integração.

    Formato recomendado:

    ```
    User-Agent: NomeDoSistema/Versao
    ```

    Exemplos:

    ```
    User-Agent: MeuERP/2.4.1
    ```

    # Retornos

    O retorno dos métodos será sempre no formato **JSON** em caso de sucesso e
    com o respectivo **HTTP Status Code**, que poderá ser um dos seguintes:

    | HTTP Code | Nome         | Descrição                                                                                                                                |
    | --------- | ------------ | ---------------------------------------------------------------------------------------------------------------------------------------- |
    | 200       | Success      | Sucesso na requisição solicitada acompanhado do respectivo retorno                                                                       |
    | 201       | Created      | Sucesso ao inserir um novo registro através dos métodos POST acompanhado do respectivo **ID** e possíveis erros                          |
    | 400       | Bad Request  | Erro na requisição que não foi possível ser completada, acompanhada do respectivo erro (nesses casos o erro será retornado em uma string e não em JSON) |
    | 401       | Unauthorized | Credenciais informadas inválidas                                                                                                         |

    # Limites de requisição

    Cada IP será avaliado de forma individual e, caso envie muitas requisições
    para o servidor, esse IP pode ser temporariamente bloqueado.

    **Limites por assinatura do cliente:**

    Na Vendizap existem dois planos que dão acesso à API, porém os limites de
    requisições em cada plano são diferentes:

    - **Plano Profissional**: 150 requisições a cada hora.
    - **Plano Empresarial**: Não há limite por hora, mas não impede que o IP
      seja temporariamente bloqueado, caso envie muitas requisições seguidas.

servers:
  - url: https://app.vendizap.com/api
    description: Produção

security:
  - AuthId: []
    AuthSecret: []

tags:
  - name: Categorias
    description: |
      Métodos utilizados para manutenção das categorias utilizadas nos produtos.

      ## Categoria

      | Nome   | Tipo        | Required | Descrição                                                                                       |
      | ------ | ----------- | -------- | ----------------------------------------------------------------------------------------------- |
      | nome   | string      | Sim      | Nome da categoria (deve ser único)                                                              |
      | imagem | base64/Url  | Não      | Imagem da categoria. Pode ser enviada em base64 ou via Url                                      |
      | codigo | string      | Não      | Código da categoria. Pode ser usado para buscar, listar ou atualizar categorias no lugar do Id. |
  - name: Variações
    description: |
      Métodos utilizados para manutenção das variações utilizadas nos produtos.
      Uma variação pode ser entendida como um grupo que contém características
      que alteram o produto de acordo com essa classificação. Alguns exemplos
      de variações: Tamanho, Cor, Sabor, Cobertura, Adicional.

      ## Variação

      | Nome       | Tipo             | Required | Descrição                                                                       |
      | ---------- | ---------------- | -------- | ------------------------------------------------------------------------------- |
      | nome       | string           | Sim      | Nome da variação (deve ser único)                                               |
      | variaveis  | Array de Objetos | Sim      | Variáveis que compõem a variação. Uma variação deve ter pelo menos uma variável.|
      | utilizaCor | boolean          | Não      | Indica se as variáveis dessa variação utilizam cores.                           |
  - name: Variáveis
    description: |
      Métodos utilizados para manutenção das variáveis pertencentes às variações.
      Uma variável pode ser entendida como uma característica que altera o
      produto ou um adicional, e pode ser vendida separadamente de acordo com
      essa característica. Essa variável deve pertencer a uma variação, que é o
      que agrupa essas variáveis de acordo com a sua classificação. Exemplo de
      variáveis pertencentes à variação "Tamanho": PP, P, M, G, GG.

      Todos os métodos abaixo devem ser acompanhados do **ID** da **variação**
      à qual a respectiva variável pertence.

      ## Variável

      | Nome | Tipo   | Required | Descrição                                                                                                                                                                                                          |
      | ---- | ------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
      | nome | string | Sim      | Nome da variável (deve ser único dentro da mesma variação)                                                                                                                                                         |
      | cor  | string | Não      | Indica quais serão a cor ou cores da variável. Necessita que a variação esteja com o atributo `utilizaCor` como `true`. Aceita cores em formato hex nestes formatos: `#000000` ou `#000000|#FFFFFF` para duas cores. |
  - name: Produtos
    description: |
      Métodos utilizados para manutenção dos produtos.

      ## Produto

      | Nome         | Tipo                | Required | Descrição                                                                                                                                                                                                                                                                                                |
      | ------------ | ------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
      | descricao    | string              | Sim      | Descrição do produto                                                                                                                                                                                                                                                                                     |
      | preco        | number              | Não      | Valor do produto                                                                                                                                                                                                                                                                                          |
      | promocao     | Object              | Não      | Informações de promoção para o produto. Objeto de promoção abaixo.                                                                                                                                                                                                                                       |
      | imagens      | Array de base64/Url | Não      | Array contendo todas as imagens do produto, com limite de acordo com o plano do usuário. As imagens poderão ser recebidas em uma string com a Url ou base64 e serão inseridas na ordem enviada, a primeira será a capa do produto                                                                       |
      | detalhes     | string              | Não      | Detalhes adicionais do produto, descrição completa                                                                                                                                                                                                                                                       |
      | categorias   | Array de IDs        | Não      | Array com strings contendo os IDs de todas as categorias às quais o produto pertence                                                                                                                                                                                                                     |
      | variacoes    | Array de Variações  | Não      | Array contendo os objetos das variações do produto. Segue abaixo o modelo deste objeto.                                                                                                                                                                                                                  |
      | unidadeVenda | string              | Não      | Unidade a ser utilizada na venda do produto. Deve ser uma das seguintes unidades: `["Unidade", "Caixa", "Pacote", "Peça", "Quilo", "Porção", "Pedaço", "Metro", "Par", "Jogo"]`. Caso nenhuma seja informada ou seja diferente de uma dessas, será cadastrada com a padrão "Unidade".                  |
      | unidadePreco | string              | Não      | Unidade a ser utilizada no preço do produto. Ex: Produto com preço por Kg mas que é vendido por Peça. Deve ser uma das mesmas unidades de `unidadeVenda`. Caso nenhuma seja informada, será cadastrada com a padrão "Unidade".                                                                            |
      | codigo       | string              | Não      | Código correspondente ao produto no ERP                                                                                                                                                                                                                                                                  |
      | qtdeMinima   | number              | Não      | Quantidade mínima do produto na venda                                                                                                                                                                                                                                                                    |
      | qtdeMaxima   | number              | Não      | Quantidade máxima do produto na venda                                                                                                                                                                                                                                                                    |
      | exibir       | bool                | Não      | Exibe ou não o produto na vitrine (corresponde a ativo/inativo). Padrão: `true`                                                                                                                                                                                                                          |
      | destaque     | bool                | Não      | Indica se o produto será exibido nos destaques da vitrine. Padrão: `false`                                                                                                                                                                                                                               |

      ### Variação (dentro do produto)

      | Nome             | Tipo                | Required | Descrição                                                                                                                  |
      | ---------------- | ------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------- |
      | id               | string              | Sim      | ID da variação que deve ser vinculada ao produto                                                                           |
      | obrigatoria      | bool                | Não      | Define se a variação é obrigatória na venda do produto. _Padrão: `true`_                                                   |
      | multipla_selecao | bool                | Não      | Define se a variação é múltipla, ou seja, permite informar mais de uma para um mesmo produto. _Padrão: `false`_            |
      | adicional        | bool                | Não      | Define se a variação é um adicional do produto. _Padrão: `false`_                                                          |
      | qtdeMinima       | number              | Não      | Define a quantidade mínima que deve ser informada na venda para adicionar ao produto. _Padrão: 0_                          |
      | qtdeMaxima       | number              | Não      | Define a quantidade máxima que pode ser selecionada da variação na venda para o produto. _Padrão: 0_                       |
      | variaveis        | Array de Variáveis  | Sim      | Array de objetos das variáveis pertencentes à variação que serão vinculadas para esse produto. Segue objeto de variável abaixo |

      ### Variável (dentro do produto)

      | Nome   | Tipo    | Required | Descrição                                                                                                                                                                                                                                                                                                                |
      | ------ | ------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
      | id     | string  | Sim      | ID da variável que deve ser vinculada à variação para o produto.                                                                                                                                                                                                                                                         |
      | preco  | number  | Não      | Valor adicional que pode ser informado para a variável. Este valor será somado ao valor do produto caso seja selecionada essa variável. _Padrão: 0_                                                                                                                                                                      |
      | imagem | integer | Não      | Índice referente à imagem do produto para esta variável. Ou seja, será mostrada uma das imagens do produto quando selecionada essa variável. O número informado deve se referir à posição de uma das imagens do produto na ordem em que estão cadastradas (inicia em 0). Ex.: para vincular a primeira foto, informe 0. |

      ### Combinações (Opcional)

      Uma combinação é a junção de todas as variações do produto, relacionando
      todas as variáveis entre si, utilizada para definir código (sku), preço
      e/ou EAN (código de barras) para um relacionamento de variações e variáveis (por exemplo, Tamanho P
      e Cor Azul).

      | Nome       | Tipo   | Required               | Descrição                                                                                                                |
      | ---------- | ------ | ---------------------- | ------------------------------------------------------------------------------------------------------------------------ |
      | combinacao | array  | Sim                    | Array de objetos, contendo as variações e variáveis que compõem a combinação                                             |
      | variacao   | string | Sim                    | Será enviado dentro do array de combinação e deve receber o ID ou o Nome da variação                                     |
      | variavel   | string | Sim                    | Será enviado dentro do array de combinação e deve receber o ID ou o Nome da variável                                     |
      | codigo     | string | Não (se houver preço)  | Campo de código de identificação da combinação em outro sistema.                                                         |
      | preco      | number | Não (se houver código) | Caso a combinação tenha um preço diferente das demais, pode ser informado o preço específico para ela.                  |
      | ean        | string | Não                    | Código de barras (EAN/GTIN) da combinação. Opcional.                                                                     |

      ### Promoção

      | Nome             | Tipo     | Required | Descrição                                                                                                                              |
      | ---------------- | -------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------- |
      | dataHoraInicio   | DateTime | Não      | String com a data e hora de início da promoção (Formato: `YYYY-mm-dd HH:MM:SS`)                                                        |
      | dataHoraFim      | DateTime | Não      | String com a data e hora de encerramento da promoção (Formato: `YYYY-mm-dd HH:MM:SS`)                                                  |
      | percentual       | number   | Sim      | Percentual da promoção aplicado sobre o preço do produto (caso seja informado o `precoPromocional`, este campo não é obrigatório)      |
      | precoPromocional | number   | Não      | Valor promocional do produto.                                                                                                          |
  - name: Estoque
    description: Métodos utilizados para atualização de estoque do produto.
  - name: Pedidos
    description: |
      Os pedidos gerados através do Vendizap serão notificados através da URL
      de Webhook cadastrada na integração através da plataforma. Desta forma,
      só será possível buscar o pedido completo através do **ID** do mesmo,
      que constará nessa notificação. A notificação será disparada nas
      seguintes ocorrências do pedido:

      ## Operações da notificação de pedido

      | Operação              | Descrição                                                       |
      | --------------------- | --------------------------------------------------------------- |
      | criado                | Quando um novo pedido for criado na plataforma                  |
      | pagamento_confirmado  | Quando o pagamento do pedido for confirmado.                    |
      | pagamento_cancelado   | Quando o pagamento do pedido for cancelado.                     |
      | cancelado             | Quando o pedido for cancelado.                                  |
      | recuperado            | Quando um pedido que estava cancelado foi reaberto (recuperado).|

      Os dados da notificação são enviados para o webhook em POST no formato
      JSON. Segue um exemplo dos dados enviados na chamada da URL cadastrada
      no webhook:

      ```json
      {
        "client_id": "451234",
        "objeto": "pedidos",
        "operacao": "criado",
        "dataHoraOperacao": "2021-03-08 17:01:45",
        "id": "60467e6380e5ef19bc2da1d3",
        "resource": "https://app.vendizap.com/api/pedidos/60467e6380e5ef19bc2da1d3"
      }
      ```

      O **client_id** refere-se ao identificador da integração que identifica o
      cliente. O **id** refere-se ao id do pedido, que pode ser acessado através
      do link no **resource**, que é o método descrito abaixo, no qual é
      possível obter o pedido completo.

      ## Parâmetros de consulta

      | Operação             | Descrição                                                                                                                          |
      | -------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
      | tipoData             | `criacao` (padrão) → Filtra os pedidos pela data em que foram criados.<br>`atualizacao` → Filtra pela data da última modificação.  |
      | dataInicial          | Enviar data e hora no formato `DD/MM/YYYY HH:MM:SS`                                                                                |
      | dataFinal            | Enviar data e hora no formato `DD/MM/YYYY HH:MM:SS`                                                                                |
      | cancelados           | Booleano; indica se deve ou não retornar pedidos cancelados                                                                        |
      | consultarVendedores  | Indica se deve ou não retornar pedidos das contas de vendedores vinculados.                                                        |
      | skip                 | Quantidade de registros a serem ignorados (paginação)                                                                              |
  - name: Produto Variações
    description: |
      Métodos utilizados para dar manutenção nas variações vinculadas a um
      determinado produto. Veja a seção de **Produtos** para ver a descrição
      dos campos do objeto de variação do produto, pois deverá ser informado
      da mesma maneira aqui.

      Todos os métodos dessa seção devem obrigatoriamente informar o
      `produtoId` na URL, pois são utilizados para um produto em específico.

      **Validações:**

      1. Uma variação opcional (`obrigatoria = false`) e múltipla seleção
         (`multipla_selecao = true`) deve **obrigatoriamente** ser um
         adicional (`adicional = true`). Caso seja informado o `adicional`
         como `false` ou não seja informado, será automaticamente cadastrado
         como adicional (`adicional = true`).
      2. Uma variação obrigatória (`obrigatoria = true`) e múltipla seleção
         (`multipla_selecao = true`) deve ter uma quantidade mínima maior ou
         igual a 1. Caso não seja informada uma quantidade mínima maior ou
         igual a 1, será automaticamente cadastrada com quantidade mínima 1.

      **ATENÇÃO:** A alteração de variações do produto pode impactar
      diretamente no estoque. Portanto, caso seja feita alguma alteração que
      mude a forma como é controlado o estoque, todo o estoque do produto
      será zerado.
  - name: Produto Variáveis
    description: |
      Métodos utilizados para dar manutenção nas variáveis vinculadas a uma
      variação de um determinado produto. Veja a seção de **Produtos** para
      ver a descrição dos campos do objeto de variável da variação, pois
      deverá ser informado da mesma maneira aqui.

      Todos os métodos dessa seção devem obrigatoriamente informar o
      `produtoId` e a `variacaoId` na URL, pois são utilizados para uma
      variação de um produto em específico.
  - name: Produto Combinações
    description: |
      Métodos utilizados para dar manutenção nas combinações do produto.

      Uma combinação é a junção de todas as variações do produto,
      relacionando todas as variáveis entre si.

      Exemplo: Um produto que possua variações `[Tamanho, Cor]`, variáveis
      `[P, G]` e `[Azul, Branco]` gera as seguintes combinações:

      - P / Azul
      - P / Branco
      - G / Azul
      - G / Branco

      Através das combinações é possível personalizar código (SKU), preço e/ou
      EAN (código de barras) de todos os relacionamentos possíveis do produto.
  - name: Usuário
    description: Este endpoint retorna as informações do usuário autenticado.
  - name: Descontos Progressivos
    description: |
      Métodos para gerenciar preços de atacado. Um preço de atacado aplica uma porcentagem de desconto
      sobre o preço unitário do produto ou sobre o total do pedido, conforme faixas de
      quantidade ou de valor.

      ## Tipos

      | tipo      | Quando aplicar                                                                                  |
      | --------- | ----------------------------------------------------------------------------------------------- |
      | produto   | Desconto no preço unitário, podendo abranger todos os produtos, uma lista de produtos, ou categorias. |
      | pedido    | Desconto no valor total do pedido. Só é permitido **um** registro ativo do tipo `pedido` por lojista. |

      ## Faixas

      O desconto se aplica por faixas crescentes. Cada item de `faixaQuantidadeLista`
      ou `faixaPrecoLista` define o limiar (`aPartirDe`) e o desconto em porcentagem (`percentualDesconto`).
      Ao menos uma das duas faixas (`faixaQuantidade` ou `faixaPreco`) deve estar ativa.

      ## Referência de produtos e categorias

      Quando `tipoFiltro="produtos"`, cada item de `produtos` pode ser referenciado por
      `id` ou por `codigo` (SKU). Quando `tipoFiltro="categorias"`, cada item de
      `categorias` pode ser o ID ou o código da categoria. Somente categorias raiz são
      aceitas — descendentes são incluídos automaticamente.

components:
  securitySchemes:
    AuthId:
      type: apiKey
      in: header
      name: X-Auth-Id
      description: ID da integração fornecido no submenu Integrações da plataforma Vendizap.
    AuthSecret:
      type: apiKey
      in: header
      name: X-Auth-Secret
      description: Secret da integração fornecido no submenu Integrações da plataforma Vendizap.

  parameters:
    CategoriaIdPath:
      name: categoriaId
      in: path
      required: true
      description: ID ou Código da categoria.
      schema:
        type: string
      example: "6048f2b4b6fa7c28844582d5"
    VariacaoIdPath:
      name: variacaoId
      in: path
      required: true
      description: ID da variação.
      schema:
        type: string
      example: "6037d8bb6df10513fb742d37"
    VariavelIdPath:
      name: variavelId
      in: path
      required: true
      description: ID da variável.
      schema:
        type: string
      example: "4437d8bb6df10513fb742d88"
    ProdutoIdPath:
      name: produtoId
      in: path
      required: true
      description: ID do produto.
      schema:
        type: string
      example: "6682f7b065be87123fd4d157"
    PedidoIdPath:
      name: pedidoId
      in: path
      required: true
      description: ID do pedido.
      schema:
        type: string
      example: "457d8bb6df10513fb742d32"
    CombinacaoIdOuCodigoPath:
      name: combinacaoId_Codigo
      in: path
      required: true
      description: ID ou Código (SKU) da combinação.
      schema:
        type: string
      example: "idOuCodigo"
    DescontoProgressivoIdPath:
      name: descontoProgressivoId
      in: path
      required: true
      description: ID do preço de atacado.
      schema:
        type: string
      example: "6a07661f4ef4d311179c988a"

  schemas:
    # ---------------------------------------------------------------- Categorias
    CategoriaCreate:
      type: object
      required: [nome]
      properties:
        nome:
          type: string
          description: Nome da categoria (deve ser único).
          example: "Utensílios"
        imagem:
          type: string
          description: Imagem da categoria. Pode ser enviada em base64 ou via URL.
          example: "https://www.vendizap.com/wp-content/themes/startit/assets/img/logo.png"
        codigo:
          type: string
          description: Código da categoria. Pode ser usado para buscar, listar ou atualizar categorias no lugar do Id.
          example: "api"
    CategoriaUpdate:
      type: object
      properties:
        nome:
          type: string
        imagem:
          type: string
          example: "https://play-lh.googleusercontent.com/sVm17jdr0Zp96sKyL8wiXoV_oBsvX92wK-4UN4Fu3quA7GHNUEqkVT1xkcmAolY9O8k"
        codigo:
          type: string
          example: "1234"
    Categoria:
      type: object
      properties:
        id:
          type: string
          example: "6048f2b4b6fa7c28844582d5"
        nome:
          type: string
          example: "Utensílios"
        codigo:
          type: string
          example: "12234"
        imagem:
          type: string
          example: "https://minio.vendizap.com/vendizap-categorias/550a0eb3812c3e44071a03ea13cb0170.jpg"

    # ---------------------------------------------------------------- Variações
    VariavelInline:
      type: object
      required: [nome]
      properties:
        nome:
          type: string
          example: "Variável 1"
    VariacaoCreate:
      type: object
      required: [nome, variaveis]
      properties:
        nome:
          type: string
          example: "Variação Teste"
        variaveis:
          type: array
          minItems: 1
          items:
            $ref: "#/components/schemas/VariavelInline"
    VariacaoUpdate:
      type: object
      description: |
        Em caso de envio de `variaveis`, todas as variáveis atualmente
        existentes na variação serão substituídas pelas variáveis informadas
        neste método (PUT), gerando um novo ID para cada uma. Caso queira
        apenas inserir uma nova variável, utilize o método PATCH ou o
        endpoint POST de Variáveis.
      properties:
        nome:
          type: string
          example: "Sabores"
        variaveis:
          type: array
          items:
            $ref: "#/components/schemas/VariavelInline"
        utilizaCor:
          type: boolean
    Variavel:
      type: object
      properties:
        id:
          type: string
          example: "604776f1b6fa7c87726f43e3"
        nome:
          type: string
          example: "variável x"
    Variacao:
      type: object
      properties:
        id:
          type: string
          example: "60490e61b6fa7c2826105b43"
        nome:
          type: string
          example: "Variação Teste"
        variaveis:
          type: array
          items:
            $ref: "#/components/schemas/Variavel"

    # ---------------------------------------------------------------- Variáveis
    VariavelCreate:
      type: object
      required: [nome]
      properties:
        nome:
          type: string
          example: "Variável 5"
        cor:
          type: string
          description: |
            Indica quais serão a cor ou cores da variável. Necessita que a
            variação esteja com o atributo `utilizaCor` como `true`. Aceita
            cores em formato hex nestes formatos: `#000000` ou
            `#000000|#FFFFFF` para duas cores.
    VariavelUpdate:
      type: object
      properties:
        nome:
          type: string
          example: "Azul"
        cor:
          type: string

    # ---------------------------------------------------------------- Produtos
    ProdutoVariacaoVariavelInput:
      type: object
      required: [id]
      properties:
        id:
          type: string
          example: "6037d8bb6df10513fb742d42"
        preco:
          type: number
          example: 0
        imagem:
          type: integer
          description: |
            Índice (iniciando em 0) referente à imagem do produto que será
            mostrada quando essa variável for selecionada.
          example: 0
    ProdutoVariacaoInput:
      type: object
      required: [id, variaveis]
      properties:
        id:
          type: string
          example: "6037d8bb6df10513fb742d40"
        obrigatoria:
          type: boolean
          example: true
        multipla_selecao:
          type: boolean
          example: false
        adicional:
          type: boolean
          example: false
        qtdeMinima:
          type: number
          nullable: true
        qtdeMaxima:
          type: number
          nullable: true
        variaveis:
          type: array
          items:
            $ref: "#/components/schemas/ProdutoVariacaoVariavelInput"
    CombinacaoParInput:
      type: object
      required: [variacao, variavel]
      properties:
        variacao:
          type: string
          description: ID ou nome da variação.
          example: "6037d8bb6df10513fb742d40"
        variavel:
          type: string
          description: ID ou nome da variável.
          example: "6037d8bb6df10513fb742d43"
    CombinacaoInput:
      type: object
      required: [combinacao]
      properties:
        codigo:
          type: string
          description: Código (SKU) da combinação.
          example: "SKU_P_AZUL"
        preco:
          type: number
          example: 12
        ean:
          type: string
          description: Código de barras (EAN/GTIN) da combinação. Opcional.
          example: "7891234567890"
        combinacao:
          type: array
          items:
            $ref: "#/components/schemas/CombinacaoParInput"
    PromocaoInput:
      type: object
      properties:
        dataHoraInicio:
          type: string
          format: date-time
          description: "Formato: YYYY-mm-dd HH:MM:SS"
          example: "2021-02-14 22:00:00"
        dataHoraFim:
          type: string
          format: date-time
          example: "2021-02-24 20:59:59"
        percentual:
          type: number
          example: 10
        precoPromocional:
          type: number
          example: 26.991
    ProdutoCreate:
      type: object
      required: [descricao]
      properties:
        descricao:
          type: string
          example: "Produto API"
        preco:
          type: number
          example: 9.99
        promocao:
          $ref: "#/components/schemas/PromocaoInput"
        imagens:
          type: array
          description: Array com Urls e/ou base64 das imagens. A primeira será a capa do produto.
          items:
            type: string
          example:
            - "https://www.vendizap.com/imagens/produto1.jpg"
            - "https://www.vendizap.com/imagens/produto2.jpg"
        detalhes:
          type: string
          example: "Detalhes do produto de exemplo"
        categorias:
          type: array
          items:
            type: string
          example: []
        variacoes:
          type: array
          items:
            $ref: "#/components/schemas/ProdutoVariacaoInput"
        combinacoes:
          type: array
          items:
            $ref: "#/components/schemas/CombinacaoInput"
        dimensoes:
          type: object
          properties:
            altura:
              type: number
              example: 10
            largura:
              type: number
              example: 10
            comprimento:
              type: number
              example: 10
            peso:
              type: number
              example: 1
        unidadeVenda:
          type: string
          enum:
            [
              Unidade,
              Caixa,
              Pacote,
              Peça,
              Quilo,
              Porção,
              Pedaço,
              Metro,
              Par,
              Jogo,
            ]
          example: "Unidade"
        unidadePreco:
          type: string
          enum:
            [
              Unidade,
              Caixa,
              Pacote,
              Peça,
              Quilo,
              Porção,
              Pedaço,
              Metro,
              Par,
              Jogo,
            ]
          example: "Unidade"
        codigo:
          type: string
          example: "10"
        ean:
          type: string
          description: Código de barras (EAN/GTIN). Apenas para produto SEM variação — em produto com variação, o EAN é por combinação.
          example: "7891234567890"
        qtdeMinima:
          type: number
          example: 0
        qtdeMaxima:
          type: number
          example: 0
        exibir:
          type: boolean
          example: true
        destaque:
          type: boolean
          example: false
    ProdutoUpdate:
      description: |
        Todos os campos informados serão atualizados. Para arrays
        (`variacoes`, `imagens`, `categorias`, `combinacoes`), o conteúdo
        atual será SUBSTITUÍDO pelo informado. Para excluir uma promoção,
        envie `promocao` como `null`.
      allOf:
        - $ref: "#/components/schemas/ProdutoCreate"
    ProdutoListItem:
      type: object
      properties:
        id:
          type: string
        descricao:
          type: string
        preco:
          type: number
        unidadeVenda:
          type: string
        destaque:
          type: boolean
        codigo:
          type: string
        exibir:
          type: boolean
        dt_cadastro:
          type: string
        dt_alteracao:
          type: string
    ProdutoCategoriaResumo:
      type: object
      properties:
        id:
          type: string
        nome:
          type: string
    ProdutoVariavelDetalhe:
      type: object
      properties:
        id:
          type: string
        nome:
          type: string
        preco:
          type: number
        codigo:
          type: string
        imagem:
          type: string
          nullable: true
    ProdutoVariacaoDetalhe:
      type: object
      properties:
        id:
          type: string
        nome:
          type: string
        variaveis:
          type: array
          items:
            $ref: "#/components/schemas/ProdutoVariavelDetalhe"
        multipla_selecao:
          type: boolean
        obrigatoria:
          type: boolean
        adicional:
          type: boolean
        qtdeMinima:
          type: number
          nullable: true
        qtdeMaxima:
          type: number
          nullable: true
        codigo:
          type: string
    ProdutoPromocao:
      type: object
      properties:
        inicio:
          type: string
        fim:
          type: string
        percentual:
          type: number
        precoPromocional:
          type: number
    Produto:
      type: object
      properties:
        id:
          type: string
        descricao:
          type: string
        detalhes:
          type: string
        preco:
          type: number
        unidadeVenda:
          type: string
        unidadePreco:
          type: string
        categorias:
          type: array
          items:
            $ref: "#/components/schemas/ProdutoCategoriaResumo"
        variacoes:
          type: array
          items:
            $ref: "#/components/schemas/ProdutoVariacaoDetalhe"
        promocao:
          $ref: "#/components/schemas/ProdutoPromocao"
        destaque:
          type: boolean
        codigo:
          type: string
        qtdeMinima:
          type: number
        qtdeMaxima:
          type: number
        exibir:
          type: boolean
        dt_cadastro:
          type: string
        dt_alteracao:
          type: string
        imagens:
          type: array
          items:
            type: string

    # ---------------------------------------------------------------- Estoque
    EstoqueSemVariacao:
      type: object
      required: [quantidade]
      properties:
        quantidade:
          type: integer
          example: 11
    EstoqueCombinacaoIdsItem:
      type: object
      required: [quantidade, combinacao]
      properties:
        quantidade:
          type: integer
          example: 15
        combinacao:
          type: object
          additionalProperties:
            type: string
          description: Mapa de `idVariacao` para `idVariavel`.
          example:
            "6037d8bb6df10513fb742d5a": "6037d8bb6df10513fb742d39"
            "6037d8bb6df10513fb742d44": "6037d8bb6df10513fb742d47"
    EstoqueCombinacaoSKUItem:
      type: object
      required: [quantidade, combinacaoSKU]
      properties:
        quantidade:
          type: integer
          example: 15
        combinacaoSKU:
          type: string
          example: "SKU_P_AZUL"
    EstoqueCombinacaoIdItem:
      type: object
      required: [quantidade, combinacaoId]
      properties:
        quantidade:
          type: integer
          example: 15
        combinacaoId:
          type: string
          example: "66831670fbf70d6ba1726972"

    # ---------------------------------------------------------------- Pedidos
    PedidoEndereco:
      type: object
      properties:
        cep:
          type: string
        logradouro:
          type: string
        numero:
          type: string
        bairro:
          type: string
        pais:
          type: string
        estado:
          type: string
        cidade:
          type: string
        complemento:
          type: string
    PedidoCliente:
      type: object
      properties:
        nome:
          type: string
        documento:
          type: string
        telefone:
          type: string
        endereco:
          $ref: "#/components/schemas/PedidoEndereco"
    PedidoPagamento:
      type: object
      properties:
        descricao:
          type: string
        utilizaTroco:
          type: boolean
        utilizaBandeira:
          type: boolean
        bandeiraSelecionada:
          type: string
          nullable: true
        parcelas:
          type: integer
          nullable: true
        id:
          type: string
        dt_alteracao:
          type: string
          nullable: true
    PedidoVendedor:
      type: object
      nullable: true
      properties:
        id:
          type: string
        nome:
          type: string
    PedidoItemVariavel:
      type: object
      properties:
        nome:
          type: string
        quantidade:
          type: integer
        valorAdicional:
          type: number
        codigo:
          type: string
        id:
          type: string
    PedidoItemVariacao:
      type: object
      properties:
        nome:
          type: string
        variaveis:
          type: array
          items:
            $ref: "#/components/schemas/PedidoItemVariavel"
        multipla_selecao:
          type: boolean
        obrigatoria:
          type: boolean
        adicional:
          type: boolean
        qtdeMinima:
          type: integer
          nullable: true
        qtdeMaxima:
          type: integer
          nullable: true
        quantidadeSelecionada:
          type: integer
        valorAdicionais:
          type: number
        codigo:
          type: string
        id:
          type: string
    PedidoItem:
      type: object
      properties:
        id_produto:
          type: string
        descricao:
          type: string
        detalhes:
          type: string
        preco:
          type: number
        controle_estoque:
          type: boolean
        unidadeVenda:
          type: string
        unidadePreco:
          type: string
        categorias:
          type: array
          items:
            type: string
        precoPromocional:
          type: number
          nullable: true
        quantidade:
          type: integer
        observacaoProduto:
          type: string
        relacaoVariacao:
          type: array
          items:
            $ref: "#/components/schemas/PedidoItemVariacao"
        codigo:
          type: string
        dimensoes:
          type: object
          nullable: true
        embalagemTransporte:
          type: object
          nullable: true
    Pedido:
      type: object
      properties:
        id:
          type: string
        data:
          type: string
        itens:
          type: array
          items:
            $ref: "#/components/schemas/PedidoItem"
        entrega:
          type: boolean
        dataHoraRetirada:
          type: string
          nullable: true
        observacao:
          type: string
        pagamento:
          $ref: "#/components/schemas/PedidoPagamento"
        taxaEntrega:
          type: number
        qrcode:
          type: string
          nullable: true
        valorPedido:
          type: number
        valorAproximado:
          type: boolean
        numero:
          type: integer
        importacaoErp:
          type: integer
        vendedor:
          $ref: "#/components/schemas/PedidoVendedor"
        cliente:
          $ref: "#/components/schemas/PedidoCliente"
        status:
          $ref: "#/components/schemas/PedidoStatus"

    PedidoStatus:
      type: object
      description: Etapas de andamento do pedido.
      properties:
        preparacao:
          type: boolean
          description: Em preparação.
        separacao:
          type: boolean
          description: Separado.
        enviado:
          type: boolean
          description: Enviado.
        entregue:
          type: boolean
          description: Entregue.
        pagamento:
          type: boolean
          description: Pagamento confirmado.
    PedidoStatusUpdate:
      type: object
      required: [status]
      properties:
        status:
          type: string
          enum: [preparacao, separacao, enviado, entregue, pagamento]
          description: Etapa alvo a ser marcada.
          example: "preparacao"
        valor:
          type: boolean
          default: true
          description: |
            `true` (padrão) para marcar a etapa; `false` para desmarcar/regredir.
          example: true

    # ---------------------------------------------------------------- Produto Variações (input)
    ProdutoVariacaoVincularInput:
      type: object
      required: [id]
      properties:
        id:
          type: string
          example: "6053bb9b6df1055978541352"
        obrigatoria:
          type: boolean
          example: true
        multipla_selecao:
          type: boolean
          example: false
        adicional:
          type: boolean
          example: false
        qtdeMinima:
          type: number
          nullable: true
        qtdeMaxima:
          type: number
          nullable: true
        variaveis:
          type: array
          items:
            $ref: "#/components/schemas/ProdutoVariacaoVariavelInput"
    ProdutoVariacaoUpdate:
      type: object
      properties:
        obrigatoria:
          type: boolean
        multipla_selecao:
          type: boolean
        adicional:
          type: boolean
        qtdeMinima:
          type: number
          nullable: true
        qtdeMaxima:
          type: number
          nullable: true
        variaveis:
          type: array
          items:
            $ref: "#/components/schemas/ProdutoVariacaoVariavelInput"

    # ---------------------------------------------------------------- Produto Variáveis (input)
    ProdutoVariavelVincularInput:
      type: object
      required: [id]
      properties:
        id:
          type: string
          example: "60dfb46dc4f8da63d518c1d2"
        preco:
          type: number
        imagem:
          type: integer
    ProdutoVariavelUpdate:
      type: object
      properties:
        preco:
          type: number
          example: 2
        imagem:
          type: integer

    # ---------------------------------------------------------------- Produto Combinações
    ProdutoCombinacoesInput:
      type: object
      required: [combinacoes]
      properties:
        combinacoes:
          type: array
          items:
            $ref: "#/components/schemas/CombinacaoInput"
    CombinacaoAlteracaoInput:
      type: object
      description: Permite alterar código (SKU), preço e/ou EAN (código de barras) de uma combinação específica.
      properties:
        codigo:
          type: string
          example: "SKU_API_ID"
        preco:
          type: number
          example: 50
        ean:
          type: string
          description: Código de barras (EAN/GTIN) da combinação. Opcional.
          example: "7891234567890"

    # ---------------------------------------------------------------- Respostas comuns
    IdResponse:
      type: object
      properties:
        id:
          type: string
          example: "6048f2b4b6fa7c28844582d5"
    IdComErrosResponse:
      type: object
      properties:
        id:
          type: string
          example: "604284466df1054914132443"
        erros:
          type: array
          items:
            type: string
          example:
            - "Não foi possível vincular a imagem de índice 2 para a variável 6037f540b6fa7c03441457b6 da variação 6037f3e2b6fa7c00064e2cb2"

    # ---------------------------------------------------------------- Usuário
    UsuarioEndereco:
      type: object
      properties:
        cep:
          type: string
          example: "80000-100"
        logradouro:
          type: string
          example: "Logradouro usuário"
        numero:
          type: string
          example: "100"
        complemento:
          type: string
          example: "Loja 42"
        bairro:
          type: string
          example: "Bairro"
        cidade:
          type: string
          example: "Cidade"
        estado:
          type: string
          example: "ES"
    Usuario:
      type: object
      properties:
        nome_usuario:
          type: string
          example: "Nome do usuário"
        nome_empresa:
          type: string
          example: "Nome da empresa"
        cpfCnpj:
          type: string
          example: "999.999.999-99"
        email:
          type: string
          example: "emailusuario@vendizap.com"
        celular:
          type: string
          example: "+55 11 99999 9999"
        endereco:
          $ref: "#/components/schemas/UsuarioEndereco"
        subdominios:
          type: array
          items:
            type: string
          example:
            - "subdominiodaloja"
            - "lojasubdominio"

    # ---------------------------------------------------------------- Descontos Progressivos
    Faixa:
      type: object
      required: [aPartirDe, percentualDesconto]
      properties:
        aPartirDe:
          type: number
          exclusiveMinimum: 0
          description: Limiar mínimo a partir do qual a faixa passa a valer (quantidade de itens em `faixaQuantidadeLista`; valor do pedido/produto em `faixaPrecoLista`). Deve ser maior que zero e **estritamente crescente** entre as faixas da mesma lista (sem repetir nem sobrepor). A maior faixa atingida prevalece, não há limite superior.
          example: 2
        percentualDesconto:
          type: number
          exclusiveMinimum: 0
          maximum: 99
          description: Percentual de desconto aplicado quando o limiar é atingido. Deve ser maior que zero e no máximo 99, e **estritamente crescente** entre as faixas da mesma lista.
          example: 10
    ProdutoRef:
      type: object
      description: Referência a um produto por id OU por código (SKU). Pelo menos um dos dois deve ser informado.
      properties:
        id:
          type: string
          example: "6682f7b065be87123fd4d157"
        codigo:
          type: string
          example: "SKU-001"
    DescontoProgressivoCreate:
      type: object
      required: [nome, tipo]
      properties:
        nome:
          type: string
          maxLength: 50
          description: Nome do preço de atacado (máximo 50 caracteres).
          example: "Quanto mais, mais barato"
        tipo:
          type: string
          enum: [produto, pedido]
          description: |
            `produto`: desconto sobre o preço unitário (combinar com `tipoFiltro`).
            `pedido`: desconto sobre o total do pedido. Apenas um registro do tipo `pedido` ativo é permitido por lojista.
          example: "produto"
        ativa:
          type: boolean
          description: Define se o desconto está ativo. Default `true`.
          example: true
        tipoFiltro:
          type: string
          enum: [todosProdutos, produtos, categorias]
          description: Obrigatório quando `tipo="produto"`. Quando `tipo="pedido"`, ignorar.
          example: "produtos"
        produtos:
          type: array
          description: Obrigatório quando `tipoFiltro="produtos"`. Aceita id OU código.
          items:
            $ref: "#/components/schemas/ProdutoRef"
        categorias:
          type: array
          description: Obrigatório quando `tipoFiltro="categorias"`. Aceita id OU código. Somente categorias raiz.
          items:
            type: string
            example: "601d957bb6fa7c11ba209426"
        faixaQuantidade:
          type: boolean
          description: Se `true`, `faixaQuantidadeLista` deve conter pelo menos uma faixa.
          example: true
        faixaQuantidadeLista:
          type: array
          items:
            $ref: "#/components/schemas/Faixa"
        faixaPreco:
          type: boolean
          description: Se `true`, `faixaPrecoLista` deve conter pelo menos uma faixa.
          example: false
        faixaPrecoLista:
          type: array
          items:
            $ref: "#/components/schemas/Faixa"
        permiteCupom:
          type: boolean
          default: true
          description: |
            Quando `false`, os itens cobertos por esta campanha (com a faixa atingida) saem da base de cálculo de cupons no carrinho. Default `true` (cupom e preço de atacado se acumulam, como antes).
          example: true
    DescontoProgressivoUpdate:
      type: object
      description: |
        Substitui os campos editáveis do desconto. Os campos definidos neste schema
        que não forem enviados voltam aos defaults (listas de faixas viram `[]`,
        `faixaQuantidade`/`faixaPreco` viram `false`, `produtos`/`categorias` viram `[]`).
        Para alterações parciais, usar PATCH.
      required: [nome, tipo]
      properties:
        nome:
          type: string
          maxLength: 50
        tipo:
          type: string
          enum: [produto, pedido]
        ativa:
          type: boolean
        tipoFiltro:
          type: string
          enum: [todosProdutos, produtos, categorias]
        produtos:
          type: array
          items:
            $ref: "#/components/schemas/ProdutoRef"
        categorias:
          type: array
          items:
            type: string
        faixaQuantidade:
          type: boolean
        faixaQuantidadeLista:
          type: array
          items:
            $ref: "#/components/schemas/Faixa"
        faixaPreco:
          type: boolean
        faixaPrecoLista:
          type: array
          items:
            $ref: "#/components/schemas/Faixa"
        permiteCupom:
          type: boolean
          default: true
          description: |
            Quando `false`, os itens cobertos por esta campanha (com a faixa atingida) saem da base de cálculo de cupons. Omitir equivale a `true`.
    DescontoProgressivoPatch:
      type: object
      description: |
        Altera apenas os campos enviados (merge). O payload mesclado deve continuar
        atendendo às regras de validação (ao menos uma faixa ativa, `produtos`/`categorias`
        coerentes com `tipoFiltro`).
      properties:
        nome:
          type: string
          maxLength: 50
        tipo:
          type: string
          enum: [produto, pedido]
        ativa:
          type: boolean
        tipoFiltro:
          type: string
          enum: [todosProdutos, produtos, categorias]
        produtos:
          type: array
          items:
            $ref: "#/components/schemas/ProdutoRef"
        categorias:
          type: array
          items:
            type: string
        faixaQuantidade:
          type: boolean
        faixaQuantidadeLista:
          type: array
          items:
            $ref: "#/components/schemas/Faixa"
        faixaPreco:
          type: boolean
        faixaPrecoLista:
          type: array
          items:
            $ref: "#/components/schemas/Faixa"
        permiteCupom:
          type: boolean
          description: |
            Quando `false`, os itens cobertos por esta campanha (com a faixa atingida) saem da base de cálculo de cupons. Omitir mantém o valor atual.
    ProdutoVinculado:
      type: object
      properties:
        id:
          type: string
          example: "6682f7b065be87123fd4d157"
        descricao:
          type: string
          example: "Produto exemplo"
    CategoriaVinculada:
      type: object
      properties:
        id:
          type: string
          example: "601d957bb6fa7c11ba209426"
        nome:
          type: string
          example: "Camisetas"
    DescontoProgressivo:
      type: object
      properties:
        id:
          type: string
          example: "6a07661f4ef4d311179c988a"
        usuarioId:
          type: string
          example: "69ea50e655f4c796230657e5"
        nome:
          type: string
          example: "Quanto mais, mais barato"
        tipo:
          type: string
          enum: [produto, pedido]
          example: "produto"
        ativa:
          type: boolean
          example: true
        tipoFiltro:
          type: string
          enum: [todosProdutos, produtos, categorias]
          example: "produtos"
        produtos:
          type: array
          description: Quando `tipoFiltro="produtos"`, retorna a lista com `id` e `descricao` resolvidos.
          items:
            $ref: "#/components/schemas/ProdutoVinculado"
        categorias:
          type: array
          description: Quando `tipoFiltro="categorias"`, retorna as categorias **raiz** selecionadas (id + nome). Os descendentes são expandidos internamente pelo servidor para vincular os produtos, mas não aparecem nesta lista.
          items:
            $ref: "#/components/schemas/CategoriaVinculada"
        faixaQuantidade:
          type: boolean
        faixaQuantidadeLista:
          type: array
          items:
            $ref: "#/components/schemas/Faixa"
        faixaPreco:
          type: boolean
        faixaPrecoLista:
          type: array
          items:
            $ref: "#/components/schemas/Faixa"
        permiteCupom:
          type: boolean
          description: Indica se cupons podem ser aplicados sobre os itens cobertos por esta campanha. Sempre presente na resposta (`true` para campanhas legadas).
          example: true
    DescontoProgressivoOkResponse:
      type: object
      properties:
        ok:
          type: boolean
          example: true
        id:
          type: string
          example: "6a07661f4ef4d311179c988a"

  responses:
    BadRequest:
      description: Erro na requisição que não foi possível ser completada. O erro é retornado em uma string (não JSON).
      content:
        text/plain:
          schema:
            type: string
    Unauthorized:
      description: Credenciais informadas inválidas.
      content:
        text/plain:
          schema:
            type: string

paths:
  # ============================================================== CATEGORIAS
  /categorias:
    post:
      operationId: create_category
      x-mcp-open-world: true
      tags: [Categorias]
      summary: Cadastrar categoria
      description: |
        Método utilizado para inserir novas categorias no sistema. Caso já
        exista uma categoria com a mesma descrição da que está sendo inserida,
        será retornado apenas o **Id** da categoria existente com status 200,
        pois não deve existir duas categorias com a mesma descrição. Caso a
        categoria não exista, ao criá-la também retornará o **Id**, porém o
        status retornado será **201**.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CategoriaCreate"
            example:
              nome: "Utensílios"
              imagem: "https://www.vendizap.com/wp-content/themes/startit/assets/img/logo.png"
              codigo: "api"
      responses:
        "201":
          description: Categoria criada com sucesso.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/IdResponse"
              example:
                id: "6048f2b4b6fa7c28844582d5"
        "200":
          description: Já existia uma categoria com a mesma descrição. Retornado o ID da existente.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/IdResponse"
        "400": { $ref: "#/components/responses/BadRequest" }
        "401": { $ref: "#/components/responses/Unauthorized" }
    get:
      operationId: list_categories
      tags: [Categorias]
      summary: Listar categorias
      description: |
        Método utilizado para listar as categorias existentes. Os parâmetros
        abaixo são opcionais — caso nenhum seja informado, serão retornadas
        todas as categorias. Os parâmetros não fazem busca exata; retornam
        registros que contenham o texto informado. Por exemplo, ao filtrar
        a descrição "carne", serão retornadas todas as categorias que contêm
        a palavra "carne" em sua descrição. O filtro de código possui o
        mesmo comportamento.

        ### Retorno

        O retorno deste método será sempre um array com os objetos das
        categorias filtradas.
      parameters:
        - name: nome
          in: query
          required: false
          description: Nome da categoria a ser filtrada (busca parcial).
          schema:
            type: string
        - name: codigo
          in: query
          required: false
          description: Código da categoria a ser filtrada (busca parcial).
          schema:
            type: string
      responses:
        "200":
          description: Lista de categorias.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/Categoria"
              example:
                - id: "601d957bb6fa7c11ba209426"
                  nome: "Categoria teste"
                  codigo: "1"
                - id: "6048f2b4b6fa7c28844582d5"
                  nome: "Teste API2"
                  codigo: "12234"
                  imagem: "https://minio.vendizap.com/vendizap-categorias/550a0eb3812c3e44071a03ea13cb0170.jpg"
        "401": { $ref: "#/components/responses/Unauthorized" }

  /categorias/{categoriaId}:
    parameters:
      - $ref: "#/components/parameters/CategoriaIdPath"
    put:
      operationId: update_category
      x-mcp-open-world: true
      tags: [Categorias]
      summary: Atualizar categoria
      description: Método utilizado para atualizar uma categoria existente através do seu **ID ou Código**.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CategoriaUpdate"
            example:
              imagem: "https://play-lh.googleusercontent.com/sVm17jdr0Zp96sKyL8wiXoV_oBsvX92wK-4UN4Fu3quA7GHNUEqkVT1xkcmAolY9O8k"
              codigo: "1234"
      responses:
        "200":
          description: Categoria atualizada com sucesso.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/IdResponse"
              example:
                id: "6048f2b4b6fa7c28844582d5"
        "400": { $ref: "#/components/responses/BadRequest" }
        "401": { $ref: "#/components/responses/Unauthorized" }
    get:
      operationId: get_category
      tags: [Categorias]
      summary: Buscar categoria
      description: |
        Método utilizado para buscar uma categoria em específico através do
        seu **ID** ou **Código**.

        ### Retorno

        Em caso de sucesso, esse método retorna um objeto em **JSON** com os
        campos e valores da categoria.
      responses:
        "200":
          description: Categoria encontrada.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Categoria"
              example:
                id: "6048f2b4b6fa7c28844582d5"
                nome: "Utensílios"
                codigo: "12234"
                imagem: "https://minio.vendizap.com/vendizap-categorias/550a0eb3812c3e44071a03ea13cb0170.jpg"
        "401": { $ref: "#/components/responses/Unauthorized" }

  # ============================================================== VARIAÇÕES
  /variacoes:
    post:
      operationId: create_variation
      x-mcp-open-world: true
      tags: [Variações]
      summary: Cadastrar variação
      description: |
        Método utilizado para cadastrar variação. Deve ser informada pelo
        menos uma variável neste método conforme exemplo abaixo, caso
        contrário não será possível cadastrar a variação.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/VariacaoCreate"
            example:
              nome: "Variação Teste"
              variaveis:
                - nome: "Variável 1"
                - nome: "Variável 2"
      responses:
        "201":
          description: Variação criada com sucesso.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Variacao"
              example:
                id: "60490e61b6fa7c2826105b43"
                nome: "Variação Teste"
                variaveis:
                  - nome: "Variável 1"
                    id: "60490e61b6fa7c2826105b44"
                  - nome: "Variável 2"
                    id: "60490e61b6fa7c2826105b45"
        "400": { $ref: "#/components/responses/BadRequest" }
        "401": { $ref: "#/components/responses/Unauthorized" }
    get:
      operationId: list_variations
      tags: [Variações]
      summary: Listar variações
      description: |
        Método utilizado para listar as variações existentes do usuário. Os
        parâmetros abaixo são opcionais — caso nenhum seja informado, serão
        retornadas todas as variações. O parâmetro `nome` faz uma busca de
        texto, ou seja, retorna as variações que contenham parte do texto
        informado. Já os demais campos fazem a busca exata pelo valor
        informado.

        ### Retorno

        O retorno deste método será um array com os objetos das variações
        filtradas e o array de objetos das variáveis.
      parameters:
        - name: nome
          in: query
          required: false
          description: Nome (parcial) da variação.
          schema:
            type: string
          example: "Variação"
      responses:
        "200":
          description: Lista de variações.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/Variacao"
              example:
                - id: "604613f7b6fa7c832e5a0314"
                  nome: "Variação API"
                  variaveis:
                    - nome: "variável 1"
                      id: "604613f7b6fa7c832e5a0313"
                    - nome: "variável 2"
                      id: "6048ae8ab6fa7c28844582d1"
                - id: "60490e61b6fa7c2826105b43"
                  nome: "Variação Teste"
                  variaveis:
                    - nome: "variável x"
                      id: "604776f1b6fa7c87726f43e3"
                    - nome: "variável y"
                      id: "6048ae8fb6fa7c29972c882b"
                    - nome: "variável 3"
                      id: "6048ae91b6fa7c29991d33e6"
        "401": { $ref: "#/components/responses/Unauthorized" }

  /variacoes/{variacaoId}:
    parameters:
      - $ref: "#/components/parameters/VariacaoIdPath"
    put:
      operationId: update_variation
      x-mcp-open-world: true
      tags: [Variações]
      summary: Atualizar variação
      description: |
        Método utilizado para atualizar uma variação. Caso sejam informadas
        `variaveis` neste método, todas as variáveis atualmente existentes
        na variação serão **substituídas** pelas variáveis informadas. Caso
        queira apenas inserir uma nova variável, verifique o método **PATCH**
        abaixo ou o método **POST** das variáveis. Os demais campos serão
        atualizados normalmente.

        **ATENÇÃO:** Em caso de envio de variáveis neste método, mesmo que as
        descrições sejam iguais às atualmente existentes, todas as existentes
        serão excluídas e cadastradas novamente, gerando um novo **ID** para
        cada uma.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/VariacaoUpdate"
            example:
              nome: "Sabores"
      responses:
        "200":
          description: Variação atualizada com sucesso.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Variacao"
              example:
                id: "60490e61b6fa7c2826105b43"
                nome: "Variação Teste"
                variaveis:
                  - nome: "variável x"
                    id: "604776f1b6fa7c87726f43e3"
                  - nome: "variável y"
                    id: "6048ae8fb6fa7c29972c882b"
        "400": { $ref: "#/components/responses/BadRequest" }
        "401": { $ref: "#/components/responses/Unauthorized" }
    patch:
      operationId: update_variation_partial
      x-mcp-open-world: true
      tags: [Variações]
      summary: Atualizar variação (parcial)
      description: |
        Método utilizado para atualizar uma variação de maneira parcial em
        relação às variáveis. Ou seja, caso sejam informadas `variaveis`
        neste método, ao contrário do método **PUT**, as variáveis informadas
        serão apenas **acrescentadas** na variação. Caso queira alterar as
        variáveis excluindo as existentes e incluindo novas, veja o método
        **PUT** acima. Os demais campos informados serão atualizados
        normalmente, igual ao método **PUT**.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/VariacaoUpdate"
            example:
              nome: "Sabores"
      responses:
        "200":
          description: Variação atualizada parcialmente.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Variacao"
              example:
                id: "60490e61b6fa7c2826105b43"
                nome: "Variação Teste"
                variaveis:
                  - nome: "variável x"
                    id: "604776f1b6fa7c87726f43e3"
                  - nome: "variável y"
                    id: "6048ae8fb6fa7c29972c882b"
                  - nome: "variável 3"
                    id: "6048ae91b6fa7c29991d33e6"
        "400": { $ref: "#/components/responses/BadRequest" }
        "401": { $ref: "#/components/responses/Unauthorized" }
    get:
      operationId: get_variation
      tags: [Variações]
      summary: Buscar variação
      description: |
        Método utilizado para buscar uma variação em específico através do
        seu **ID**, informado através da URL.

        ### Retorno

        Em caso de sucesso, esse método retorna um objeto em **JSON** com os
        campos e valores da variação e suas respectivas variáveis.
      responses:
        "200":
          description: Variação encontrada.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Variacao"
              example:
                id: "60490e61b6fa7c2826105b43"
                nome: "Variação Teste"
                variaveis:
                  - nome: "variável x"
                    id: "604776f1b6fa7c87726f43e3"
                  - nome: "variável y"
                    id: "6048ae8fb6fa7c29972c882b"
                  - nome: "variável 3"
                    id: "6048ae91b6fa7c29991d33e6"
        "401": { $ref: "#/components/responses/Unauthorized" }

  # ============================================================== VARIÁVEIS
  /variaveis/{variacaoId}:
    parameters:
      - $ref: "#/components/parameters/VariacaoIdPath"
    post:
      operationId: create_variation_value
      x-mcp-open-world: true
      tags: [Variáveis]
      summary: Cadastrar variável
      description: Método utilizado para cadastrar variável dentro de uma variação.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/VariavelCreate"
            example:
              nome: "Variável 5"
      responses:
        "201":
          description: Variável criada com sucesso.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Variavel"
              example:
                id: "604912a9b6fa7c28836ced05"
                nome: "Variável 5"
        "400": { $ref: "#/components/responses/BadRequest" }
        "401": { $ref: "#/components/responses/Unauthorized" }
    get:
      operationId: list_variation_values
      tags: [Variáveis]
      summary: Listar variáveis
      description: |
        Método utilizado para listar as variáveis existentes dentro de uma
        determinada variação. Os parâmetros abaixo são opcionais — caso
        nenhum seja informado, serão retornadas todas as variáveis dentro da
        variação especificada. O parâmetro `nome` faz uma busca de texto,
        ou seja, retorna as variáveis que contenham parte do texto informado.
        Já os demais campos fazem a busca exata pelo valor informado.

        ### Retorno

        O retorno deste método será um array com os objetos das variáveis
        filtradas dentro da variação informada.
      parameters:
        - name: nome
          in: query
          required: false
          description: Nome (parcial) da variável.
          schema:
            type: string
      responses:
        "200":
          description: Lista de variáveis da variação.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/Variavel"
              example:
                - nome: "variável x"
                  id: "604776f1b6fa7c87726f43e3"
                - nome: "variável y"
                  id: "6048ae8fb6fa7c29972c882b"
                - nome: "variável 3"
                  id: "6048ae91b6fa7c29991d33e6"
        "401": { $ref: "#/components/responses/Unauthorized" }

  /variaveis/{variacaoId}/{variavelId}:
    parameters:
      - $ref: "#/components/parameters/VariacaoIdPath"
      - $ref: "#/components/parameters/VariavelIdPath"
    put:
      operationId: update_variation_value
      x-mcp-open-world: true
      tags: [Variáveis]
      summary: Atualizar variável
      description: |
        Método utilizado para atualizar uma variável de uma variação. Deve
        ser informado na URL o **ID** da variação e em seguida o da
        respectiva variável que deseja alterar.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/VariavelUpdate"
            example:
              nome: "Azul"
      responses:
        "200":
          description: Variável atualizada com sucesso.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Variavel"
              example:
                id: "604912a9b6fa7c28836ced05"
                nome: "5 Variável"
        "400": { $ref: "#/components/responses/BadRequest" }
        "401": { $ref: "#/components/responses/Unauthorized" }
    get:
      operationId: get_variation_value
      tags: [Variáveis]
      summary: Buscar variável
      description: |
        Método utilizado para buscar uma variável em específico através do
        seu **ID** e do **ID de sua variação**, ambos informados através
        da URL.

        ### Retorno

        Em caso de sucesso, esse método retorna um objeto em **JSON** com
        os campos e valores da variável.
      responses:
        "200":
          description: Variável encontrada.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Variavel"
              example:
                id: "604912a9b6fa7c28836ced05"
                nome: "5 Variável"
        "401": { $ref: "#/components/responses/Unauthorized" }

  # ============================================================== PRODUTOS
  /produtos:
    post:
      operationId: create_product
      x-mcp-open-world: true
      tags: [Produtos]
      summary: Cadastrar produto
      description: |
        Método utilizado para cadastrar novos produtos. Vale ressaltar que
        apenas com a `descricao` já é possível inserir um produto.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ProdutoCreate"
            example:
              descricao: "Produto API"
              preco: 9.99
              dimensoes:
                altura: 10
                largura: 10
                comprimento: 10
                peso: 1
              variacoes:
                - id: "6037d8bb6df10513fb742d40"
                  obrigatoria: true
                  multipla_selecao: false
                  adicional: false
                  variaveis:
                    - id: "6037d8bb6df10513fb742d42"
                      preco: 0
                      imagem: 0
                    - id: "6037d8bb6df10513fb742d43"
                      preco: 0
                      imagem: 1
                - id: "6037d8bb6df10513fb742d44"
                  obrigatoria: true
                  multipla_selecao: false
                  adicional: false
                  variaveis:
                    - id: "6037d8bb6df10513fb742d46"
                      preco: 0
                      imagem: 0
              combinacoes:
                - codigo: "SKU_P_AZUL"
                  preco: 12
                  ean: "7891234567890"
                  combinacao:
                    - variacao: "6037d8bb6df10513fb742d40"
                      variavel: "6037d8bb6df10513fb742d43"
                    - variacao: "6037d8bb6df10513fb742d44"
                      variavel: "6037d8bb6df10513fb742d46"
                - codigo: "SKU_M_AZUL"
                  preco: 12
                  combinacao:
                    - variacao: "6037d8bb6df10513fb742d40"
                      variavel: "6037d8bb6df10513fb742d42"
                    - variacao: "6037d8bb6df10513fb742d44"
                      variavel: "6037d8bb6df10513fb742d46"
              imagens:
                - "https://www.vendizap.com/imagens/produto1.jpg"
                - "https://www.vendizap.com/imagens/produto2.jpg"
              detalhes: "Detalhes do produto de exemplo"
              categorias: []
              unidadeVenda: "Unidade"
              unidadePreco: "Unidade"
              codigo: "10"
              qtdeMinima: 0
              qtdeMaxima: 0
              exibir: true
              destaque: false
      responses:
        "201":
          description: Produto criado com sucesso (com ou sem erros parciais).
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: "#/components/schemas/IdResponse"
                  - $ref: "#/components/schemas/IdComErrosResponse"
              examples:
                sucesso:
                  summary: Cadastrar produto
                  value:
                    id: "604284466df1054914132443"
                comErros:
                  summary: Cadastrar produto (retorno com erros)
                  value:
                    id: "604284466df1054914132443"
                    erros:
                      - "Não foi possível vincular a imagem de índice 2 para a variável 6037f540b6fa7c03441457b6 da variação 6037f3e2b6fa7c00064e2cb2"
        "400": { $ref: "#/components/responses/BadRequest" }
        "401": { $ref: "#/components/responses/Unauthorized" }
    get:
      operationId: list_products
      tags: [Produtos]
      summary: Listar produtos
      description: |
        Método utilizado para fazer uma busca dos produtos, sendo possível
        utilizar os campos do produto como filtro. O retorno deste método
        será um array de objetos de produtos. Os produtos serão retornados
        de maneira resumida; caso queira o produto completo, deve ser
        buscado pelo **ID** através do endpoint **Buscar produto** abaixo.

        Com exceção dos campos `variacoes`, `imagens` e `promocao`, todos
        os demais podem ser utilizados como filtro. Todos podem ser
        filtrados com o seu respectivo nome, com exceção do campo
        `categorias`, que deve ser filtrado como `categoria`.

        Os campos `descricao`, `codigo` e `detalhes` fazem a busca parcial,
        ou seja, qualquer produto que contenha parte do texto informado
        será retornado. Os demais campos fazem busca exata (equivalente
        ao operador `=`).
      parameters:
        - name: descricao
          in: query
          required: false
          description: Descrição (parcial) do produto.
          schema: { type: string }
        - name: skip
          in: query
          required: false
          description: Quantidade de registros a serem ignorados (paginação).
          schema: { type: integer }
        - name: limit
          in: query
          required: false
          description: Quantidade máxima de registros a retornar.
          schema: { type: integer }
        - name: sort
          in: query
          required: false
          description: Campo a ser utilizado para ordenação (ex.&nbsp;`descricao`).
          schema: { type: string }
        - name: sortType
          in: query
          required: false
          description: Tipo de ordenação.
          schema:
            type: string
            enum: [ASC, DESC]
        - name: categoria
          in: query
          required: false
          description: ID da categoria para filtrar produtos.
          schema: { type: string }
      responses:
        "200":
          description: Lista de produtos (resumida).
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/ProdutoListItem"
              example:
                - descricao: "Produto exemplo"
                  preco: 9.99
                  unidadeVenda: "Unidade"
                  destaque: false
                  codigo: "10"
                  exibir: true
                  dt_cadastro: "2021-02-11 13:22:36"
                  dt_alteracao: "2021-03-01 11:23:21"
                  id: "60254bbcb6fa7c731139e763"
                - descricao: "Produto teste API"
                  preco: 20
                  unidadeVenda: "Unidade"
                  destaque: false
                  codigo: "1054"
                  exibir: true
                  dt_cadastro: "2021-02-26 19:30:41"
                  dt_alteracao: "2021-03-10 12:36:15"
                  id: "60397691b6fa7c849962a025"
        "401": { $ref: "#/components/responses/Unauthorized" }

  /produtos/{produtoId}:
    parameters:
      - $ref: "#/components/parameters/ProdutoIdPath"
    put:
      operationId: update_product
      x-mcp-open-world: true
      tags: [Produtos]
      summary: Atualizar produto
      description: |
        Este método é utilizado para atualizar um produto existente. Todos os
        campos que forem informados na requisição serão atualizados. No caso
        de `variacoes`, `imagens` e `categorias`, que são _arrays_, caso
        sejam enviados, **substituirão** as atuais (caso deseje atualizar
        parcialmente, veja o método **PATCH** abaixo).

        **OBS:** Para excluir uma promoção de um produto, basta enviar o
        campo `promocao` como `null`.

        **ATENÇÃO:** No caso de enviar variações neste método, como elas
        substituirão as atuais, caso o estoque do produto seja controlado
        pela variação, o mesmo será zerado.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ProdutoUpdate"
            example:
              combinacoes:
                - codigo: "api"
                  preco: 12
                  ean: "7891234567890"
                  combinacao:
                    - variacao: "Tamanho"
                      variavel: "P"
      responses:
        "200":
          description: Produto atualizado.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/IdResponse"
              example:
                id: "604284466df1054914132443"
        "400": { $ref: "#/components/responses/BadRequest" }
        "401": { $ref: "#/components/responses/Unauthorized" }
    patch:
      operationId: update_product_partial
      x-mcp-open-world: true
      tags: [Produtos]
      summary: Atualizar produto (parcial)
      description: |
        Este método é utilizado para atualizar um produto existente. É
        similar ao método **PUT**, porém a principal diferença é que campos
        que são arrays como `variacoes`, `imagens` e `categorias`, quando
        informados através deste método, serão apenas **acrescentados**, e
        não substituídos como acontece no **PUT**.

        **Exemplo:** caso seja enviado um array com 1 imagem neste método
        para um produto que contenha 2 imagens, essa imagem será acrescentada
        no produto, ficando ele com 3 imagens. O mesmo acontece para
        variações e categorias. Em relação às variações, caso o controle de
        estoque seja impactado com a inclusão de uma variação, o estoque
        será zerado.

        Os demais campos são possíveis de atualizar normalmente, conforme
        o método **PUT**.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ProdutoUpdate"
            example:
              variacoes:
                - id: "6037d8bb6df10513fb742d40"
                  obrigatoria: true
                  multipla_selecao: false
                  adicional: false
                  variaveis:
                    - id: "6037d8bb6df10513fb742d42"
                      preco: 0
                      imagem: 0
                    - id: "6037d8bb6df10513fb742d43"
                      preco: 0
                      imagem: 1
      responses:
        "200":
          description: Produto atualizado parcialmente.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/IdResponse"
              example:
                id: "604284466df1054914132443"
        "400": { $ref: "#/components/responses/BadRequest" }
        "401": { $ref: "#/components/responses/Unauthorized" }
    get:
      operationId: get_product
      tags: [Produtos]
      summary: Buscar produto
      description: |
        Método utilizado para buscar um produto em específico através do seu
        **ID**. Este método retornará um objeto com o produto completo
        contendo todos os seus campos.
      responses:
        "200":
          description: Produto encontrado.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Produto"
              example:
                id: "60254bbcb6fa7c731139e763"
                descricao: "Produto exemplo"
                detalhes: "Detalhes do produto de exemplo"
                preco: 9.99
                unidadeVenda: "Unidade"
                unidadePreco: "Unidade"
                categorias:
                  - id: "601d957bb6fa7c11ba209426"
                    nome: "Utensílios"
                variacoes:
                  - id: "6037f3e2b6fa7c00064e2cb2"
                    nome: "Variacao Teste"
                    variaveis:
                      - id: "604776f1b6fa7c87726f43e3"
                        nome: "Variável 1"
                        preco: 0
                        codigo: ""
                        imagem: "https://minio.vendizap.com/produtos/8b5c26aaa4539ef48ca42bbfb98cc47c.jpg"
                      - id: "6048ae8fb6fa7c29972c882b"
                        nome: "Variável 2"
                        preco: 0
                        codigo: ""
                        imagem: null
                      - id: "6048ae91b6fa7c29991d33e6"
                        nome: "Variável 3"
                        preco: 0
                        codigo: ""
                        imagem: null
                    multipla_selecao: false
                    obrigatoria: true
                    adicional: false
                    qtdeMinima: null
                    qtdeMaxima: null
                promocao:
                  inicio: "2021-02-14 22:00:00"
                  fim: "2021-02-24 20:59:59"
                  percentual: 9.999999999999996
                  precoPromocional: 26.991
                destaque: true
                codigo: "10"
                qtdeMinima: 0
                qtdeMaxima: 0
                exibir: true
                dt_cadastro: "2021-02-11 13:22:36"
                dt_alteracao: "2021-03-01 11:23:21"
                imagens:
                  - "https://minio.vendizap.com/produtos/8b5c26aaa4539ef48ca42bbfb98cc47c.jpg"
                  - "https://minio.vendizap.com/produtos/af9d54f62ac290dc083d2b8b8e58697a.jpg"
        "401": { $ref: "#/components/responses/Unauthorized" }

  # ============================================================== ESTOQUE
  /estoque/{produtoId}:
    parameters:
      - $ref: "#/components/parameters/ProdutoIdPath"
    put:
      operationId: update_product_stock
      x-mcp-open-world: true
      tags: [Estoque]
      summary: Atualizar estoque
      description: |
        Atualiza o estoque do produto. O corpo da requisição varia conforme
        o cenário:

        - **Produto sem variação:** envie um objeto com `quantidade`.
        - **Produto com variações (via IDs):** envie um array de objetos
          contendo `quantidade` e `combinacao` (mapa de `idVariacao` →
          `idVariavel`).
        - **Produto com variações (via SKU):** envie um array de objetos
          contendo `quantidade` e `combinacaoSKU`.
        - **Produto com variações (via ID da combinação):** envie um array
          de objetos contendo `quantidade` e `combinacaoId`.

        O retorno é o boolean `true` em caso de sucesso.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              oneOf:
                - $ref: "#/components/schemas/EstoqueSemVariacao"
                - type: array
                  items:
                    $ref: "#/components/schemas/EstoqueCombinacaoIdsItem"
                - type: array
                  items:
                    $ref: "#/components/schemas/EstoqueCombinacaoSKUItem"
                - type: array
                  items:
                    $ref: "#/components/schemas/EstoqueCombinacaoIdItem"
            examples:
              SemVariacao:
                summary: Atualizar estoque - Sem variação
                description: |
                  Exemplo de um produto simples (sem variação) atualizando
                  o estoque para 11.
                value:
                  quantidade: 11
              CombinacaoPorIds:
                summary: Atualizar estoque - Id Variação/Variável
                description: |
                  Atualiza o estoque de combinações utilizando os IDs das
                  variações e variáveis que compõem a combinação. Deve ser
                  utilizado apenas para produtos que possuam variações.
                value:
                  - quantidade: 15
                    combinacao:
                      "6037d8bb6df10513fb742d5a": "6037d8bb6df10513fb742d39"
                      "6037d8bb6df10513fb742d44": "6037d8bb6df10513fb742d47"
                  - quantidade: 5
                    combinacao:
                      "6037d8bb6df10513fb742d5a": "6037d8bb6df10513fb742d38"
                      "6037d8bb6df10513fb742d44": "6037d8bb6df10513fb742d46"
              CombinacaoPorSKU:
                summary: Atualizar estoque - Código SKU (Combinação)
                description: |
                  Atualiza o estoque de combinações utilizando o código SKU.
                value:
                  - quantidade: 15
                    combinacaoSKU: "SKU_P_AZUL"
                  - quantidade: 5
                    combinacaoSKU: "SKU_M_AZUL"
              CombinacaoPorId:
                summary: Atualizar estoque - Id (Combinação)
                description: |
                  Atualiza o estoque de combinações utilizando o ID da combinação.
                value:
                  - quantidade: 15
                    combinacaoId: "66831670fbf70d6ba1726972"
                  - quantidade: 5
                    combinacaoId: "66571e84d590f749515092e4"
      responses:
        "200":
          description: Estoque atualizado.
          content:
            application/json:
              schema:
                type: boolean
              example: true
        "400": { $ref: "#/components/responses/BadRequest" }
        "401": { $ref: "#/components/responses/Unauthorized" }

  # ============================================================== PEDIDOS
  /pedidos:
    get:
      operationId: list_orders
      tags: [Pedidos]
      summary: Buscar pedidos
      description: |
        Consulta pedidos por intervalo de datas ou por uma data específica.
        Utilize `dataInicial`/`dataFinal` para um intervalo, ou `data` para
        uma única data.
      parameters:
        - name: tipoData
          in: query
          required: false
          description: |
            `criacao` (padrão) filtra pelos pedidos criados.
            `atualizacao` filtra pela data da última modificação.
          schema:
            type: string
            enum: [criacao, atualizacao]
            default: criacao
          example: criacao
        - name: dataInicial
          in: query
          required: false
          description: "Data e hora inicial no formato DD/MM/YYYY HH:MM:SS."
          schema: { type: string }
          example: "05/01/2023 00:00:00"
        - name: dataFinal
          in: query
          required: false
          description: "Data e hora final no formato DD/MM/YYYY HH:MM:SS."
          schema: { type: string }
          example: "05/09/2023 23:59:59"
        - name: data
          in: query
          required: false
          description: "Data única (alternativa ao intervalo) no formato DD/MM/YYYY."
          schema: { type: string }
          example: "14/06/2023"
        - name: cancelados
          in: query
          required: false
          description: Indica se devem ou não ser retornados pedidos cancelados.
          schema:
            type: boolean
            default: false
        - name: somenteNovos
          in: query
          required: false
          description: Retorna apenas pedidos novos.
          schema:
            type: boolean
            default: false
        - name: consultarVendedores
          in: query
          required: false
          description: Indica se devem ou não ser retornados pedidos das contas de vendedores vinculados.
          schema:
            type: boolean
            default: true
        - name: skip
          in: query
          required: false
          description: Quantidade de registros a serem ignorados (paginação).
          schema:
            type: integer
            default: 0
        - name: limit
          in: query
          required: false
          description: Quantidade máxima de pedidos retornados (paginação, use com `skip`). Valores acima de 200 são reduzidos para 200.
          schema:
            type: integer
            default: 50
            minimum: 1
            maximum: 200
            x-mcp-inject-default: true
      responses:
        "200":
          description: Pedidos encontrados.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/Pedido"
              examples:
                BuscarPedidos:
                  summary: Buscar pedidos
                  value:
                    - id: "6040ee0eb6fa7c21341c2617"
                      data: "2021-03-04 11:26:21"
                      itens:
                        - id_produto: "5e9613a41c23e16216777a62"
                          descricao: "Produto teste"
                          detalhes: ""
                          preco: 1
                          controle_estoque: true
                          unidadeVenda: "Unidade"
                          unidadePreco: "Unidade"
                          categorias: ["Bebidas"]
                          precoPromocional: null
                          quantidade: 1
                          observacaoProduto: ""
                          relacaoVariacao:
                            - nome: "Tamanho"
                              variaveis:
                                - nome: "900ml"
                                  quantidade: 1
                                  valorAdicional: 0
                                  codigo: "m"
                                  id: "604613f7b6fa7c832e5a0314"
                              multipla_selecao: false
                              obrigatoria: true
                              adicional: false
                              qtdeMinima: 1
                              qtdeMaxima: null
                              quantidadeSelecionada: 0
                              valorAdicionais: 0
                              codigo: "1"
                              id: "6035138cb6fa7c30a933452a"
                          codigo: "teste"
                          dimensoes: null
                          embalagemTransporte: null
                      entrega: true
                      dataHoraRetirada: null
                      observacao: ""
                      pagamento:
                        descricao: "Dinheiro"
                        utilizaTroco: true
                        utilizaBandeira: false
                        bandeiraSelecionada: null
                        parcelas: null
                        id: "5ecfefb393eab21d8d4b3acf"
                        dt_alteracao: null
                      taxaEntrega: 0
                      qrcode: null
                      valorPedido: 1
                      valorAproximado: false
                      numero: 162
                      importacaoErp: 0
                      vendedor: null
                      cliente:
                        nome: "José"
                        documento: "999.999.999-99"
                        telefone: "(44) 99999-9999"
                        endereco:
                          cep: "99999-999"
                          logradouro: "Avenida Brasil"
                          numero: "9999"
                          bairro: "Centro"
                          pais: "Brasil"
                          estado: "PR"
                          cidade: "Maringá"
                          complemento: "apartamento 19"
                BuscarPedidosVendedor:
                  summary: Buscar pedidos - Vendedor
                  description: Quando o pedido foi efetuado por uma conta de vendedor vinculada.
                  value:
                    - id: "6040ee0eb6fa7c21341c2617"
                      data: "2021-03-04 11:26:21"
                      itens:
                        - id_produto: "5e9613a41c23e16216777a62"
                          descricao: "Produto teste"
                          detalhes: ""
                          preco: 1
                          controle_estoque: true
                          unidadeVenda: "Unidade"
                          unidadePreco: "Unidade"
                          categorias: ["Bebidas"]
                          precoPromocional: null
                          quantidade: 1
                          observacaoProduto: ""
                          relacaoVariacao:
                            - nome: "Tamanho"
                              variaveis:
                                - nome: "900ml"
                                  quantidade: 1
                                  valorAdicional: 0
                                  codigo: "m"
                                  id: "604613f7b6fa7c832e5a0314"
                              multipla_selecao: false
                              obrigatoria: true
                              adicional: false
                              qtdeMinima: 1
                              qtdeMaxima: null
                              quantidadeSelecionada: 0
                              valorAdicionais: 0
                              codigo: "1"
                              id: "6035138cb6fa7c30a933452a"
                          codigo: "teste"
                          dimensoes: null
                          embalagemTransporte: null
                      entrega: true
                      dataHoraRetirada: null
                      observacao: ""
                      pagamento:
                        descricao: "Dinheiro"
                        utilizaTroco: true
                        utilizaBandeira: false
                        bandeiraSelecionada: null
                        parcelas: null
                        id: "5ecfefb393eab21d8d4b3acf"
                        dt_alteracao: null
                      taxaEntrega: 0
                      qrcode: null
                      valorPedido: 1
                      valorAproximado: false
                      numero: 162
                      importacaoErp: 0
                      vendedor:
                        id: "6035137cb6fa7c30a933452a"
                        nome: "Nome - Vendedor"
                      cliente:
                        nome: "José"
                        documento: "999.999.999-99"
                        telefone: "(44) 99999-9999"
                        endereco:
                          cep: "99999-999"
                          logradouro: "Avenida Brasil"
                          numero: "9999"
                          bairro: "Centro"
                          pais: "Brasil"
                          estado: "PR"
                          cidade: "Maringá"
                          complemento: "apartamento 19"
                BuscarPedidosPorData:
                  summary: Buscar pedidos - Data
                  description: Consulta por uma data única usando o parâmetro `data`.
                  value:
                    - id: "6040ee0eb6fa7c21341c2617"
                      data: "2021-03-04 11:26:21"
                      itens:
                        - id_produto: "5e9613a41c23e16216777a62"
                          descricao: "Produto teste"
                          detalhes: ""
                          preco: 1
                          controle_estoque: true
                          unidadeVenda: "Unidade"
                          unidadePreco: "Unidade"
                          categorias: ["Bebidas"]
                          precoPromocional: null
                          quantidade: 1
                          observacaoProduto: ""
                          relacaoVariacao:
                            - nome: "Tamanho"
                              variaveis:
                                - nome: "900ml"
                                  quantidade: 1
                                  valorAdicional: 0
                                  id: "604613f7b6fa7c832e5a0314"
                              multipla_selecao: false
                              obrigatoria: true
                              adicional: false
                              qtdeMinima: 1
                              qtdeMaxima: null
                              quantidadeSelecionada: 0
                              valorAdicionais: 0
                              id: "6035138cb6fa7c30a933452a"
                          dimensoes: null
                          embalagemTransporte: null
                      entrega: true
                      dataHoraRetirada: null
                      observacao: ""
                      pagamento:
                        descricao: "Dinheiro"
                        utilizaTroco: true
                        utilizaBandeira: false
                        bandeiraSelecionada: null
                        parcelas: null
                        id: "5ecfefb393eab21d8d4b3acf"
                        dt_alteracao: null
                      taxaEntrega: 0
                      qrcode: null
                      valorPedido: 1
                      valorAproximado: false
                      numero: 162
                      importacaoErp: 0
                      vendedor: null
                      cliente:
                        nome: "José"
                        documento: "999.999.999-99"
                        telefone: "(44) 99999-9999"
                        endereco:
                          cep: "99999-999"
                          logradouro: "Avenida Brasil"
                          numero: "9999"
                          bairro: "Centro"
                          pais: "Brasil"
                          estado: "PR"
                          cidade: "Maringá"
                          complemento: "apartamento 19"
        "401": { $ref: "#/components/responses/Unauthorized" }

  /pedidos/{pedidoId}:
    parameters:
      - $ref: "#/components/parameters/PedidoIdPath"
    get:
      operationId: get_order
      tags: [Pedidos]
      summary: Buscar pedido
      description: |
        Esse método é responsável por retornar o pedido completo em formato
        JSON, contendo todos os dados do cliente, itens (produtos) e suas
        variações, como mostra o exemplo.
      responses:
        "200":
          description: Pedido completo.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Pedido"
              example:
                id: "6040ee0eb6fa7c21341c2617"
                data: "2021-03-04 11:26:21"
                itens:
                  - id_produto: "5e9613a41c23e16216777a62"
                    descricao: "Produto teste"
                    detalhes: ""
                    preco: 1
                    controle_estoque: true
                    unidadeVenda: "Unidade"
                    unidadePreco: "Unidade"
                    categorias: ["Bebidas"]
                    precoPromocional: null
                    quantidade: 1
                    observacaoProduto: ""
                    relacaoVariacao:
                      - nome: "Tamanho"
                        variaveis:
                          - nome: "900ml"
                            quantidade: 1
                            valorAdicional: 0
                            id: "604613f7b6fa7c832e5a0314"
                        multipla_selecao: false
                        obrigatoria: true
                        adicional: false
                        qtdeMinima: 1
                        qtdeMaxima: null
                        quantidadeSelecionada: 0
                        valorAdicionais: 0
                        id: "6035138cb6fa7c30a933452a"
                    dimensoes: null
                    embalagemTransporte: null
                entrega: true
                dataHoraRetirada: null
                observacao: ""
                pagamento:
                  descricao: "Dinheiro"
                  utilizaTroco: true
                  utilizaBandeira: false
                  bandeiraSelecionada: null
                  parcelas: null
                  id: "5ecfefb393eab21d8d4b3acf"
                  dt_alteracao: null
                taxaEntrega: 0
                qrcode: null
                valorPedido: 1
                valorAproximado: false
                numero: 162
                importacaoErp: 0
                vendedor: null
                cliente:
                  nome: "José"
                  documento: "999.999.999-99"
                  telefone: "(44) 99999-9999"
                  endereco:
                    cep: "99999-999"
                    logradouro: "Avenida Brasil"
                    numero: "9999"
                    bairro: "Centro"
                    pais: "Brasil"
                    estado: "PR"
                    cidade: "Maringá"
                    complemento: "apartamento 19"
                status:
                  preparacao: true
                  separacao: true
                  enviado: false
                  entregue: false
                  pagamento: true
        "401": { $ref: "#/components/responses/Unauthorized" }

  /pedidos/{pedidoId}/status:
    parameters:
      - $ref: "#/components/parameters/PedidoIdPath"
    patch:
      operationId: update_order_status
      # Descrição dedicada da tool MCP: explicita que a etapa 'pagamento' só marca status (não
      # movimenta dinheiro) — sem isso, reviewers de diretório de connector a confundem com
      # execução de transação financeira, que é caso vetado.
      x-mcp-description: |
        Atualiza a etapa de andamento do pedido (preparacao, separacao, enviado, entregue)
        com efeito cascata server-side: marcar uma etapa conclui as anteriores e deixa as
        posteriores pendentes; envie valor=false para desmarcar e regredir. A etapa 'pagamento'
        apenas registra manualmente que o pedido foi pago (ex.: dinheiro na entrega) — NÃO
        processa nem movimenta dinheiro, e é rejeitada quando o pedido tem cobrança eletrônica
        (carteira, link de pagamento ou Pix). Atualiza apenas pedidos da própria conta; pedidos
        de vendedores vinculados retornam "pedido não encontrado".
      tags: [Pedidos]
      summary: Atualizar status do pedido
      description: |
        Atualiza a etapa de andamento do pedido com efeito cascata server-side:
        ao marcar uma etapa, todas as etapas anteriores são automaticamente
        marcadas como concluídas e as posteriores ficam pendentes.

        Para desmarcar uma etapa e regredir o pedido, envie `valor: false`.

        **Atenção:** a etapa `pagamento` apenas confirma/cancela o pagamento
        manualmente — **não** aciona link de pagamento, carteira digital ou Pix,
        e **não** envia notificação de WhatsApp ao cliente. Marcar `pagamento`
        dispara o webhook de pagamento do lojista (`pagamento_confirmado` quando
        `valor: true`, `pagamento_cancelado` quando `valor: false`); as demais
        etapas não disparam webhook. Se o pedido tiver pagamento por carteira
        virtual, link de pagamento ou Pix **ativo (Pendente) ou aprovado
        (Aprovado)**, a alteração da etapa `pagamento` é **rejeitada** — nesses
        casos o pagamento deve ser gerenciado pelo painel da plataforma.

        O endpoint atualiza apenas pedidos da própria conta da credencial:
        pedidos de vendedores vinculados (visíveis no GET /pedidos com
        `consultarVendedores=true`) não são alteráveis por aqui e retornam
        `pedido não encontrado`.

        Respostas 400 (texto): status inválido (fora de
        `preparacao|separacao|enviado|entregue|pagamento`), campo `valor`
        não-booleano, pedido cancelado, etapa `enviado` não aplicável a pedido
        sem entrega/retirada em outro local, alteração da etapa `pagamento` em
        pedido com pagamento por carteira virtual/link/Pix ativo ou aprovado
        (gerencie pelo painel), id do pedido inválido, ou pedido
        não encontrado (inclui pedido de outra loja ou de vendedor vinculado).
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/PedidoStatusUpdate"
            example:
              status: "preparacao"
              valor: true
      responses:
        "200":
          description: Status atualizado.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PedidoStatus"
              example:
                preparacao: true
                separacao: false
                enviado: false
                entregue: false
                pagamento: false
        "400": { $ref: "#/components/responses/BadRequest" }
        "401": { $ref: "#/components/responses/Unauthorized" }

  # ============================================================== PRODUTO VARIAÇÕES
  /produtoVariacoes/{produtoId}:
    parameters:
      - $ref: "#/components/parameters/ProdutoIdPath"
    post:
      operationId: create_product_variation
      x-mcp-open-world: true
      tags: [Produto Variações]
      summary: Vincular variação no produto
      description: |
        Método utilizado para vincular uma nova variação ao produto. A
        variação informada neste método será vinculada no produto. Deve ser
        informada com as respectivas variáveis.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ProdutoVariacaoVincularInput"
            example:
              id: "6053bb9b6df1055978541352"
              obrigatoria: true
              multipla_selecao: false
              adicional: false
              qtdeMinima: null
              qtdeMaxima: null
              variaveis:
                - id: "6053bb9b6df1055978541358"
                  preco: 0
                  imagem: 0
      responses:
        "201":
          description: Variação vinculada ao produto.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProdutoVariacaoDetalhe"
              example:
                id: "6037f3e2b6fa7c00064e2cb2"
                nome: "Variação teste"
                variaveis:
                  - id: "6037f540b6fa7c03441457b6"
                    nome: "Variável 1"
                    preco: 0
                    imagem: null
                multipla_selecao: false
                obrigatoria: true
                adicional: false
                qtdeMinima: null
                qtdeMaxima: null
        "400": { $ref: "#/components/responses/BadRequest" }
        "401": { $ref: "#/components/responses/Unauthorized" }
    get:
      operationId: list_product_variations
      tags: [Produto Variações]
      summary: Listar variações de um produto
      description: |
        Método utilizado para listar todas as variações e respectivas
        variáveis que um produto possui. Com exceção das variáveis, todos
        os demais campos da variação podem ser utilizados como filtro via
        query string, com a única particularidade que o campo `nome` não
        fará a busca exata e sim trará a variação que contém parte daquele
        texto no nome.
      parameters:
        - name: nome
          in: query
          required: false
          description: Nome (parcial) da variação.
          schema: { type: string }
        - name: obrigatoria
          in: query
          required: false
          description: Filtra variações obrigatórias.
          schema: { type: boolean }
      responses:
        "200":
          description: Lista de variações do produto.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/ProdutoVariacaoDetalhe"
              example:
                - id: "60461196b6fa7c83fa48ecee"
                  nome: "Variacao Teste"
                  variaveis:
                    - id: "60461196b6fa7c83fa48ecef"
                      nome: "Variável 1"
                      preco: 0
                      imagem: null
                    - id: "60461196b6fa7c83fa48ecf0"
                      nome: "Variável 2"
                      preco: 0
                      imagem: null
                  multipla_selecao: false
                  obrigatoria: true
                  adicional: false
                  qtdeMinima: null
                  qtdeMaxima: null
                - id: "6037f3e2b6fa7c00064e2cb2"
                  nome: "Variação API"
                  variaveis:
                    - id: "6037f540b6fa7c03441457b6"
                      nome: "Variável x"
                      preco: 0
                      imagem: null
                    - id: "6037f540b6fa7c03441457b7"
                      nome: "Variável y"
                      preco: 0
                      codigo: "v2"
                  multipla_selecao: false
                  obrigatoria: true
                  adicional: false
                  qtdeMinima: null
                  qtdeMaxima: null
        "401": { $ref: "#/components/responses/Unauthorized" }

  /produtoVariacoes/{produtoId}/{variacaoId}:
    parameters:
      - $ref: "#/components/parameters/ProdutoIdPath"
      - $ref: "#/components/parameters/VariacaoIdPath"
    put:
      operationId: update_product_variation
      x-mcp-open-world: true
      tags: [Produto Variações]
      summary: Atualizar variação do produto
      description: |
        Método utilizado para atualizar uma variação já vinculada em um
        produto. Dependendo da alteração de indicadores, o estoque pode ser
        afetado. As variáveis informadas neste método **substituem** as
        atuais existentes; dessa forma, o estoque das variáveis existentes
        será zerado. Caso queira apenas adicionar uma nova variável, utilize
        o método **PATCH** abaixo ou o método **POST** de Produto Variáveis.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ProdutoVariacaoUpdate"
            example:
              obrigatoria: true
              multipla_selecao: false
              adicional: false
      responses:
        "200":
          description: Variação do produto atualizada.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProdutoVariacaoDetalhe"
              example:
                id: "6037f3e2b6fa7c00064e2cb2"
                nome: "Variação teste"
                variaveis:
                  - id: "6037f540b6fa7c03441457b6"
                    nome: "Variável 1"
                    preco: 0
                    imagem: null
                multipla_selecao: true
                obrigatoria: false
                adicional: true
                qtdeMinima: null
                qtdeMaxima: null
        "400": { $ref: "#/components/responses/BadRequest" }
        "401": { $ref: "#/components/responses/Unauthorized" }
    patch:
      operationId: update_product_variation_partial
      x-mcp-open-world: true
      tags: [Produto Variações]
      summary: Atualizar variação do produto (parcial)
      description: |
        Método utilizado para atualizar uma variação já vinculada em um
        produto. Funciona similar ao método **PUT** acima, porém com a
        diferença de que as variáveis informadas serão apenas **adicionadas**
        no produto e não substituídas.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ProdutoVariacaoUpdate"
            example:
              obrigatoria: true
              multipla_selecao: false
              adicional: false
              variaveis:
                - id: "6037f540b6fa7c03441457b6"
      responses:
        "200":
          description: Variação do produto atualizada parcialmente.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProdutoVariacaoDetalhe"
              example:
                id: "6037f3e2b6fa7c00064e2cb2"
                nome: "Variação teste"
                variaveis:
                  - id: "6037f540b6fa7c03441457b6"
                    nome: "Variável 1"
                    preco: 0
                    imagem: null
                  - id: "6048aea5b6fa7c299835f50c"
                    nome: "Variável 2"
                    preco: 0
                    imagem: null
                multipla_selecao: false
                obrigatoria: true
                adicional: false
                qtdeMinima: null
                qtdeMaxima: null
        "400": { $ref: "#/components/responses/BadRequest" }
        "401": { $ref: "#/components/responses/Unauthorized" }
    get:
      operationId: get_product_variation
      tags: [Produto Variações]
      summary: Buscar variação de um produto
      description: |
        Método utilizado para retornar uma variação específica de um
        determinado produto e suas respectivas variáveis.
      responses:
        "200":
          description: Variação do produto.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProdutoVariacaoDetalhe"
              example:
                id: "60461196b6fa7c83fa48ecee"
                nome: "Variacao Teste"
                variaveis:
                  - id: "60461196b6fa7c83fa48ecef"
                    nome: "Variável 1"
                    preco: 0
                    imagem: null
                  - id: "60461196b6fa7c83fa48ecf0"
                    nome: "Variável 2"
                    preco: 0
                    imagem: null
                multipla_selecao: false
                obrigatoria: true
                adicional: false
                qtdeMinima: null
                qtdeMaxima: null
                codigo: "Teste"
        "401": { $ref: "#/components/responses/Unauthorized" }
    delete:
      operationId: delete_product_variation
      x-mcp-open-world: true
      tags: [Produto Variações]
      summary: Desvincular variação do produto
      description: |
        Método utilizado para excluir (desvincular) uma variação de um
        produto. Ao executar este método, a variação informada e suas
        respectivas variáveis serão "desmarcadas" para o produto informado.
        Nos casos em que esta variação fazia parte do controle de estoque
        do produto, todo o estoque dele será zerado.
      responses:
        "200":
          description: Variação desvinculada.
          content:
            application/json:
              schema:
                type: boolean
              example: true
        "400": { $ref: "#/components/responses/BadRequest" }
        "401": { $ref: "#/components/responses/Unauthorized" }

  # ============================================================== PRODUTO VARIÁVEIS
  /produtoVariaveis/{produtoId}/{variacaoId}:
    parameters:
      - $ref: "#/components/parameters/ProdutoIdPath"
      - $ref: "#/components/parameters/VariacaoIdPath"
    post:
      operationId: create_product_variation_value
      x-mcp-open-world: true
      tags: [Produto Variáveis]
      summary: Vincular variável na variação do produto
      description: Método utilizado para vincular uma nova variável a uma variação do produto.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ProdutoVariavelVincularInput"
            example:
              id: "60dfb46dc4f8da63d518c1d2"
      responses:
        "201":
          description: Variável vinculada à variação do produto.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProdutoVariavelDetalhe"
              example:
                id: "6037f540b6fa7c03441457b6"
                nome: "Variável 1"
                preco: 0
                imagem: "https://minio.vendizap.com/produtos/75ffe8875716db9e8da84ec77322c38d.jpg"
        "400": { $ref: "#/components/responses/BadRequest" }
        "401": { $ref: "#/components/responses/Unauthorized" }
    get:
      operationId: list_product_variation_values
      tags: [Produto Variáveis]
      summary: Listar variáveis de uma variação do produto
      description: |
        Método utilizado para listar todas as variáveis que estão vinculadas
        a uma variação do produto. Retorna um array de objetos com as
        variáveis e podem ser utilizados os campos nos query params para
        filtrar (opcionais). O campo `nome` localiza todas as variáveis
        que contenham parte do texto informado.
      parameters:
        - name: nome
          in: query
          required: false
          description: Nome (parcial) da variável.
          schema: { type: string }
        - name: preco
          in: query
          required: false
          description: Preço (busca exata).
          schema: { type: number }
      responses:
        "200":
          description: Lista de variáveis da variação do produto.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/ProdutoVariavelDetalhe"
              example:
                - id: "60461196b6fa7c83fa48ecef"
                  nome: "Variável 1"
                  preco: 0
                  imagem: null
                - id: "60461196b6fa7c83fa48ecf0"
                  nome: "Variável 2"
                  preco: 1.99
                  imagem: null
        "401": { $ref: "#/components/responses/Unauthorized" }

  /produtoVariaveis/{produtoId}/{variacaoId}/{variavelId}:
    parameters:
      - $ref: "#/components/parameters/ProdutoIdPath"
      - $ref: "#/components/parameters/VariacaoIdPath"
      - $ref: "#/components/parameters/VariavelIdPath"
    put:
      operationId: update_product_variation_value
      x-mcp-open-world: true
      tags: [Produto Variáveis]
      summary: Atualizar variável do produto
      description: Método utilizado para alterar uma variável existente em uma variação no produto.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ProdutoVariavelUpdate"
            example:
              preco: 2
      responses:
        "200":
          description: Variável atualizada.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProdutoVariavelDetalhe"
              example:
                id: "6037f540b6fa7c03441457b6"
                nome: "Variável 1"
                preco: 2
                imagem: "https://minio.vendizap.com/produtos/75ffe8875716db9e8da84ec77322c38d.jpg"
        "400": { $ref: "#/components/responses/BadRequest" }
        "401": { $ref: "#/components/responses/Unauthorized" }
    get:
      operationId: get_product_variation_value
      tags: [Produto Variáveis]
      summary: Buscar variável de uma variação do produto
      description: |
        Método utilizado para buscar uma variável específica vinculada a uma
        variação de um produto. Retorna um objeto com os dados da variável.
      responses:
        "200":
          description: Variável encontrada.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProdutoVariavelDetalhe"
              example:
                id: "60461196b6fa7c83fa48ecef"
                nome: "Variável 1"
                preco: 0
                imagem: null
        "401": { $ref: "#/components/responses/Unauthorized" }
    delete:
      operationId: delete_product_variation_value
      x-mcp-open-world: true
      tags: [Produto Variáveis]
      summary: Desvincular variável do produto
      description: |
        Método utilizado para desvincular (excluir) uma variável de uma
        variação do produto.

        **ATENÇÃO:** Caso o produto controle estoque por essa variação e
        essa variável possua saldo em estoque, o mesmo será zerado.
      responses:
        "200":
          description: Variável desvinculada.
          content:
            application/json:
              schema:
                type: boolean
              example: true
        "400": { $ref: "#/components/responses/BadRequest" }
        "401": { $ref: "#/components/responses/Unauthorized" }

  # ============================================================== PRODUTO COMBINAÇÕES
  /produtoCombinacoes/{produtoId}:
    parameters:
      - $ref: "#/components/parameters/ProdutoIdPath"
    post:
      operationId: create_product_combinations
      x-mcp-open-world: true
      # lote pode sobrescrever combinações já existentes do produto (resposta "alteradas")
      x-mcp-destructive: true
      tags: [Produto Combinações]
      summary: Vincular combinações no produto
      description: |
        Método utilizado para adicionar combinações no produto, sendo
        possível adicionar código (SKU), preço e/ou EAN (código de barras)
        em cada combinação.

        O método aceita um array de combinações. As variações e variáveis
        podem ser enviadas usando o nome ou o id.

        O array `combinacao` deve conter os pares de variação e variável;
        esses pares devem ser os mesmos já vinculados no produto e todas as
        variações e variáveis também devem estar ativadas no produto.

        Caso o sistema encontre alguma divergência na combinação, ela não
        será vinculada ao produto e retornará mais informações no objeto
        `erros`.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ProdutoCombinacoesInput"
            example:
              combinacoes:
                - codigo: "SKU_API_NOME"
                  preco: 0
                  ean: "7891234567890"
                  combinacao:
                    - variacao: "Tamanho"
                      variavel: "P"
                    - variacao: "Cor"
                      variavel: "Azul"
                - codigo: "SKU_API_ID"
                  preco: 10
                  combinacao:
                    - variacao: "6037d8bb6df10513fb742d40"
                      variavel: "655e3fe59a41cd020c30ff19"
                    - variacao: "6037d8bb6df10513fb742d44"
                      variavel: "6037d8bb6df10513fb742d46"
      responses:
        "200":
          description: Resultado da vinculação das combinações.
          content:
            application/json:
              schema:
                type: object
                properties:
                  alteradas:
                    type: array
                    items:
                      type: object
                  erros:
                    type: array
                    items:
                      type: object
              example:
                alteradas:
                  - codigo: "SKU_API_NOME"
                    preco: 0
                    ean: "7891234567890"
                    combinacao:
                      Tamanho: "P"
                      Cor: "Azul"
                    id:
                      $oid: "6571b932e3dd80645758f442"
                erros:
                  - codigo: "SKU_API_ID"
                    preco: 10
                    combinacao:
                      - variacao: "6037d8bb6df10513fb742d40"
                        variavel: "655e3fe59a41cd020c30ff19"
                      - variacao: "6037d8bb6df10513fb742d44"
                        variavel: "6037d8bb6df10513fb742d46"
                    erros:
                      - "Variável Tamanho/PP não está vinculada ao produto"
        "400": { $ref: "#/components/responses/BadRequest" }
        "401": { $ref: "#/components/responses/Unauthorized" }
    get:
      operationId: list_product_combinations
      tags: [Produto Combinações]
      summary: Listar combinações do produto
      description: |
        Método utilizado para listar todas as combinações que estão vinculadas
        ao produto. Retorna um array de objetos com as combinações. Podem
        ser utilizados os campos `id` e `codigo` para filtrar (opcional).
      parameters:
        - name: id
          in: query
          required: false
          description: ID da combinação para filtrar.
          schema: { type: string }
        - name: codigo
          in: query
          required: false
          description: Código (SKU) da combinação para filtrar.
          schema: { type: string }
          example: "SKU_API_NOME"
      responses:
        "200":
          description: Lista de combinações do produto.
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
              example:
                - id:
                    $oid: "6570ce46f9fdf13b7f6713d7"
                  combinacao:
                    Tamanho: "P"
                  codigo: "SKU_API_NOME"
                  preco: 10
                  ean: "7891234567890"
        "401": { $ref: "#/components/responses/Unauthorized" }

  /produtoCombinacoes/{produtoId}/{combinacaoId_Codigo}:
    parameters:
      - $ref: "#/components/parameters/ProdutoIdPath"
      - $ref: "#/components/parameters/CombinacaoIdOuCodigoPath"
    patch:
      operationId: update_product_combination
      x-mcp-open-world: true
      tags: [Produto Combinações]
      summary: Alterar combinação
      description: |
        Permite alterar código (SKU), preço e/ou EAN (código de barras) de
        uma combinação específica. Para localizar a combinação a ser
        alterada, pode ser usado o `id` ou o `codigo` (SKU).
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CombinacaoAlteracaoInput"
            example:
              codigo: "SKU_API_ID"
              preco: 50
              ean: "7891234567890"
      responses:
        "200":
          description: Resultado da alteração.
          content:
            application/json:
              schema:
                type: object
                properties:
                  sucesso:
                    type: array
                    items:
                      type: object
                  erros:
                    type: array
                    items:
                      type: object
              example:
                sucesso:
                  - id:
                      $oid: "6570ce8c532eea32de0808b2"
                    codigo: "SKU_API_ID"
                    preco: 50
                    ean: "7891234567890"
                erros: []
        "400": { $ref: "#/components/responses/BadRequest" }
        "401": { $ref: "#/components/responses/Unauthorized" }

  # ============================================================== USUÁRIO
  /usuario:
    get:
      operationId: get_current_user
      tags: [Usuário]
      summary: Obter informações do usuário autenticado
      description: |
        Retorna as informações detalhadas do usuário autenticado. Os dados
        retornados incluem o nome do usuário, o nome da empresa, o CPF/CNPJ,
        o e-mail, o número de celular e o endereço completo (com CEP,
        logradouro, número, complemento, bairro, cidade e estado). Além
        disso, são listados os subdomínios associados ao usuário.
      responses:
        "200":
          description: Dados do usuário autenticado.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Usuario"
              example:
                nome_usuario: "Nome do usuário"
                nome_empresa: "Nome da empresa"
                cpfCnpj: "999.999.999-99"
                email: "emailusuario@vendizap.com"
                celular: "+55 11 99999 9999"
                endereco:
                  cep: "80000-100"
                  logradouro: "Logradouro usuário"
                  numero: "100"
                  complemento: "Loja 42"
                  bairro: "Bairro"
                  cidade: "Cidade"
                  estado: "ES"
                subdominios:
                  - "subdominiodaloja"
                  - "lojasubdominio"
        "401": { $ref: "#/components/responses/Unauthorized" }

  # ============================================================== DESCONTOS PROGRESSIVOS
  /descontosProgressivos:
    post:
      operationId: create_progressive_discount
      x-mcp-open-world: true
      tags: [Descontos Progressivos]
      summary: Cadastrar desconto progressivo
      description: |
        Cria um novo preço de atacado. O ID do registro criado é retornado
        com HTTP 201.

        ### Regras

        - Ao menos uma das faixas (`faixaQuantidade` ou `faixaPreco`) deve estar ativa.
        - Quando `tipo="produto"`, `tipoFiltro` é obrigatório.
        - Quando `tipoFiltro="produtos"`, `produtos` é uma lista de referências por `id` ou `codigo`.
        - Quando `tipoFiltro="categorias"`, `categorias` aceita IDs ou códigos de categorias raiz.
        - Apenas **um** registro do tipo `pedido` ativo é permitido por lojista.
        - Em cada lista de faixas, `aPartirDe` e `percentualDesconto` devem ser maiores que zero (percentual no máximo 99) e **estritamente crescentes** entre as faixas.
        - `nome` aceita no máximo 50 caracteres.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/DescontoProgressivoCreate"
            examples:
              produtoPorProdutos:
                summary: Tipo produto, filtro por produtos (id e código), faixa por quantidade
                value:
                  nome: "Quanto mais, mais barato"
                  tipo: "produto"
                  tipoFiltro: "produtos"
                  produtos:
                    - codigo: "SKU-001"
                    - id: "6682f7b065be87123fd4d157"
                  faixaQuantidade: true
                  faixaQuantidadeLista:
                    - aPartirDe: 2
                      percentualDesconto: 10
                    - aPartirDe: 5
                      percentualDesconto: 20
                  ativa: true
              produtoPorCategorias:
                summary: Tipo produto, filtro por categorias raiz (por id e por código), faixa por preço
                value:
                  nome: "Promoção de categorias"
                  tipo: "produto"
                  tipoFiltro: "categorias"
                  categorias:
                    - "601d957bb6fa7c11ba209426"
                    - "CAT-RAIZ-01"
                  faixaPreco: true
                  faixaPrecoLista:
                    - aPartirDe: 100
                      percentualDesconto: 5
                  ativa: true
              pedido:
                summary: Tipo pedido (desconto no total do pedido; só uma ativa por lojista)
                value:
                  nome: "Desconto no pedido"
                  tipo: "pedido"
                  faixaPreco: true
                  faixaPrecoLista:
                    - aPartirDe: 200
                      percentualDesconto: 10
                  ativa: true
      responses:
        "201":
          description: Preço de atacado criado com sucesso.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/IdResponse"
              example:
                id: "6a07661f4ef4d311179c988a"
        "400": { $ref: "#/components/responses/BadRequest" }
        "401": { $ref: "#/components/responses/Unauthorized" }
    get:
      operationId: list_progressive_discounts
      tags: [Descontos Progressivos]
      summary: Listar descontos progressivos
      description: |
        Retorna todos os preços de atacado do lojista autenticado.
        Sem parâmetros de filtro.

        ### Retorno

        Array de objetos no formato `DescontoProgressivo`.
      responses:
        "200":
          description: Lista de preços de atacado.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/DescontoProgressivo"
        "401": { $ref: "#/components/responses/Unauthorized" }

  /descontosProgressivos/{descontoProgressivoId}:
    parameters:
      - $ref: "#/components/parameters/DescontoProgressivoIdPath"
    get:
      operationId: get_progressive_discount
      tags: [Descontos Progressivos]
      summary: Buscar desconto progressivo
      description: Retorna um preço de atacado específico pelo ID.
      responses:
        "200":
          description: Preço de atacado encontrado.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DescontoProgressivo"
              example:
                id: "6a07661f4ef4d311179c988a"
                usuarioId: "69ea50e655f4c796230657e5"
                nome: "Quanto mais, mais barato"
                tipo: "produto"
                ativa: true
                tipoFiltro: "produtos"
                produtos:
                  - id: "6682f7b065be87123fd4d157"
                    descricao: "Produto exemplo"
                faixaQuantidade: true
                faixaQuantidadeLista:
                  - aPartirDe: 2
                    percentualDesconto: 10
                faixaPreco: false
                faixaPrecoLista: []
                permiteCupom: true
        "400": { $ref: "#/components/responses/BadRequest" }
        "401": { $ref: "#/components/responses/Unauthorized" }
    put:
      operationId: update_progressive_discount
      x-mcp-open-world: true
      tags: [Descontos Progressivos]
      summary: Substituir desconto progressivo (replace)
      description: |
        Substitui os campos editáveis do desconto. Os campos do schema que não
        forem enviados voltam aos defaults (`[]` ou `false`). Campos legados
        não documentados aqui são preservados. Para alterações parciais, use PATCH.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/DescontoProgressivoUpdate"
            example:
              nome: "Quanto mais, mais barato (atualizado)"
              tipo: "produto"
              tipoFiltro: "todosProdutos"
              faixaQuantidade: true
              faixaQuantidadeLista:
                - aPartirDe: 3
                  percentualDesconto: 15
              ativa: true
      responses:
        "200":
          description: Preço de atacado substituído com sucesso.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/IdResponse"
              example:
                id: "6a07661f4ef4d311179c988a"
        "400": { $ref: "#/components/responses/BadRequest" }
        "401": { $ref: "#/components/responses/Unauthorized" }
    patch:
      operationId: update_progressive_discount_partial
      x-mcp-open-world: true
      tags: [Descontos Progressivos]
      summary: Atualizar parcialmente desconto progressivo (merge)
      description: |
        Atualiza apenas os campos enviados; os demais permanecem como estavam.
        O payload mesclado é re-validado pelas regras gerais.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/DescontoProgressivoPatch"
            examples:
              soNome:
                summary: Alterar apenas o nome (demais campos preservados)
                value:
                  nome: "Novo nome via PATCH"
              faixasParciais:
                summary: Trocar apenas as faixas de quantidade (merge; demais campos preservados)
                value:
                  faixaQuantidade: true
                  faixaQuantidadeLista:
                    - aPartirDe: 3
                      percentualDesconto: 12
                    - aPartirDe: 6
                      percentualDesconto: 25
      responses:
        "200":
          description: Preço de atacado atualizado.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/IdResponse"
              example:
                id: "6a07661f4ef4d311179c988a"
        "400": { $ref: "#/components/responses/BadRequest" }
        "401": { $ref: "#/components/responses/Unauthorized" }
    delete:
      operationId: delete_progressive_discount
      x-mcp-open-world: true
      tags: [Descontos Progressivos]
      summary: Excluir desconto progressivo
      description: |
        Remove o preço de atacado e o desvincula automaticamente de todos
        os produtos a que estava associado.
      responses:
        "200":
          description: Preço de atacado removido.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DescontoProgressivoOkResponse"
              example:
                ok: true
                id: "6a07661f4ef4d311179c988a"
        "400": { $ref: "#/components/responses/BadRequest" }
        "401": { $ref: "#/components/responses/Unauthorized" }
