openapi: 3.1.0
info:
  title: API da Loja
  description: Identidade visual da página pública da loja e avaliações.
  version: 1.0.0
  contact:
    name: UniSupri
servers:
  - url: https://api.sandbox.samdevel.com.br
    description: Sandbox (ambiente de homologação)
tags:
  - name: Página da Loja
    description: |-
      Gerencie a identidade visual e informações da página pública da loja.
      
      **Recursos visuais:**
      - **Logo**: imagem de destaque (JPG, PNG, WebP, máx. 5MB)
      - **Background**: imagem de fundo da página
      
      Logo e background são enviados direto nos endpoints da própria página — você não precisa passar pelo fluxo de upload da API de Media nem colar um `id` aqui; mande o arquivo de uma vez.
  - name: Avaliação
    description: |-
      Acompanhe a nota da loja e o histórico de avaliações dos compradores.
      
      A nota é calculada automaticamente com base nas avaliações recebidas nos pedidos entregues.
paths:
  "/api/stores/page":
    get:
      tags:
        - Página da Loja
      summary: Ver Página da Loja
      description: Retorna todos os dados da página da loja, incluindo identidade visual.
      responses:
        "200":
          description: Dados da página
          content:
            "application/json":
              example:
                success: true
                message_code: SUCCESS
                data:
                  store_id: 01K8PB0KMM36AY2P0NKSZBP2NA
                  store_name: Minha Loja Premium
                  store_code: MINHALOJA
                  store_status: active
                  store_url: minha-loja-premium
                  store_type: default
                  commission_table_id: null
                  max_locations: 5
                  shares_stock_locations: false
                  shares_logistics: false
                  shares_products: false
                  features: []
                  company:
                    company_id: 01K8PB0KMM36AY2P0NKSZBP2NB
                    name: Empresa Comércio Ltda
                    social_name: Empresa de Comércio Eletrônico LTDA
                    document:
                      name: CNPJ
                      type: cnpj
                      number: 12.345.678/0001-90
                      description: Cadastro Nacional da Pessoa Jurídica
                    state_registration:
                      name: IE
                      type: ie
                      number: 123.456.789.012
                      description: Inscrição Estadual
                    tax_regime: simples
                    has_primary_store: true
                    primary_store_name: Minha Loja Premium
                    allow_partner_branches: false
                  attributes:
                    description: Loja dedicada a produtos de qualidade
                    foundation_date: "2015-05-20T00:00:00-03:00"
                    short_description: Produtos premium para o atacado
                    full_description: Descrição completa da loja...
                    logo_image: https://cdn.example.com/logo.png
                    background_image: https://cdn.example.com/bg.jpg
        "401":
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "$ref": "#/components/responses/Forbidden"
      security:
        - bearer: []
    put:
      tags:
        - Página da Loja
      summary: Atualizar Dados da Página
      description: Atualiza textos descritivos da página da loja.
      requestBody:
        required: true
        content:
          "application/json":
            schema:
              type: object
              properties:
                description:
                  type: string
                  maxLength: 500
                  nullable: true
                foundation_date:
                  type: string
                  format: date
                  nullable: true
                short_description:
                  type: string
                  maxLength: 255
                  nullable: true
                full_description:
                  type: string
                  nullable: true
            example:
              description: Loja referência em atacado de tecnologia
              short_description: Tecnologia no atacado
              foundation_date: "2015-05-20"
      responses:
        "200":
          description: Página atualizada com sucesso
          content:
            "application/json":
              example:
                success: true
                message_code: RESOURCE_UPDATED
                data:
                  store_id: 01K8PB0KMM36AY2P0NKSZBP2NA
                  store_name: Minha Loja Premium
                  store_code: MINHALOJA
                  store_status: active
                  store_url: minha-loja-premium
                  store_type: default
                  commission_table_id: null
                  max_locations: 5
                  shares_stock_locations: false
                  shares_logistics: false
                  shares_products: false
                  features: []
                  company:
                    company_id: 01K8PB0KMM36AY2P0NKSZBP2NB
                    name: Empresa Comércio Ltda
                    social_name: Empresa de Comércio Eletrônico LTDA
                    document:
                      name: CNPJ
                      type: cnpj
                      number: 12.345.678/0001-90
                      description: Cadastro Nacional da Pessoa Jurídica
                    state_registration:
                      name: IE
                      type: ie
                      number: 123.456.789.012
                      description: Inscrição Estadual
                    tax_regime: simples
                    has_primary_store: true
                    primary_store_name: Minha Loja Premium
                    allow_partner_branches: false
                  attributes:
                    description: Loja referência em atacado de tecnologia
                    foundation_date: "2015-05-20T00:00:00-03:00"
                    short_description: Tecnologia no atacado
                    full_description: Descrição completa da loja...
                    logo_image: https://cdn.example.com/logo.png
                    background_image: https://cdn.example.com/bg.jpg
        "401":
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "$ref": "#/components/responses/Forbidden"
        "422":
          "$ref": "#/components/responses/ValidationError"
      security:
        - bearer: []
  "/api/stores/page/logo":
    post:
      tags:
        - Página da Loja
      summary: Upload de Logo
      description: "Envia a imagem de logo da loja. Formatos: JPG, PNG, WEBP, GIF. Máximo: 5MB."
      requestBody:
        required: true
        content:
          "multipart/form-data":
            schema:
              type: object
              required:
                - image
              properties:
                image:
                  type: string
                  format: binary
                  description: "Arquivo de imagem (max 5MB, formatos: jpeg, png, jpg, gif, webp)"
      responses:
        "201":
          description: Logo enviado com sucesso
          content:
            "application/json":
              example:
                success: true
                message_code: RESOURCE_CREATED
                data:
                  store_id: 01K8PB0KMM36AY2P0NKSZBP2NA
                  store_name: Minha Loja Premium
                  store_code: MINHALOJA
                  store_status: active
                  store_url: minha-loja-premium
                  store_type: default
                  commission_table_id: null
                  max_locations: 5
                  shares_stock_locations: false
                  shares_logistics: false
                  shares_products: false
                  features: []
                  company:
                    company_id: 01K8PB0KMM36AY2P0NKSZBP2NB
                    name: Empresa Comércio Ltda
                    social_name: Empresa de Comércio Eletrônico LTDA
                    document:
                      name: CNPJ
                      type: cnpj
                      number: 12.345.678/0001-90
                      description: Cadastro Nacional da Pessoa Jurídica
                    state_registration:
                      name: IE
                      type: ie
                      number: 123.456.789.012
                      description: Inscrição Estadual
                    tax_regime: simples
                    has_primary_store: true
                    primary_store_name: Minha Loja Premium
                    allow_partner_branches: false
                  attributes:
                    description: Loja dedicada a produtos de qualidade
                    foundation_date: "2015-05-20T00:00:00-03:00"
                    short_description: Produtos premium para o atacado
                    full_description: Descrição completa da loja...
                    logo_image: https://cdn.example.com/logo.webp
                    background_image: https://cdn.example.com/bg.jpg
        "401":
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "$ref": "#/components/responses/Forbidden"
        "422":
          "$ref": "#/components/responses/ValidationError"
      security:
        - bearer: []
    delete:
      tags:
        - Página da Loja
      summary: Remover Logo
      description: Remove a imagem de logo da loja.
      responses:
        "200":
          description: Logo removido
          content:
            "application/json":
              example:
                success: true
                message_code: SUCCESS
                data:
                  store_id: 01K8PB0KMM36AY2P0NKSZBP2NA
                  store_name: Minha Loja Premium
                  store_code: MINHALOJA
                  store_status: active
                  store_url: minha-loja-premium
                  store_type: default
                  commission_table_id: null
                  max_locations: 5
                  shares_stock_locations: false
                  shares_logistics: false
                  shares_products: false
                  features: []
                  company:
                    company_id: 01K8PB0KMM36AY2P0NKSZBP2NB
                    name: Empresa Comércio Ltda
                    social_name: Empresa de Comércio Eletrônico LTDA
                    document:
                      name: CNPJ
                      type: cnpj
                      number: 12.345.678/0001-90
                      description: Cadastro Nacional da Pessoa Jurídica
                    state_registration:
                      name: IE
                      type: ie
                      number: 123.456.789.012
                      description: Inscrição Estadual
                    tax_regime: simples
                    has_primary_store: true
                    primary_store_name: Minha Loja Premium
                    allow_partner_branches: false
                  attributes:
                    description: Loja dedicada a produtos de qualidade
                    foundation_date: "2015-05-20T00:00:00-03:00"
                    short_description: Produtos premium para o atacado
                    full_description: Descrição completa da loja...
                    logo_image: null
                    background_image: https://cdn.example.com/bg.jpg
        "401":
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "$ref": "#/components/responses/Forbidden"
      security:
        - bearer: []
  "/api/stores/page/background":
    post:
      tags:
        - Página da Loja
      summary: Upload de Background
      description: Envia a imagem de fundo da página da loja.
      requestBody:
        required: true
        content:
          "multipart/form-data":
            schema:
              type: object
              required:
                - image
              properties:
                image:
                  type: string
                  format: binary
                  description: "Arquivo de imagem (max 5MB, formatos: jpeg, png, jpg, gif, webp)"
      responses:
        "201":
          description: Background enviado com sucesso
          content:
            "application/json":
              example:
                success: true
                message_code: RESOURCE_CREATED
                data:
                  store_id: 01K8PB0KMM36AY2P0NKSZBP2NA
                  store_name: Minha Loja Premium
                  store_code: MINHALOJA
                  store_status: active
                  store_url: minha-loja-premium
                  store_type: default
                  commission_table_id: null
                  max_locations: 5
                  shares_stock_locations: false
                  shares_logistics: false
                  shares_products: false
                  features: []
                  company:
                    company_id: 01K8PB0KMM36AY2P0NKSZBP2NB
                    name: Empresa Comércio Ltda
                    social_name: Empresa de Comércio Eletrônico LTDA
                    document:
                      name: CNPJ
                      type: cnpj
                      number: 12.345.678/0001-90
                      description: Cadastro Nacional da Pessoa Jurídica
                    state_registration:
                      name: IE
                      type: ie
                      number: 123.456.789.012
                      description: Inscrição Estadual
                    tax_regime: simples
                    has_primary_store: true
                    primary_store_name: Minha Loja Premium
                    allow_partner_branches: false
                  attributes:
                    description: Loja dedicada a produtos de qualidade
                    foundation_date: "2015-05-20T00:00:00-03:00"
                    short_description: Produtos premium para o atacado
                    full_description: Descrição completa da loja...
                    logo_image: https://cdn.example.com/logo.png
                    background_image: https://cdn.example.com/bg.webp
        "401":
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "$ref": "#/components/responses/Forbidden"
        "422":
          "$ref": "#/components/responses/ValidationError"
      security:
        - bearer: []
    delete:
      tags:
        - Página da Loja
      summary: Remover Background
      description: Remove a imagem de fundo da loja.
      responses:
        "200":
          description: Background removido
          content:
            "application/json":
              example:
                success: true
                message_code: SUCCESS
                data:
                  store_id: 01K8PB0KMM36AY2P0NKSZBP2NA
                  store_name: Minha Loja Premium
                  store_code: MINHALOJA
                  store_status: active
                  store_url: minha-loja-premium
                  store_type: default
                  commission_table_id: null
                  max_locations: 5
                  shares_stock_locations: false
                  shares_logistics: false
                  shares_products: false
                  features: []
                  company:
                    company_id: 01K8PB0KMM36AY2P0NKSZBP2NB
                    name: Empresa Comércio Ltda
                    social_name: Empresa de Comércio Eletrônico LTDA
                    document:
                      name: CNPJ
                      type: cnpj
                      number: 12.345.678/0001-90
                      description: Cadastro Nacional da Pessoa Jurídica
                    state_registration:
                      name: IE
                      type: ie
                      number: 123.456.789.012
                      description: Inscrição Estadual
                    tax_regime: simples
                    has_primary_store: true
                    primary_store_name: Minha Loja Premium
                    allow_partner_branches: false
                  attributes:
                    description: Loja dedicada a produtos de qualidade
                    foundation_date: "2015-05-20T00:00:00-03:00"
                    short_description: Produtos premium para o atacado
                    full_description: Descrição completa da loja...
                    logo_image: https://cdn.example.com/logo.png
                    background_image: null
        "401":
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "$ref": "#/components/responses/Forbidden"
      security:
        - bearer: []
  "/api/stores/rating":
    get:
      tags:
        - Avaliação
      summary: Resumo de Avaliação
      description: Retorna a nota atual da loja em cada critério e a nota geral (0-10).
      responses:
        "200":
          description: Resumo da avaliação
          content:
            "application/json":
              example:
                success: true
                message_code: SUCCESS
                data:
                  store:
                    store_id: 01K8PB0KMM36AY2P0NKSZBP2NA
                    store_name: Minha Loja Premium
                    store_code: MINHALOJA
                    store_status: active
                    store_url: minha-loja-premium
                    store_type: default
                    commission_table_id: null
                    max_locations: 5
                    features: []
                    company:
                      company_id: 01K8PB0KMM36AY2P0NKSZBP2NB
                      name: Empresa Comércio Ltda
                      social_name: Empresa de Comércio Eletrônico LTDA
                      document:
                        name: CNPJ
                        type: cnpj
                        number: 12.345.678/0001-90
                        description: Cadastro Nacional da Pessoa Jurídica
                      state_registration: null
                      tax_regime: simples
                      has_primary_store: true
                      primary_store_name: Minha Loja Premium
                      allow_partner_branches: false
                    shares_products: false
                    shares_stock_locations: false
                    shares_logistics: false
                    is_primary: true
                    primary_store: null
                  rating:
                    subjects:
                      shipping: 8.5
                      support: 9.2
                      selling: 7.8
                      shipping_time: 8
                      cancel_counts: 9.5
                    overall: 8.6
                    period_start: "2026-01-13T00:00:00.000000Z"
                    period_end: "2026-04-13T23:59:59.000000Z"
        "401":
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "$ref": "#/components/responses/Forbidden"
      security:
        - bearer: []
  "/api/stores/rating/history":
    get:
      tags:
        - Avaliação
      summary: Histórico de Avaliação
      description: Retorna o histórico paginado de variações na nota da loja.
      parameters:
        - name: per_page
          in: query
          description: Quantidade de itens por página.
          schema:
            type: integer
            default: 20
        - name: filter[subject]
          in: query
          description: Filtrar por critério (`shipping`, `support`, `selling`, `shipping_time`, `cancel_counts`).
          schema:
            type: string
            enum:
              - shipping
              - support
              - selling
              - shipping_time
              - cancel_counts
        - name: filter[direction]
          in: query
          description: Filtrar por direção da variação (`up`, `down`).
          schema:
            type: string
            enum:
              - up
              - down
        - name: filter[date_between]
          in: query
          description: "Intervalo de datas no formato `from,to` (ex.: `2026-01-01,2026-03-31`). Alternativa aos parâmetros `from`/`to`."
          schema:
            type: string
        - name: from
          in: query
          description: Data inicial (compara contra `occurred_at`).
          schema:
            type: string
            format: date
        - name: to
          in: query
          description: Data final (compara contra `occurred_at`).
          schema:
            type: string
            format: date
        - name: sort
          in: query
          description: "Campo de ordenação. Prefixe com `-` para descendente. Valores permitidos: `occurred_at`, `subject`, `direction`, `value`. Padrão: `-occurred_at`."
          schema:
            type: string
            example: "-occurred_at"
      responses:
        "200":
          description: Histórico paginado
          content:
            "application/json":
              example:
                success: true
                message_code: SUCCESS
                data:
                  meta:
                    search_query: ""
                    filters: []
                    pagination:
                      page: 1
                      per_page: 20
                      last_page: 8
                      has_prev_page: false
                      has_next_page: true
                      records:
                        from: 1
                        to: 20
                        records: 150
                  data:
                    - subject: shipping
                      direction: up
                      value: 1.5
                      meta: {}
                      occurred_at: "2026-04-10T14:30:00.000000Z"
                    - subject: support
                      direction: down
                      value: 0.8
                      meta: {}
                      occurred_at: "2026-04-09T10:15:00.000000Z"
        "401":
          "$ref": "#/components/responses/Unauthorized"
        "403":
          "$ref": "#/components/responses/Forbidden"
      security:
        - bearer: []
components:
  securitySchemes:
    integrationToken:
      type: http
      scheme: bearer
      description: "Token de Integração da loja (formato: sk_...). Criado em Configurações → Tokens de Integração no painel do seller."
  schemas:
    Product:
      type: object
      properties:
        id:
          type: string
          description: ID do produto (26 caracteres)
        name:
          type: string
        sku:
          type: string
        price_type:
          type: string
          enum:
            - default
            - wholesale
        base_unit:
          type: string
          enum:
            - un
            - kg
            - pc
            - cx
            - pct
            - lt
            - mt
            - m2
            - m3
        dimensions:
          type: object
          properties:
            width:
              type: number
              description: Largura em cm
            height:
              type: number
              description: Altura em cm
            length:
              type: number
              description: Comprimento em cm
            weight:
              type: number
              description: Peso em kg
        is_available_for_sale:
          type: boolean
          description: Indica se o produto está disponível para venda
          default: true
        is_industrializable:
          type: boolean
          description: Indica se o produto pode ser fabricado sob demanda
        auto_wholesale_pricing:
          type: boolean
          description: Indica se os preços das faixas de atacado são derivados automaticamente do percentual de desconto
        allow_sale_without_stock:
          type: boolean
          description: Permite venda sem estoque disponível (pedido sob encomenda)
        dimensions_formatted:
          type: object
          nullable: true
          description: Dimensões formatadas para exibição (somente se include_dimensions_formatted=true)
          properties:
            width:
              type: string
              nullable: true
              example: 10,00 cm
            height:
              type: string
              nullable: true
              example: 10,00 cm
            length:
              type: string
              nullable: true
              example: 10,00 cm
            weight:
              type: string
              nullable: true
              example: 500g
        quantity:
          type: number
          description: Quantidade total em estoque
        reserved_quantity:
          type: number
          description: Quantidade reservada
        available_quantity:
          type: number
          description: Quantidade disponível para venda (quantity - reserved_quantity)
        price:
          type: number
          description: Preço de venda (somente para price_type=default)
        min_price:
          type: number
          description: Menor preço entre as faixas (somente para price_type=wholesale)
        max_price:
          type: number
          description: Maior preço entre as faixas (somente para price_type=wholesale)
        thumbnail:
          type: object
          nullable: true
          description: Imagem de destaque do produto (variantes thumbnail e md)
          properties:
            id:
              type: string
              description: ID da imagem
            resources:
              type: array
              items:
                type: object
                properties:
                  name:
                    type: string
                    description: Nome da variante (thumbnail, sm, md, lg)
                  size:
                    type: string
                    description: "Dimensões da variante (ex: 400x400)"
                  url:
                    type: string
                    format: uri
    ProductInput:
      type: object
      required:
        - name
        - sku
        - base_unit
        - price_type
        - dimensions
      properties:
        name:
          type: string
          maxLength: 255
        sku:
          type: string
          maxLength: 50
          description: Deve ser único por loja
        base_unit:
          type: string
          enum:
            - un
            - kg
            - pc
            - cx
            - pct
            - lt
            - mt
            - m2
            - m3
        price_type:
          type: string
          enum:
            - default
            - wholesale
        is_available_for_sale:
          type: boolean
          default: true
        is_industrializable:
          type: boolean
          nullable: true
        allow_sale_without_stock:
          type: boolean
          nullable: true
          description: Permite venda sem estoque disponível (pedido sob encomenda)
        auto_wholesale_pricing:
          type: boolean
          description: Opcional. Deriva automaticamente os preços das faixas de atacado a partir do percentual de desconto
        dimensions:
          type: object
          required:
            - width
            - height
            - length
            - weight
          properties:
            width:
              type: number
              minimum: 0.001
              description: Largura em cm
            height:
              type: number
              minimum: 0.001
              description: Altura em cm
            length:
              type: number
              minimum: 0.001
              description: Comprimento em cm
            weight:
              type: number
              minimum: 0.001
              description: Peso em kg
    ProductUpdateInput:
      type: object
      description: Corpo da atualização de produto. Diferente da criação, o `sku` não é aceito (é ignorado se enviado) e apenas `name` e `dimensions` são obrigatórios.
      required:
        - name
        - dimensions
      properties:
        name:
          type: string
          maxLength: 255
        base_unit:
          type: string
          description: Opcional. Mantém o valor atual quando omitido
          enum:
            - un
            - kg
            - pc
            - cx
            - pct
            - lt
            - mt
            - m2
            - m3
        price_type:
          type: string
          description: Opcional. Veja as regras de troca na descrição do endpoint
          enum:
            - default
            - wholesale
        is_available_for_sale:
          type: boolean
          description: Opcional
        is_industrializable:
          type: boolean
          description: Opcional
        allow_sale_without_stock:
          type: boolean
          description: Opcional. Permite venda sem estoque disponível (pedido sob encomenda)
        auto_wholesale_pricing:
          type: boolean
          description: Opcional. Deriva automaticamente os preços das faixas de atacado a partir do percentual de desconto
        dimensions:
          type: object
          required:
            - width
            - height
            - length
            - weight
          properties:
            width:
              type: number
              minimum: 0.001
              description: Largura em cm
            height:
              type: number
              minimum: 0.001
              description: Altura em cm
            length:
              type: number
              minimum: 0.001
              description: Comprimento em cm
            weight:
              type: number
              minimum: 0.001
              description: Peso em kg
    Price:
      type: object
      properties:
        value:
          type: number
          description: Valor unitário da faixa
        min_quantity:
          type: integer
          description: Quantidade mínima para a faixa valer
        discount_percent:
          type: number
          nullable: true
          description: Percentual de desconto da faixa em relação ao preço-base (usado no atacado automático)
        package_weight:
          type: number
          nullable: true
          description: Peso da embalagem da faixa em kg
        package_height:
          type: number
          nullable: true
          description: Altura da embalagem da faixa em cm
        package_width:
          type: number
          nullable: true
          description: Largura da embalagem da faixa em cm
        package_length:
          type: number
          nullable: true
          description: Comprimento da embalagem da faixa em cm
    Stock:
      type: object
      properties:
        location_stock:
          type: object
          properties:
            location_id:
              type: string
              description: ID do local de estoque
            store_id:
              type: string
              description: ID da loja
            name:
              type: string
            status:
              type: string
              enum:
                - available
                - unavailable
            location_type:
              type: string
              enum:
                - seller_location
                - fulfillment
            allows_pickup:
              type: boolean
              description: Local permite retirada
            allows_production:
              type: boolean
              description: Local permite produção sob demanda
        quantity:
          type: number
        reserved_quantity:
          type: number
        available_quantity:
          type: number
    PaginationMeta:
      type: object
      properties:
        search_query:
          type: string
        filters:
          type: array
          items:
            type: string
        pagination:
          type: object
          properties:
            page:
              type: integer
            per_page:
              type: integer
            last_page:
              type: integer
            has_prev_page:
              type: boolean
            has_next_page:
              type: boolean
            records:
              type: object
              properties:
                from:
                  type: integer
                to:
                  type: integer
                records:
                  type: integer
    PriceInput:
      type: object
      properties:
        price:
          type: number
          nullable: true
          description: Valor monetário da faixa. Obrigatório na precificação manual (se omitido vira 0). Em produtos `wholesale` com `auto_wholesale_pricing` ligado é ignorado nas faixas `min_quantity >= 2` — o preço é calculado a partir do preço base e do `discount_percent`.
        min_quantity:
          type: integer
          default: 1
          description: "Quantidade mínima para ativar este preço (Padrão: 1). Produtos `default` só aceitam `min_quantity = 1`."
        discount_percent:
          type: number
          nullable: true
          minimum: 0
          description: Percentual de desconto sobre o preço base unitário (0 a menos de 100). Usado nas faixas de atacado automáticas; os descontos precisam ser progressivos (faixa de quantidade maior exige desconto maior).
          exclusiveMaximum: 100
        package_weight:
          type: number
          nullable: true
          minimum: 0.001
          description: Peso da embalagem fechada, em kg. Faz parte das medidas obrigatórias das faixas de atacado (`min_quantity >= 2`).
        package_height:
          type: number
          nullable: true
          minimum: 0.01
          description: Altura da embalagem fechada, em cm. Faz parte das medidas obrigatórias das faixas de atacado.
        package_width:
          type: number
          nullable: true
          minimum: 0.01
          description: Largura da embalagem fechada, em cm. Faz parte das medidas obrigatórias das faixas de atacado.
        package_length:
          type: number
          nullable: true
          minimum: 0.01
          description: Comprimento da embalagem fechada, em cm. Faz parte das medidas obrigatórias das faixas de atacado.
    ProductStockOverview:
      type: object
      properties:
        total:
          type: integer
          description: Quantidade total de estoque somando todas as localizações.
          example: 150
        stocks:
          type: array
          description: Lista detalhada de estoque do produto em cada localização.
          items:
            "$ref": "#/components/schemas/ProductStockDetail"
        locations:
          type: array
          description: Lista de todas as localizações disponíveis para a loja.
          items:
            "$ref": "#/components/schemas/LocationStock"
    ProductStock:
      type: object
      properties:
        id:
          type: integer
          description: Identificador interno do registro de estoque.
          example: 321
        product_id:
          type: string
          description: ID do produto.
          example: 01H81AV32307PVBSV4RXF15EK9
        location_id:
          type: string
          description: ID da localização de estoque.
          example: 01H81AV32307PVBSV4RXF15LOC
        quantity:
          type: integer
          description: Quantidade atual em estoque.
          example: 50
        reserved_quantity:
          type: integer
          description: Quantidade reservada (não disponível para venda imediata).
          example: 0
        available_quantity:
          type: integer
          description: Quantidade disponível para venda (quantity - reserved_quantity).
          example: 50
    ProductStockDetail:
      type: object
      description: Registro de estoque do produto em uma localização, com o produto e o local aninhados.
      properties:
        id:
          type: integer
          description: Identificador interno do registro de estoque.
          example: 321
        product_sku:
          type: object
          description: Dados do produto (id, name, sku, base_unit, dimensions, flags de venda, prices, totais de estoque, thumbnail e images).
        location_stock:
          "$ref": "#/components/schemas/LocationStock"
        quantity:
          type: integer
          description: Quantidade física nesta localização.
          example: 100
        reserved_quantity:
          type: integer
          description: Quantidade reservada em carrinhos/pedidos abertos.
          example: 5
        available_quantity:
          type: integer
          description: Quantidade disponível para venda (quantity - reserved_quantity).
          example: 95
    LocationStock:
      type: object
      properties:
        location_id:
          type: string
          description: ID da localização.
          example: 01H81AV32307PVBSV4RXF15LOC
        store_id:
          type: integer
          description: Identificador interno da loja dona do local.
          example: 42
        name:
          type: string
          description: Nome da localização.
          example: Matriz - São Paulo
        status:
          type: string
          enum:
            - available
            - unavailable
          description: Status da localização.
          example: available
        location_type:
          type: string
          enum:
            - seller_location
            - fulfillment
          description: Tipo da localização.
          example: seller_location
        allows_pickup:
          type: boolean
          description: Indica se o local permite retirada em mãos.
          example: false
        allows_production:
          type: boolean
          description: Indica se o local permite produção sob demanda.
          example: false
    StockUpdateInput:
      type: object
      required:
        - location_id
        - quantity
      properties:
        location_id:
          type: string
          description: ID da localização onde o estoque será alterado.
          example: 01H81AV32307PVBSV4RXF15LOC
        quantity:
          type: integer
          minimum: 1
          description: Quantidade a ser definida, incrementada ou decrementada.
          example: 10
        increment:
          type: boolean
          description: Se verdadeiro, soma a quantidade ao estoque atual.
          default: false
          example: false
        decrement:
          type: boolean
          description: Se verdadeiro, subtrai a quantidade do estoque atual.
          default: false
          example: false
    SuccessResponse:
      type: object
      properties:
        success:
          type: boolean
          example: true
        message_code:
          type: string
          example: SUCCESS
        data:
          type: object
        meta:
          type: object
          description: Presente apenas quando há metadados a retornar.
    ErrorResponse:
      type: object
      properties:
        success:
          type: boolean
          example: false
        code:
          type: integer
          example: 400
        message_code:
          type: string
          example: BAD_REQUEST
        description:
          type: string
          example: Erro na requisição.
        data:
          type: array
          items: {}
          example: []
        errors:
          type: object
          additionalProperties:
            type: array
            items:
              type: string
        meta:
          type: array
          items: {}
          example: []
    LocationStockInput:
      type: object
      required:
        - name
        - status
        - location_type
      properties:
        name:
          type: string
        status:
          type: string
          enum:
            - available
            - unavailable
          default: available
        location_type:
          type: string
          enum:
            - seller_location
          default: seller_location
        allows_pickup:
          type: boolean
          default: false
          description: Permite retirada no local
        allows_production:
          type: boolean
          default: false
          description: Permite producao sob demanda
        company_branch_uid:
          type: string
          nullable: true
          description: ID da filial a vincular ao local. Precisa ser uma filial ativa da empresa; omita para deixar o local respondendo pela matriz.
    Address:
      type: object
      properties:
        id:
          type: string
          description: ID do endereco
        uid:
          type: string
          description: Mesmo valor de id (mantido por compatibilidade)
        street:
          type: string
        number:
          type: string
        complement:
          type: string
          nullable: true
        reference:
          type: string
          nullable: true
          description: Ponto de referencia
        can_deliver_to_neighbor:
          type: boolean
          description: Se o entregador pode deixar com um vizinho
        delivery_instructions:
          type: string
          nullable: true
          description: Instrucoes de entrega
        district:
          type: string
        city:
          type: string
        state:
          type: string
        country:
          type: string
        zip_code:
          type: string
          description: CEP formatado (00000-000)
        latitude:
          type: number
        longitude:
          type: number
        place_id:
          type: string
          nullable: true
          description: Identificador do lugar no provedor de geocodificacao
        address_components:
          nullable: true
          description: Componentes estruturados do endereco retornados pelo provedor de geocodificacao
        full_address:
          type: string
          description: Endereco completo em uma unica linha
        is_complete:
          type: boolean
          description: Indica se o endereco ja possui coordenadas resolvidas
        type:
          type: string
          enum:
            - logistics
            - local_real
            - local_devolucao
          description: O tipo do endereco. Pelo menos um endereco do tipo 'logistics' e obrigatorio para o local de estoque operar.
        type_label:
          type: string
          nullable: true
          description: Rotulo legivel do tipo
    AddressInput:
      type: object
      required:
        - zip_code
        - street
        - number
        - district
        - city
        - state
        - type
      properties:
        zip_code:
          type: string
          description: CEP (apenas numeros ou com traco, formato 00000-000 ou 00000000)
        street:
          type: string
          minLength: 3
        number:
          type: string
          maxLength: 20
        complement:
          type: string
          nullable: true
          maxLength: 255
        reference:
          type: string
          nullable: true
          maxLength: 60
          description: Ponto de referencia
        can_deliver_to_neighbor:
          type: boolean
          nullable: true
          description: Se o entregador pode deixar com um vizinho
        delivery_instructions:
          type: string
          nullable: true
          maxLength: 150
          description: Instrucoes de entrega
        district:
          type: string
          minLength: 2
        city:
          type: string
          minLength: 2
        state:
          type: string
          minLength: 2
          maxLength: 2
        country:
          type: string
          minLength: 2
          maxLength: 2
          default: BR
        latitude:
          type: number
          nullable: true
          description: Se omitido, a plataforma tenta resolver as coordenadas pelo CEP ou por geocodificacao
        longitude:
          type: number
          nullable: true
        place_id:
          type: string
          nullable: true
        address_components:
          type: array
          nullable: true
          items: {}
        type:
          type: string
          enum:
            - logistics
            - local_real
            - local_devolucao
          description: "Tipo de endereco para este local. Valores validos: logistics, local_real, local_devolucao"
    AddressUpdateInput:
      type: object
      description: Mesmos campos do cadastro, porem todos opcionais — envie apenas o que quer alterar.
      properties:
        zip_code:
          type: string
          description: CEP (apenas numeros ou com traco, formato 00000-000 ou 00000000)
        street:
          type: string
          minLength: 3
        number:
          type: string
          maxLength: 20
        complement:
          type: string
          nullable: true
          maxLength: 255
        reference:
          type: string
          nullable: true
          maxLength: 60
        can_deliver_to_neighbor:
          type: boolean
          nullable: true
        delivery_instructions:
          type: string
          nullable: true
          maxLength: 150
        district:
          type: string
          minLength: 2
        city:
          type: string
          minLength: 2
        state:
          type: string
          minLength: 2
          maxLength: 2
        country:
          type: string
          minLength: 2
          maxLength: 2
        latitude:
          type: number
          nullable: true
        longitude:
          type: number
          nullable: true
        place_id:
          type: string
          nullable: true
        address_components:
          type: array
          nullable: true
          items: {}
        type:
          type: string
          nullable: true
          enum:
            - logistics
            - local_real
            - local_devolucao
          description: Novo tipo do vinculo do endereco com o local
    CategoriesResponse:
      type: object
      properties:
        success:
          type: boolean
        message_code:
          type: string
        data:
          type: array
          items:
            "$ref": "#/components/schemas/Category"
      required:
        - success
        - message_code
        - data
    Category:
      type: object
      properties:
        id:
          type: integer
          description: ID da categoria
        name:
          type: string
        description:
          type:
            - string
            - "null"
        departament:
          "$ref": "#/components/schemas/Department"
        parent:
          "$ref": "#/components/schemas/ParentCategory"
        is_visible:
          type: boolean
        priority:
          type: integer
        domain:
          type: string
        level:
          type: integer
        hierarchy:
          type: array
          description: Breadcrumb completo da categoria (cada nível com id e nome)
          items:
            "$ref": "#/components/schemas/HierarchyLevel"
        settings:
          type: array
          items: {}
        catalog_overrides:
          type:
            - object
            - "null"
        total_children:
          type: integer
        children:
          type: array
          description: Subcategorias (recursivo). Na busca, só voltam folhas — portanto vazio.
          items:
            "$ref": "#/components/schemas/Category"
      required:
        - id
        - name
        - departament
        - parent
    HierarchyLevel:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
      required:
        - id
        - name
    Department:
      type: object
      properties:
        id:
          type: integer
          description: ID do departamento
        name:
          type: string
        icon_svg:
          type:
            - string
            - "null"
      required:
        - id
        - name
    ParentCategory:
      type: object
      properties:
        id:
          type: integer
        parent_id:
          type:
            - integer
            - "null"
        name:
          type: string
        hierarchy:
          type: array
          items:
            "$ref": "#/components/schemas/HierarchyLevel"
      required:
        - id
        - parent_id
        - name
    CategoryAttributesResponse:
      type: object
      properties:
        success:
          type: boolean
        message_code:
          type: string
        data:
          type: array
          description: Com `matrix=true`, lista de grupos (`AttributeGroup`). Sem `matrix`, lista plana de atributos (`AttributeItem`).
          items:
            oneOf:
              - "$ref": "#/components/schemas/AttributeGroup"
              - "$ref": "#/components/schemas/AttributeItem"
      required:
        - success
        - message_code
        - data
    AttributeGroup:
      type: object
      properties:
        key:
          type:
            - string
            - "null"
          description: "Chave da matriz (ex: identification, appearance, technical). `null` para atributos sem matriz."
        label:
          type: string
        items:
          type: array
          items:
            "$ref": "#/components/schemas/AttributeItem"
      required:
        - key
        - label
        - items
    AttributeItem:
      type: object
      properties:
        id:
          type: integer
          description: ID do vínculo categoria-atributo
        attribute_id:
          type: integer
          description: ID do atributo
        category_id:
          type: integer
          description: ID da categoria
        is_required:
          type: boolean
          description: Indica se o atributo e obrigatorio para a categoria
        is_feature:
          type: boolean
          description: Indica se e uma caracteristica do produto
        is_variant:
          type: boolean
          description: Indica se e um atributo de variacao
        is_combinable:
          type: boolean
          description: Indica se pode ser usado em combinacoes para variacoes
        is_filter:
          type: boolean
          description: Indica se o atributo aparece como filtro na vitrine
        attribute_data:
          "$ref": "#/components/schemas/AttributeData"
      required:
        - id
        - attribute_id
        - category_id
        - is_required
        - is_feature
        - is_variant
        - is_combinable
        - is_filter
    AttributeData:
      type: object
      description: "Definição do atributo. O bloco `value_definition` é autodescritivo: traz os campos esperados (`fields`), as opções pré-cadastradas (`options`, quando houver) e as unidades disponíveis."
      properties:
        id:
          type: integer
          description: ID do atributo
        name:
          type: string
        type:
          type: string
          enum:
            - default
            - default_unit
            - default_list
            - dimension_3d
            - dimension_2d
            - color
            - image
            - brand
            - packaging
          description: Tipo estrutural do atributo. `default_unit` exige `unit`; `dimension_2d/3d` exigem width/height(/depth)+unit; `color` aceita opção pré-cadastrada ou cor customizada (value + hex).
        value_type:
          type:
            - string
            - "null"
          enum:
            - text
            - float
            - number
            - date
            - boolean
            - select
            - radio
            - checkbox
            - null
          description: Tipo do valor para atributos default. Tipos especializados (color, image, brand, packaging) ignoram este campo.
        is_feature:
          type: boolean
        is_variant:
          type: boolean
        is_calculable:
          type: boolean
          description: "Atributo usado em cálculos (ex: Quantidade, que precisa casar com a unidade base do SKU)"
        domain:
          type:
            - string
            - "null"
        ui:
          type: object
          properties:
            public_name:
              type:
                - string
                - "null"
            description:
              type:
                - string
                - "null"
            matrix:
              type:
                - string
                - "null"
              description: Matriz de organização (identification, appearance, technical, dimensions, ...)
            select_type:
              type: string
              enum:
                - select
                - radio
                - checkbox
                - text
              description: Como o valor é escolhido. `text` = digitação livre; os demais exigem opção pré-cadastrada (exceto atributos de cor, que aceitam cor customizada).
        value_definition:
          type: object
          properties:
            fields:
              type: object
              description: Schema dos campos esperados no valor (montagem dinâmica de formulário)
            options:
              type: array
              description: Opções pré-cadastradas (presente apenas quando o atributo tem opções)
              items:
                "$ref": "#/components/schemas/AttributeOption"
            default_unit:
              type:
                - string
                - "null"
            available_units:
              type: array
              items:
                type: string
    AttributeOption:
      type: object
      properties:
        id:
          type: integer
          description: ID da opção (use em `value_id` ao criar o anúncio)
        attribute_id:
          type: integer
        value:
          type: string
        component:
          type: object
          description: "Payload visual da opção, varia por tipo de atributo. Para cor: `{ value, main_color, hex, brightness }`."
          additionalProperties: true
        position:
          type: integer
        is_default:
          type: boolean
      required:
        - id
        - attribute_id
        - value
        - component
        - position
        - is_default
    AttributeCombinationsResponse:
      type: object
      properties:
        success:
          type: boolean
        message_code:
          type: string
        data:
          type: object
          properties:
            combinations:
              type: array
              items:
                "$ref": "#/components/schemas/AttributeCombination"
            primary_attribute:
              "$ref": "#/components/schemas/PrimaryAttributeInfo"
          required:
            - combinations
            - primary_attribute
      required:
        - success
        - message_code
        - data
    AttributeCombination:
      type: object
      properties:
        attributes:
          type: array
          items:
            "$ref": "#/components/schemas/CombinationAttribute"
        attributes_details:
          type: object
          additionalProperties:
            type: string
        description:
          type: string
      required:
        - attributes
        - attributes_details
        - description
    CombinationAttribute:
      type: object
      properties:
        attribute_id:
          type: integer
          description: ID do atributo
        attribute_name:
          type: string
        value:
          type: string
        unit:
          type: string
          description: Unidade de medida (presente apenas quando aplicável)
        hex:
          type: string
          description: Cor em hexadecimal (presente apenas para atributos de cor)
        main_color:
          type: string
          description: Cor principal (presente apenas para atributos de cor)
        brightness:
          type: string
          enum:
            - light
            - dark
          description: Luminosidade calculada da cor (presente apenas para atributos de cor)
        width:
          type:
            - string
            - number
          description: Largura (presente apenas para atributos de dimensão)
        height:
          type:
            - string
            - number
          description: Altura (presente apenas para atributos de dimensão)
      required:
        - attribute_id
        - attribute_name
        - value
    PrimaryAttributeInfo:
      type: object
      description: Atributo principal das combinações — facilita organizar fotos por variação no front.
      properties:
        id:
          type: integer
          description: ID do atributo principal
        name:
          type:
            - string
            - "null"
        has_options:
          type: boolean
        default_unit:
          type:
            - string
            - "null"
        values:
          type: array
          items:
            type: object
            properties:
              value:
                type: string
              label:
                type: string
              hex:
                type: string
              main_color:
                type: string
              brightness:
                type: string
            required:
              - value
              - label
      required:
        - id
        - name
        - has_options
        - default_unit
        - values
    CreateAdvertisementRequest:
      type: object
      description: É obrigatório informar `seller_sku` (anúncio sem variações) ou `variations` — um dos dois precisa estar presente. Os SKUs devem existir previamente na loja.
      properties:
        title:
          type: string
          maxLength: 100
          description: Titulo do anuncio
        category_id:
          type: integer
          description: ID da categoria selecionada (precisa ser categoria folha existente)
        gtin:
          "$ref": "#/components/schemas/GTIN"
        seller_sku:
          type:
            - string
            - "null"
          description: SKU do produto para anúncio sem variações. Obrigatório quando `variations` não for enviado. O SKU precisa existir na loja.
        attributes:
          type: array
          items:
            "$ref": "#/components/schemas/AdvertisementAttribute"
          description: Atributos de caracteristicas do produto. Obrigatório quando a categoria possui atributos com `is_required=true`.
        variations:
          type: array
          items:
            "$ref": "#/components/schemas/AdvertisementVariation"
          description: Variacoes do produto. Obrigatório quando `seller_sku` não for enviado.
        images:
          type: array
          items:
            "$ref": "#/components/schemas/ImageReference"
          description: Imagens do anuncio principal. Opcional na criação, mas o checklist exige pelo menos uma imagem para publicar.
        description:
          "$ref": "#/components/schemas/PublicationDescription"
          description: Descrição longa do anúncio. Opcional. Pode ser informada na criação ou depois via PUT /api/items/{id}/description.
        technical_sheets:
          type: array
          items:
            "$ref": "#/components/schemas/TechnicalSheetInput"
          description: Fichas técnicas do anúncio. Opcionais. Também podem ser criadas ou editadas depois via /api/items/{id}/technical-sheets.
      required:
        - title
        - category_id
    PublicationDescription:
      type: object
      description: Aceita um objeto `{ layout, raw_content }` ou uma string simples (legado, equivale a `layout=markdown`).
      properties:
        layout:
          type: string
          enum:
            - text
            - html
            - markdown
          description: "Formato do `raw_content`. Default: `markdown`."
        raw_content:
          type: string
          description: Conteúdo bruto da descrição no formato indicado por `layout`.
    TechnicalSheetInput:
      type: object
      required:
        - type
        - title
      properties:
        type:
          type: string
          enum:
            - technical_specification
            - characteristics
            - materials
            - installation
            - maintenance
            - safety
            - environmental
            - custom
          description: Tipo da ficha técnica.
        title:
          type: string
          maxLength: 255
          description: Título exibido para a seção da ficha.
        items:
          type: array
          items:
            type: object
            required:
              - item_key
              - item_value
            properties:
              item_key:
                type: string
                maxLength: 255
              item_value:
                type: string
                maxLength: 1000
              display_order:
                type: integer
                minimum: 0
    GTIN:
      type: object
      properties:
        type:
          type:
            - integer
            - string
          enum:
            - 8
            - 12
            - 13
            - 14
            - "8"
            - "12"
            - "13"
            - "14"
          description: "Tipo de GTIN: 8, 12, 13 ou 14 dígitos (13 para EAN-13). Nas respostas, vem como string."
        value:
          type: string
          description: Numero do codigo de barras
    AdvertisementAttribute:
      type: object
      description: "Valor de um atributo do anúncio. Campos extras dependem do tipo do atributo: cor customizada usa `hex`/`main_color`/`brightness`; dimensões usam `width`/`height`/`depth` + `unit`; listas usam `items`."
      properties:
        id:
          type: integer
          description: ID do atributo
        value_id:
          type:
            - integer
            - "null"
          description: ID da opção selecionada (para atributos com opcoes pré-cadastradas)
        option_id:
          type:
            - integer
            - "null"
          description: Alias aceito para `value_id`
        value:
          type:
            - string
            - integer
            - "null"
          description: Valor do atributo
        unit:
          type:
            - string
            - "null"
          description: Unidade de medida (obrigatória em atributos do tipo default_unit; precisa estar em available_units)
        hex:
          type:
            - string
            - "null"
          description: "Cor customizada em hexadecimal (#RGB ou #RRGGBB). Para atributos de cor, `value` (nome da cor) + `hex` válido dispensam opção pré-cadastrada."
        main_color:
          type:
            - string
            - "null"
          description: "Cor principal da cor customizada (ex: Vermelho)"
        brightness:
          type:
            - string
            - "null"
          description: Luminosidade da cor (light/dark). Se omitido, é calculada a partir do hex.
        width:
          type:
            - string
            - number
            - "null"
          description: Largura (atributos dimension_2d/dimension_3d)
        height:
          type:
            - string
            - number
            - "null"
          description: Altura (atributos dimension_2d/dimension_3d)
        depth:
          type:
            - string
            - number
            - "null"
          description: Profundidade (atributos dimension_3d)
        fields:
          type:
            - object
            - "null"
          description: "Forma alternativa de enviar dimensões: `{ width, height, depth, unit }`"
          properties:
            width: {}
            height: {}
            depth: {}
            unit:
              type: string
        items:
          type:
            - array
            - "null"
          description: Itens do atributo (obrigatório em atributos do tipo default_list)
    AdvertisementVariation:
      type: object
      properties:
        seller_sku:
          type: string
          description: SKU do produto para esta variacao (precisa existir na loja)
        attributes:
          type: array
          items:
            "$ref": "#/components/schemas/VariationAttribute"
          description: Atributos que definem esta variacao
        images:
          type: array
          items:
            "$ref": "#/components/schemas/ImageReference"
          description: Imagens especificas desta variacao
      required:
        - seller_sku
    VariationAttribute:
      type: object
      description: Informe `attribute_id` e `value` (ou `value_id` para opção pré-cadastrada). Atributos de cor aceitam cor customizada com `value` + `hex` (+ `main_color`/`brightness` opcionais), sem opção pré-cadastrada.
      properties:
        attribute_id:
          type: integer
          description: ID do atributo
        attribute_name:
          type:
            - string
            - "null"
        value:
          type:
            - string
            - integer
            - "null"
        unit:
          type:
            - string
            - "null"
        value_id:
          type:
            - integer
            - "null"
          description: ID da opção pré-cadastrada
        option_id:
          type:
            - integer
            - "null"
          description: Alias aceito para `value_id`
        hex:
          type:
            - string
            - "null"
          description: "Cor customizada em hexadecimal (#RGB ou #RRGGBB)"
        main_color:
          type:
            - string
            - "null"
        brightness:
          type:
            - string
            - "null"
        width:
          type:
            - string
            - number
            - "null"
        height:
          type:
            - string
            - number
            - "null"
        depth:
          type:
            - string
            - number
            - "null"
        fields:
          type:
            - object
            - "null"
          description: "Forma alternativa de enviar dimensões: `{ width, height, depth, unit }`"
    ImageReference:
      type: object
      properties:
        id:
          type: string
          description: ID da imagem (UUID retornado por POST /api/media/upload)
      required:
        - id
    SimulatedAdvertisementResponse:
      type: object
      properties:
        success:
          type: boolean
        message_code:
          type: string
        data:
          "$ref": "#/components/schemas/CreatedAdvertisementData"
      required:
        - success
        - message_code
        - data
    CreatedAdvertisementResponse:
      type: object
      properties:
        success:
          type: boolean
        message_code:
          type: string
        data:
          "$ref": "#/components/schemas/CreatedAdvertisementData"
      required:
        - success
        - message_code
        - data
    CreatedAdvertisementData:
      type: object
      description: Objeto do anúncio, retornado por create, publish e simulate.
      properties:
        item_id:
          type: string
          description: "ID do anúncio: prefixo da plataforma + 13 dígitos (ex: SAM-0000000000007)"
        title:
          type: string
        short_description:
          type:
            - string
            - "null"
        slug:
          type:
            - string
            - "null"
        type:
          allOf:
            - "$ref": "#/components/schemas/TypeValue"
          description: "Tipo do anúncio: `default` (Padrão) ou `catalog` (Catálogo)"
        status:
          allOf:
            - "$ref": "#/components/schemas/StatusValue"
          description: "Status do anúncio: `draft`, `pending_review`, `active`, `paused` ou `inactive`"
        seller_sku:
          type:
            - string
            - "null"
          description: SKU vinculado diretamente ao anúncio (quando não há variações)
        price_range:
          type:
            - array
            - "null"
          description: Faixa de preço calculada a partir das ofertas (pode ser null em rascunhos)
        score:
          type:
            - integer
            - "null"
          description: Score de qualidade do anúncio
        campaigns:
          type: array
        pricing_context:
          type: array
          description: Contexto de precificação por faixa de quantidade (descontos, campanhas)
        frontend_sync_status:
          type: string
          description: "Status de sincronização com a vitrine (ex: pending)"
        last_frontend_sync_at:
          type:
            - string
            - "null"
          description: Formato Y-m-d H:i:s
        submitted_for_review_at:
          type:
            - string
            - "null"
          description: Quando o anúncio foi enviado para revisão. Formato Y-m-d H:i:s
        reviewed_at:
          type:
            - string
            - "null"
          description: Quando a plataforma revisou o anúncio. Formato Y-m-d H:i:s
        rejection_reason:
          type:
            - string
            - "null"
          description: Motivo da rejeição quando o anúncio volta para rascunho
        gtin:
          allOf:
            - "$ref": "#/components/schemas/GTIN"
          description: Presente apenas quando informado
        store:
          allOf:
            - "$ref": "#/components/schemas/Store"
          description: Loja dona do anúncio (presente quando carregada)
        department:
          "$ref": "#/components/schemas/Department"
        category:
          "$ref": "#/components/schemas/CategoryRef"
        thumbnail:
          type:
            - object
            - "null"
          description: "Miniatura no tamanho `sm`: `{ id, resource }`"
        images:
          type: array
          items:
            "$ref": "#/components/schemas/Image"
        attributes:
          type: array
          items:
            "$ref": "#/components/schemas/PublicationAttributeOut"
        variations:
          type: array
          items:
            "$ref": "#/components/schemas/PublicationVariationOut"
      required:
        - item_id
        - title
        - type
        - status
        - department
        - category
        - images
        - attributes
        - variations
    Image:
      type: object
      properties:
        id:
          type: string
          description: ID da imagem (UUID)
        resources:
          type: array
          description: Variações de tamanho da imagem (`{ name, url, ... }`)
          items:
            type: object
      required:
        - id
        - resources
    PublicationAttributeOut:
      type: object
      properties:
        attribute_id:
          type: integer
          description: ID do atributo
        attribute_name:
          type:
            - string
            - "null"
        attribute_value:
          type:
            - string
            - integer
            - "null"
        value_unit:
          type:
            - string
            - "null"
        value_id:
          type:
            - integer
            - "null"
        component:
          type:
            - object
            - "null"
          description: "Payload visual do valor. Para cor: `{ value, main_color, hex, brightness }`."
      required:
        - attribute_id
        - attribute_name
        - attribute_value
        - value_unit
        - value_id
        - component
    PublicationVariationOut:
      type: object
      description: Variação do anúncio. Em anúncios padrão o identificador vem como `offer_id`; em anúncios de catálogo, como `option_id`.
      properties:
        offer_id:
          type: string
          description: ID da variação (26 caracteres). Presente em anúncios padrão.
        option_id:
          type: string
          description: ID da opção de catálogo (26 caracteres). Presente em anúncios de catálogo.
        description:
          type: string
          description: "Descrição legível da combinação (ex: Voltagem: 110 V, Cor: Azul)"
        attributes:
          type: array
          description: Atributos da variação (`{ attribute_id, attribute_name, value, unit?, value_id?, hex?, main_color?, brightness? }`)
          items:
            type: object
        status:
          type: string
          enum:
            - active
            - pending
            - hidden
          description: Status da variação
        type:
          type: string
          enum:
            - offer
            - option
        images:
          type: array
          items:
            "$ref": "#/components/schemas/Image"
        seller_sku:
          type:
            - string
            - "null"
          description: Presente quando `type=offer`
        offer:
          "$ref": "#/components/schemas/OfferData"
      required:
        - description
        - attributes
        - status
        - type
        - images
        - offer
    OfferData:
      type: object
      properties:
        price_type:
          type: string
          description: "Tipo de precificação (ex: default, wholesale)"
        price_from:
          type: number
          description: Preço "De" quando há desconto
        prices:
          type: array
          description: Faixas de preço (atacado)
          items:
            type: object
        quantity:
          type: integer
        price:
          type: number
          description: Preço "Por"
        original_price:
          type:
            - number
            - "null"
        has_discount:
          type: boolean
        discount_percent:
          type: integer
        wholesale_tiers:
          type: array
          description: Presente apenas quando há faixas de atacado
          items:
            type: object
        buybox:
          type: object
          description: Dados da buybox (presente apenas em anúncios de catálogo)
      required:
        - price_type
        - price_from
        - prices
        - quantity
        - price
        - original_price
        - has_discount
        - discount_percent
    TypeValue:
      type: object
      properties:
        value:
          type: string
          enum:
            - default
            - catalog
        label:
          type: string
      required:
        - value
        - label
    StatusValue:
      type: object
      properties:
        value:
          type: string
          enum:
            - draft
            - pending_review
            - active
            - paused
            - inactive
        label:
          type: string
      required:
        - value
        - label
    Store:
      type: object
      properties:
        store_id:
          type: string
          description: ID da loja (26 caracteres)
        store_name:
          type: string
        store_code:
          type: string
        store_status:
          type: string
        store_url:
          type:
            - string
            - "null"
        store_type:
          type: string
        commission_table_id:
          type:
            - integer
            - string
            - "null"
          description: ID da tabela de comissão
        max_locations:
          type:
            - integer
            - "null"
        features:
          type: array
        company:
          type: object
          description: Dados cadastrais da empresa
        shares_products:
          type: boolean
        shares_stock_locations:
          type: boolean
        shares_logistics:
          type: boolean
        is_primary:
          type: boolean
        primary_store:
          type:
            - object
            - "null"
      required:
        - store_id
        - store_name
        - store_code
    CategoryRef:
      type: object
      properties:
        id:
          type: integer
          description: ID da categoria
        parent_id:
          type:
            - integer
            - "null"
        name:
          type: string
        hierarchy:
          type: array
          items:
            "$ref": "#/components/schemas/HierarchyLevel"
      required:
        - id
        - parent_id
        - name
    AttachSKURequest:
      type: object
      properties:
        seller_sku:
          type: string
          maxLength: 64
          description: SKU do produto a vincular. Precisa pertencer (ou estar associado) à loja autenticada.
        status:
          type: string
          description: "Status inicial da oferta. Default: `active`."
          enum:
            - active
            - paused
            - inactive
      required:
        - seller_sku
    AttachedSKUResponse:
      type: object
      properties:
        success:
          type: boolean
        message_code:
          type: string
        data:
          "$ref": "#/components/schemas/AttachedSKUData"
      required:
        - success
        - message_code
        - data
    AttachedSKUData:
      type: object
      properties:
        offer_id:
          type: string
          description: ID da oferta criada (26 caracteres). Use em PUT/DELETE /api/items/catalog/offers/{offerId}.
        seller_sku:
          type: string
        status:
          type: string
          enum:
            - active
            - paused
            - inactive
            - pending
        is_buybox_winner:
          type: boolean
          description: Recalculado em background após o vínculo — costuma vir `false` na resposta imediata
        last_buybox_calculation:
          type:
            - string
            - "null"
        price_data:
          "$ref": "#/components/schemas/PriceData"
        stock_data:
          "$ref": "#/components/schemas/StockData"
        publication:
          type:
            - object
            - "null"
          description: Resumo do anúncio de catálogo
          properties:
            item_id:
              type: string
              description: ID do anúncio
            title:
              type: string
            status:
              type: string
            type:
              type: string
            thumbnail_id:
              type:
                - string
                - "null"
              description: ID da imagem de capa (UUID)
        option:
          "$ref": "#/components/schemas/OptionData"
      required:
        - offer_id
        - seller_sku
        - status
        - is_buybox_winner
        - last_buybox_calculation
        - price_data
        - stock_data
        - publication
        - option
    PriceData:
      type: object
      description: "Snapshot de preço da oferta. Preço único: `{ price }`. Atacado: `{ type: \"wholesale\", tiers: [...] }`."
      properties:
        price:
          type: number
          description: Preço único (presente quando não há faixas de atacado)
        type:
          type: string
          enum:
            - wholesale
          description: Presente apenas quando há faixas de atacado
        tiers:
          type: array
          description: Faixas de preço por quantidade (presente apenas no atacado)
          items:
            "$ref": "#/components/schemas/PriceTier"
    PriceTier:
      type: object
      properties:
        min_quantity:
          type: integer
        price:
          type: number
      required:
        - min_quantity
        - price
    StockData:
      type: object
      properties:
        id:
          type: integer
          description: ID interno do registro de estoque
        product_id:
          type: string
          description: ID do SKU do produto (26 caracteres)
        location_id:
          type: string
          description: ID do local de estoque (26 caracteres)
        quantity:
          type: integer
        reserved_quantity:
          type: integer
        available_quantity:
          type: integer
      required:
        - id
        - product_id
        - location_id
        - quantity
        - reserved_quantity
        - available_quantity
    OptionData:
      type: object
      properties:
        uid:
          type: string
          description: ID da opção de catálogo (26 caracteres)
        description:
          type: string
        attributes:
          type: array
          items:
            "$ref": "#/components/schemas/OptionAttribute"
        type:
          type: string
          enum:
            - option
            - offer
        status:
          type: string
          enum:
            - active
            - pending
            - hidden
        images:
          type: array
          items:
            type: object
      required:
        - uid
        - description
        - attributes
        - type
        - status
        - images
    OptionAttribute:
      type: object
      properties:
        attribute_id:
          type: integer
          description: ID do atributo
        attribute_name:
          type: string
        value:
          type: string
        unit:
          type:
            - string
            - "null"
        value_id:
          type:
            - integer
            - "null"
      required:
        - attribute_id
        - attribute_name
        - value
    TechnicalSheet:
      type: object
      description: "Ficha técnica de um anúncio: lista ordenada de pares chave/valor agrupada por tipo (especificações, materiais, segurança etc.)."
      properties:
        sheet_id:
          type: string
          description: ID da ficha técnica (26 caracteres)
        publication_id:
          type: string
          description: "`item_id` do anúncio dono da ficha"
        type:
          type: object
          description: Tipo da ficha técnica
          properties:
            value:
              type: string
              enum:
                - technical_specification
                - characteristics
                - materials
                - installation
                - maintenance
                - safety
                - environmental
                - custom
            label:
              type: string
              description: "Rótulo amigável do tipo (ex.: Ficha Técnica, Materiais)"
            description:
              type: string
          required:
            - value
            - label
            - description
        title:
          type: string
          maxLength: 255
        items:
          type: array
          items:
            "$ref": "#/components/schemas/TechnicalSheetItem"
      required:
        - sheet_id
        - publication_id
        - type
        - title
        - items
    TechnicalSheetItem:
      type: object
      description: Linha da ficha técnica (par chave/valor).
      properties:
        item_id:
          type: string
          description: ID do item da ficha (26 caracteres)
        item_key:
          type: string
          maxLength: 255
          description: "Nome da característica (ex.: Potência)"
        item_value:
          type: string
          maxLength: 1000
          description: "Valor da característica (ex.: 650 W)"
        display_order:
          type: integer
          minimum: 0
          description: Posição de exibição (0 = primeiro)
      required:
        - item_id
        - item_key
        - item_value
        - display_order
    MediaCreatedResponse:
      type: object
      properties:
        success:
          type: boolean
          example: true
        message_code:
          type: string
          example: RESOURCE_CREATED
        data:
          "$ref": "#/components/schemas/MediaItem"
      required:
        - success
        - message_code
        - data
    MediaItemResponse:
      type: object
      properties:
        success:
          type: boolean
          example: true
        message_code:
          type: string
          example: SUCCESS
        data:
          "$ref": "#/components/schemas/MediaItem"
      required:
        - success
        - message_code
        - data
    MediaCollectionResponse:
      type: object
      properties:
        success:
          type: boolean
          example: true
        message_code:
          type: string
          example: SUCCESS
        data:
          type: object
          properties:
            meta:
              "$ref": "#/components/schemas/PaginationMeta"
            data:
              type: array
              items:
                "$ref": "#/components/schemas/MediaItem"
      required:
        - success
        - message_code
        - data
    MediaItem:
      type: object
      description: Objeto que representa uma imagem/mídia na API de seller. Campos internos de propriedade (`owner_id`, `owner_model`) ficam de fora do payload de propósito — você não precisa deles para integrar, então não vai encontrá-los aqui.
      properties:
        id:
          type: string
          description: Identificador único da imagem (26 caracteres). É o valor usado como `{file_hash}` nas rotas de detalhe e exclusão.
          example: 01JMZXZ72881MD2P37N2K97YJJ
        original_source:
          type: string
          format: uri
          description: URL da imagem original, já convertida para WebP em alta qualidade.
          example: https://cdn.example.com/products/2026/05/28/original_01JMZXZ72881MD2P37N2K97YJJ.webp
        urls:
          type: array
          description: "Variações de tamanho geradas automaticamente (todas em WebP). Uma entrada por variação: `thumbnail` (135x135), `sm` (200x200), `md` (400x400), `lg` (800x800) e `xl` (1600x1600)."
          items:
            type: object
            properties:
              name:
                type: string
                enum:
                  - thumbnail
                  - sm
                  - md
                  - lg
                  - xl
                description: Nome da variação de tamanho.
                example: thumbnail
              size:
                type: string
                description: Dimensões máximas da variação, no formato largura x altura.
                example: 135x135
              url:
                type: string
                format: uri
                description: URL pública da variação.
                example: https://cdn.example.com/products/2026/05/28/thumbnail_01JMZXZ72881MD2P37N2K97YJJ.webp
            required:
              - name
              - size
              - url
        in_use:
          type: boolean
          description: Indica se a imagem está associada a algum recurso.
          example: false
        reference_id:
          type: string
          nullable: true
          description: ID do recurso referenciado (se houver).
        reference_model:
          type: string
          nullable: true
          enum:
            - product
            - publication
            - store
          description: Tipo do recurso vinculado, em formato curto. Use o mesmo valor no filtro `filter[reference_model]=...`.
        created_at:
          type: string
          format: date-time
          description: Data de criação da imagem.
          example: "2026-05-28T10:00:00-03:00"
        updated_at:
          type: string
          format: date-time
          description: Data da última atualização da imagem.
          example: "2026-05-28T10:00:00-03:00"
      required:
        - id
        - original_source
        - urls
        - in_use
        - reference_id
        - reference_model
        - created_at
        - updated_at
    MediaCloneFromSkusResponse:
      type: object
      properties:
        success:
          type: boolean
          example: true
        message_code:
          type: string
          example: OK
        data:
          type: object
          properties:
            results:
              type: object
              description: Mapa key → lista de mídias clonadas. As keys são exatamente as enviadas nos targets.
              additionalProperties:
                type: array
                items:
                  "$ref": "#/components/schemas/ClonedMediaItem"
            ignored_skus:
              type: array
              description: SKUs que não pertencem (ou não estão associados) à loja autenticada. Não geram erro — as keys correspondentes voltam vazias.
              items:
                type: string
              example:
                - CAMISETA-VERM-M
          required:
            - results
            - ignored_skus
      required:
        - success
        - data
    ClonedMediaItem:
      type: object
      description: Mídia recém-clonada a partir de uma foto de produto. Nasce sem vínculo (`in_use=false`) — vincule ao anúncio normalmente via `images[].id`; se não for usada, a limpeza diária remove a cópia após ~72 horas.
      properties:
        id:
          type: string
          description: ID da nova mídia (26 caracteres). Use este valor nas `images` do anúncio/variação.
          example: 01JNB2T4G93QRT5V6W7X8Y9Z0A
        source_image_id:
          type: string
          description: ID da imagem de origem (foto da galeria do produto). Útil para rastrear de onde a cópia veio e evitar duplicar sugestões.
          example: 01JMZXZ72881MD2P37N2K97YJJ
        original_source:
          type: string
          format: uri
          description: URL da cópia em alta qualidade (WebP).
          example: https://cdn.example.com/products/2026/06/11/original_01JNB2T4G93QRT5V6W7X8Y9Z0A.webp
        urls:
          type: array
          description: "Variações de tamanho copiadas da imagem de origem (mesmos nomes do upload: `thumbnail`, `sm`, `md`, `lg`, `xl`)."
          items:
            type: object
            properties:
              name:
                type: string
                example: sm
              size:
                type: string
                nullable: true
                example: 200x200
              url:
                type: string
                format: uri
                example: https://cdn.example.com/products/2026/06/11/sm_01JNB2T4G93QRT5V6W7X8Y9Z0A.webp
            required:
              - name
              - url
      required:
        - id
        - source_image_id
        - original_source
        - urls
  responses:
    Unauthorized:
      description: Token não fornecido, inválido ou expirado
      content:
        "application/json":
          example:
            success: false
            code: 401
            message_code: UNAUTHORIZED
            description: A autenticação é necessária e falhou ou não foi fornecida.
            data: []
            errors:
              - O access_token da loja é obrigatório no cabeçalho Authorization
            meta: []
    Forbidden:
      description: Sem permissão para acessar este recurso
      content:
        "application/json":
          example:
            success: false
            code: 403
            message_code: FORBIDDEN
            description: Você não tem permissão para acessar este recurso.
            data: []
            errors:
              - "Você não tem permissão para acessar este recurso (escopos ausentes: store_products_write)"
            meta: []
    NotFound:
      description: Recurso não encontrado
      content:
        "application/json":
          example:
            success: false
            code: 404
            message_code: NOT_FOUND
            description: O recurso solicitado não foi encontrado.
            data: []
            errors:
              - Produto não encontrado.
            meta: []
    Duplicated:
      description: "Recurso duplicado (ex: SKU já existe nesta loja)"
      content:
        "application/json":
          example:
            success: false
            code: 409
            message_code: DUPLICATED
            description: Este SKU já está cadastrado para esta loja.
            data: []
            errors:
              - Este SKU já está cadastrado para esta loja.
            meta: []
    ValidationError:
      description: Erro de validação nos campos enviados
      content:
        "application/json":
          example:
            success: false
            code: 422
            message_code: VALIDATION_ERROR
            description: Foram encontrados erros de validação na requisição.
            data: []
            errors:
              sku:
                - O campo SKU é obrigatório.
              name:
                - O campo Nome é obrigatório.
              "dimensions.height":
                - O campo dimensions.height é obrigatório.
            meta: []
    Conflict:
      description: Endereco identico ja vinculado ao local de estoque
      content:
        "application/json":
          example:
            success: false
            message_code: CONFLICT
            data:
              message: Já existe um endereço idêntico vinculado ao local de estoque.
security:
  - integrationToken: []
