{
  "openapi": "3.0.3",
  "info": {
    "title": "PrintBee - Pedidos do Cliente",
    "description": "Endpoints para listar e consultar pedidos do cliente. Acessíveis por **Customer** (área do cliente) ou **ApiClient** (credencial de API).\n\n**Autenticação:** Enviar o header `Authorization: Bearer <token>` em cada requisição. O token é obtido via `POST /api/Auth/Token` com client_credentials.\n\n**Criação via API (integração):** lojas e sistemas próprios podem enviar pedidos via `POST /api/Customers/Integrations/Orders` (credencial ApiClient) — eles entram como rascunhos no portal para revisão e geração do pedido de produção.\n\n## Jornada: Pedido criado pela API\n\nSeu sistema envia o pedido para a API. Ele entra como rascunho e a conversão em pedido de produção é feita pela sua equipe no portal, onde produto, frete e arte são conferidos.\n\n![Diagrama de sequência do pedido criado pela API: seu sistema envia POST /api/Customers/Integrations/Orders; a API valida o contrato, deduplica pelo identificador externo e responde 202 Accepted com o rascunho criado; o evento integration_order.received chega ao portal, onde sua equipe mapeia os itens, define o frete e converte, gerando integration_order.converted e order.created.](/openapi/diagrams/jornada-pedido-api.svg)\n\nO `202 Accepted` confirma que o pedido foi recebido como RASCUNHO — ele ainda não entrou em produção. A conversão do rascunho em pedido é feita no portal: a credencial de API cria e consulta o rascunho, mas não converte.\n\n**Erros de contrato retornados na criação do pedido:**\n\n| Código | HTTP | O que significa |\n|--------|------|----------|\n| INT0018 | 400 | O código do pedido é obrigatório |\n| INT0019 | 400 | O pedido deve conter ao menos um item |\n| INT0020 | 400 | Item inválido: nome e quantidade (mínimo 1) são obrigatórios |\n| ATH0002 | 403 | Pedido fora do escopo da sua credencial |\n\n## Jornada: Acompanhando o pedido\n\nA consulta aceita vários formatos de identificador e sempre respeita o escopo da sua credencial: você só enxerga o que pertence à sua conta.\n\n![Diagrama de sequência do acompanhamento: seu sistema envia GET /api/Customers/Orders/{identificador}, aceitando o id, 2490, #2490 ou BEE00002490; a API resolve o identificador, aplica o escopo da credencial e responde 200 com status e rastreio, ou 204 sem conteúdo quando o pedido não está no seu escopo.](/openapi/diagrams/jornada-acompanhamento.svg)\n\nPedido que não pertence à sua conta responde `204`, nunca os dados de outro cliente. Para listar, use `GET /api/Customers/Orders` com paginação.\n\n## Pedido vindo de loja conectada\n\nCom a loja Nuvemshop ou WooCommerce conectada, o pedido não começa aqui: ele começa no webhook enviado pela plataforma da loja. A jornada completa desse fluxo está no Overview da seção **Webhooks**.",
    "version": "1.0.0",
    "contact": {
      "name": "Suporte PrintBee",
      "url": "https://api.printbee.com.br"
    }
  },
  "servers": [
    {
      "url": "https://api.printbee.com.br",
      "description": "Produção"
    }
  ],
  "security": [
    {
      "BearerAuth": []
    }
  ],
  "paths": {
    "/api/Customers/Orders": {
      "get": {
        "tags": [
          "Pedidos"
        ],
        "summary": "Listar Pedidos",
        "description": "Retorna lista paginada de pedidos do cliente autenticado. Restringe automaticamente ao CustomerId do CustomerUser ou ApiClient.\n\n**Tabela de erros:**\n\n| Código | HTTP | Descrição |\n|--------|------|----------|\n| - | 400 | Requisição inválida (parâmetros incorretos) |\n| - | 401 | Token ausente ou inválido. Obtenha novo token via POST /api/Auth/Token |\n| - | 403 | Acesso negado. Endpoint exclusivo para Customer e ApiClient |",
        "operationId": "getCustomerOrders",
        "parameters": [
          {
            "name": "pageNumber",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 1
            },
            "description": "Número da página da paginação (inicia em 1)"
          },
          {
            "name": "pageSize",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 20
            },
            "description": "Quantidade de itens por página"
          },
          {
            "name": "sort",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "CreatedAt DESC"
            },
            "description": "Campo e direção de ordenação. Ex: CreatedAt DESC, Amount ASC"
          },
          {
            "name": "search",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Busca textual em nome, documento, NSU e ordem de compra. Use #123 para buscar por NSU ou PurchaseOrder"
          },
          {
            "name": "nsu",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "example": "BEE00001383",
            "description": "Filtro por número do pedido. Aceita o código público (`BEE00001383`) ou o número puro (`1383`) — as duas formas localizam o mesmo pedido."
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "array",
              "items": {
                "$ref": "#/components/schemas/OrderStatus"
              }
            },
            "description": "Filtro por status do pedido. Pode enviar múltiplos valores"
          }
        ],
        "responses": {
          "200": {
            "description": "Lista de pedidos retornada com sucesso",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomerOrdersPaginatedResponse"
                }
              }
            }
          },
          "400": {
            "description": "Requisição inválida",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorPayload"
                }
              }
            }
          },
          "401": {
            "description": "Token inválido ou ausente",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorPayload"
                }
              }
            }
          },
          "403": {
            "description": "Acesso negado - endpoint exclusivo para Customer e ApiClient",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorPayload"
                }
              }
            }
          }
        }
      }
    },
    "/api/Customers/Orders/{identifier}": {
      "get": {
        "tags": [
          "Pedidos"
        ],
        "summary": "Obter Pedido por Identificador",
        "description": "Retorna um pedido específico por OrderId (Guid), NSU (número) ou PurchaseOrder (ordem de compra). Restringe ao cliente autenticado. Retorna 204 (sem corpo) quando o pedido não existe ou não pertence ao cliente.\n\n**Tabela de erros:**\n\n| Código | HTTP | Descrição |\n|--------|------|----------|\n| - | 401 | Token ausente ou inválido. Obtenha novo token via POST /api/Auth/Token |\n| - | 403 | Acesso negado. Endpoint exclusivo para Customer e ApiClient |",
        "operationId": "getCustomerOrder",
        "parameters": [
          {
            "name": "identifier",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "BEE00001383",
            "description": "Identificador do pedido: código público (`BEE00001383`), número puro (`1383`), OrderId (GUID) ou PurchaseOrder (`PO-2024-001`). O código público e o número puro localizam o mesmo pedido; um identificador que não seja GUID nem numérico é tratado como ordem de compra."
          }
        ],
        "responses": {
          "200": {
            "description": "Pedido encontrado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrderTrackingModel"
                }
              }
            }
          },
          "204": {
            "description": "Pedido não encontrado ou não pertence ao cliente autenticado"
          },
          "401": {
            "description": "Token inválido ou ausente",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorPayload"
                }
              }
            }
          },
          "403": {
            "description": "Acesso negado - endpoint exclusivo para Customer e ApiClient",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorPayload"
                }
              }
            }
          }
        }
      }
    },
    "/api/Customers/Simulate": {
      "post": {
        "tags": [
          "Frete"
        ],
        "summary": "Simular frete",
        "description": "Simula opções de frete para um CEP de destino. Utiliza sempre a empresa de logística ID 1. Requer autenticação (Customer). Usado no carrinho e checkout para calcular frete. Retorna opções incluindo \"Retirada na Fábrica\" com custo zero.\n\n**Tabela de erros:**\n\n| Código | HTTP | Descrição |\n|--------|------|----------|\n| - | 400 | Requisição inválida - CEP ou dados incorretos |\n| - | 401 | Token ausente ou inválido. Obtenha novo token via POST /api/Auth/Token |\n| - | 403 | Acesso negado. Endpoint exclusivo para Customer |",
        "operationId": "simulateFreight",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SimulateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Simulação retornada com sucesso",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "type": "integer",
                      "description": "Código HTTP da resposta (200)"
                    },
                    "data": {
                      "type": "array",
                      "description": "Lista de opções de frete ordenadas por custo-benefício",
                      "items": {
                        "$ref": "#/components/schemas/SimulationModel"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Requisição inválida",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorPayload"
                }
              }
            }
          },
          "401": {
            "description": "Token inválido ou ausente",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorPayload"
                }
              }
            }
          },
          "403": {
            "description": "Acesso negado - endpoint exclusivo para Customer",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorPayload"
                }
              }
            }
          }
        }
      }
    },
    "/api/Customers/Integrations/Orders": {
      "post": {
        "tags": [
          "Pedidos de Integração"
        ],
        "summary": "Criar Pedido",
        "description": "Recebe um pedido da **sua plataforma** (loja virtual ou sistema próprio) e o registra como **rascunho de pedido de integração** no PrintBee. Os dados enviados são os do **seu mundo** — nomes, SKUs e valores da sua loja, sem relação com o catálogo PrintBee. No portal, você vincula cada item a um produto interno (com cor/tamanho), adiciona a customização (arte) e seleciona o frete; só então o rascunho vira um pedido real de produção (com os preços do catálogo PrintBee).\n\n**Campos do body:**\n\n| Campo | Obrigatório | Descrição |\n|-------|-------------|----------|\n| `code` | Sim | Código único do pedido na sua plataforma (único por cliente). Base da deduplicação |\n| `requestClientId` | Não | Identificação interna do pedido no seu sistema (ID técnico), distinta do código visível. Aceita na consulta por identificador |\n| `buyer` | Sim | Comprador/destinatário: nome, telefone, CPF/CNPJ e endereço de entrega (etiqueta) |\n| `status` | Não | Status do pedido na sua plataforma (texto livre, informativo) |\n| `freightAmount` | Não | Valor do frete cobrado na sua plataforma |\n| `paidAmount` | Não | Valor pago pelo comprador na sua plataforma |\n| `items[]` | Sim (mín. 1) | Itens como vendidos: `name`, `sku` (o SEU, opcional — alimenta o auto-vínculo), `quantity`, `unitPrice`, `properties[]` |\n| `properties[]` | Não | Informações adicionais do pedido (pares chave/valor) |\n\n**Idempotência:** reenviar o mesmo `code` não duplica — retorna o rascunho existente com `deduplicated: true` (seguro reenviar em timeout).\n\n**Tabela de erros:**\n\n| Código | HTTP | Descrição |\n|--------|------|----------|\n| - | 202 | Rascunho criado ou deduplicado |\n| INT0018 | 400 | O código do pedido é obrigatório |\n| INT0019 | 400 | O pedido deve conter ao menos um item |\n| INT0020 | 400 | Item inválido: nome e quantidade (mínimo 1) são obrigatórios |\n| - | 401 | Token ausente ou inválido. Obtenha novo token via POST /api/Auth/Token |\n| - | 403 | Acesso negado (credencial sem permissão) |",
        "operationId": "createIntegrationOrder",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateIntegrationOrderRequest"
              },
              "example": {
                "code": "1001",
                "requestClientId": "871254203",
                "buyer": {
                  "name": "João Silva",
                  "email": "joao.silva@exemplo.com",
                  "phone": "11999990000",
                  "taxId": "39053344705",
                  "zipCode": "01310100",
                  "street": "Rua das Flores",
                  "number": "123",
                  "complement": "Apto 45",
                  "neighborhood": "Centro",
                  "city": "São Paulo",
                  "state": "SP"
                },
                "status": "pago",
                "freightAmount": 15.0,
                "paidAmount": 115.0,
                "items": [
                  {
                    "name": "Camiseta do Naruto",
                    "sku": "CAM-NARUTO-G",
                    "quantity": 2,
                    "unitPrice": 50.0,
                    "properties": [
                      {
                        "key": "Nome para estampar",
                        "value": "João"
                      }
                    ]
                  }
                ],
                "properties": [
                  {
                    "key": "Canal de venda",
                    "value": "Loja virtual"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Rascunho criado, deduplicado ou registrado como falha de normalização",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IngestResultPayload"
                },
                "examples": {
                  "criado": {
                    "summary": "Rascunho criado com sucesso",
                    "value": {
                      "code": 202,
                      "data": {
                        "draftId": "5819a1c4-1ebd-4375-880b-6762d427262b",
                        "status": "Pending",
                        "deduplicated": false
                      }
                    }
                  },
                  "deduplicado": {
                    "summary": "Pedido já recebido (dedup) — rascunho existente retornado",
                    "value": {
                      "code": 202,
                      "data": {
                        "draftId": "5819a1c4-1ebd-4375-880b-6762d427262b",
                        "status": "Pending",
                        "deduplicated": true
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Request inválido (payload inválido ou maior que 512 KB)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorPayload"
                }
              }
            }
          },
          "401": {
            "description": "Token inválido ou ausente",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorPayload"
                }
              }
            }
          },
          "403": {
            "description": "Acesso negado (credencial sem permissão)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorPayload"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "Pedidos de Integração"
        ],
        "summary": "Listar Pedidos",
        "description": "Lista paginada dos rascunhos de pedidos de integração do cliente autenticado. A credencial de integração (ApiClient) vê **apenas os próprios** rascunhos (escopo pelo `customer_id` do token).\n\n**Tabela de erros:**\n\n| Código | HTTP | Descrição |\n|--------|------|----------|\n| - | 200 | Lista paginada (vazia se a credencial não tiver `customer_id`) |\n| - | 401 | Token ausente ou inválido |",
        "operationId": "listIntegrationOrders",
        "parameters": [
          {
            "name": "pageNumber",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 1
            },
            "description": "Número da página (inicia em 1)"
          },
          {
            "name": "pageSize",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 20
            },
            "description": "Quantidade de itens por página"
          },
          {
            "name": "sort",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "ReceivedAt DESC"
            },
            "description": "Campo e direção de ordenação (ex.: ReceivedAt DESC)"
          },
          {
            "name": "search",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Busca por número externo ou nome do comprador"
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "Pending",
                "Reviewing",
                "Ready",
                "Converted",
                "Discarded",
                "Failed"
              ]
            },
            "description": "Filtro por status do rascunho"
          },
          {
            "name": "platform",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "OTHER",
                "NUVEMSHOP",
                "SHOPIFY",
                "WOOCOMMERCE",
                "TRAY",
                "WIX",
                "EBAY",
                "MANUAL"
              ]
            },
            "description": "Filtro por plataforma de origem"
          }
        ],
        "responses": {
          "200": {
            "description": "Lista paginada retornada com sucesso",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IntegrationOrdersPaginatedResponse"
                }
              }
            }
          },
          "401": {
            "description": "Token inválido ou ausente",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorPayload"
                }
              }
            }
          }
        }
      }
    },
    "/api/Customers/Integrations/Orders/{identifier}": {
      "get": {
        "tags": [
          "Pedidos de Integração"
        ],
        "summary": "Obter Pedido por Identificador",
        "description": "Retorna o detalhe de um rascunho por um **identificador único**, que pode ser:\n\n- o **Id** do rascunho (GUID PrintBee — o `draftId` retornado na criação); ou\n- o **código do cliente** (`code`) ou a **identificação interna** (`requestClientId`) atribuídos pela sua plataforma.\n\nGUID → busca por Id; caso contrário → busca por `externalId`/`externalNumber`. ApiClient só acessa o próprio rascunho (escopo pelo `customer_id`). Havendo múltiplos com o mesmo código, retorna o mais recente.\n\n**Resposta:** o **modelo direto** do rascunho (mesmo padrão dos demais \"Obter por …\"), não envelopado em `{ code, data }`.\n\n**Tabela de erros:**\n\n| Código | HTTP | Descrição |\n|--------|------|----------|\n| - | 200 | Rascunho retornado (modelo direto) |\n| - | 204 | Não encontrado para o identificador (ou de outro cliente) |\n| - | 401 | Token ausente ou inválido |",
        "operationId": "getIntegrationOrder",
        "parameters": [
          {
            "name": "identifier",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Id do rascunho (GUID), código do pedido (code) ou identificação interna (requestClientId)"
          }
        ],
        "responses": {
          "200": {
            "description": "Rascunho retornado com sucesso",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IntegrationOrderDetail"
                }
              }
            }
          },
          "204": {
            "description": "Rascunho não encontrado para o identificador (ou de outro cliente — fail-closed, sem corpo)"
          },
          "401": {
            "description": "Token inválido ou ausente",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorPayload"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "BearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "Token obtido via POST /api/Auth/Token. Header: Authorization: Bearer <token>"
      }
    },
    "schemas": {
      "OrderStatus": {
        "type": "string",
        "enum": [
          "OPEN",
          "WAITINGPAYMENT",
          "PAYMENTRECEIVED",
          "PRODUCTIONQUEUE",
          "PRODUCTION",
          "PRODUCTIONCOMPLETED",
          "WAITINGFINALPAYMENT",
          "DISPATCH",
          "TRANSIT",
          "DELIVERED",
          "ATTENDED",
          "LOST",
          "RETURNED",
          "CANCELED"
        ],
        "description": "Status do pedido no fluxo de produção e entrega.",
        "x-enumDescriptions": {
          "OPEN": "Aberto — Status inicial do pedido quando é criado. O pedido ainda pode ser modificado e não foi confirmado pelo cliente.",
          "WAITINGPAYMENT": "Aguardando Pagamento — Pedido aguardando confirmação de pagamento. O pedido foi confirmado pelo cliente, mas o pagamento ainda não foi processado.",
          "PAYMENTRECEIVED": "Pagamento Recebido — Indica que o pagamento foi recebido e confirmado. O pedido está pronto para ser processado.",
          "PRODUCTIONQUEUE": "Fila de Produção — Pedido confirmado, aguardando início da produção. Itens de produção foram criados e o pedido está na fila.",
          "PRODUCTION": "Produção — Pedido está em produção pela equipe de manufatura. Os itens estão sendo fabricados/customizados.",
          "PRODUCTIONCOMPLETED": "Produção Concluída — Produção do pedido foi finalizada. Todos os itens foram fabricados e estão prontos para despacho.",
          "WAITINGFINALPAYMENT": "Aguardando Pagamento Final — Produção finalizada, aguardando pagamento do frete. O pedido está pronto para envio.",
          "DISPATCH": "Despachar — Pedido finalizado e aguardando coleta para entrega. O envio foi criado e o pedido está pronto para ser coletado pela transportadora.",
          "TRANSIT": "Em Trânsito — Pedido em rota de entrega. O pacote foi postado e está sendo transportado pela empresa de logística.",
          "DELIVERED": "Entregue — Pedido já entregue ao cliente. O pacote foi entregue com sucesso ao destinatário.",
          "ATTENDED": "Atendido — Pedido finalizado e entregue ao cliente. Status terminal do fluxo normal.",
          "LOST": "Extravio — Pedido foi extraviado durante o transporte. O pacote foi perdido pela transportadora.",
          "RETURNED": "Devolvido — Pedido foi devolvido ao remetente. O pacote retornou e foi recebido de volta.",
          "CANCELED": "Cancelado — Pedido foi cancelado e não será processado. Não será entregue."
        }
      },
      "CustomerOrdersPaginatedResponse": {
        "type": "object",
        "description": "Resposta paginada da lista de pedidos",
        "properties": {
          "items": {
            "type": "array",
            "description": "Lista de pedidos da página atual",
            "items": {
              "$ref": "#/components/schemas/OrderSummaryModel"
            }
          },
          "currentPage": {
            "type": "integer",
            "description": "Número da página retornada"
          },
          "pageSize": {
            "type": "integer",
            "description": "Quantidade de itens por página solicitada"
          },
          "totalCount": {
            "type": "integer",
            "description": "Total de pedidos que atendem aos filtros"
          },
          "totalPages": {
            "type": "integer",
            "description": "Total de páginas disponíveis"
          }
        }
      },
      "OrderSummaryModel": {
        "type": "object",
        "description": "Resumo de um pedido para listagem",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Identificador único do pedido (GUID)"
          },
          "nsu": {
            "type": "string",
            "example": "BEE00001383",
            "description": "Código público do pedido — prefixo `BEE` + 8 dígitos. É o mesmo código exibido ao cliente e aceito no filtro `nsu` e na rota `/Orders/{identifier}`."
          },
          "personType": {
            "type": "string",
            "description": "Tipo da pessoa (PF ou PJ)"
          },
          "personName": {
            "type": "string",
            "description": "Nome ou razão social do cliente"
          },
          "personTaxId": {
            "type": "string",
            "description": "CPF ou CNPJ do cliente"
          },
          "deliveryName": {
            "type": "string",
            "description": "Nome do destinatário da entrega"
          },
          "sellerName": {
            "type": "string",
            "description": "Nome do vendedor responsável"
          },
          "status": {
            "$ref": "#/components/schemas/OrderStatus"
          },
          "amount": {
            "type": "number",
            "format": "decimal",
            "description": "Valor total do pedido"
          },
          "saleDate": {
            "type": "string",
            "format": "date",
            "description": "Data da venda"
          },
          "departureDate": {
            "type": "string",
            "format": "date",
            "description": "Data de saída/envio do pedido"
          },
          "deliveryDate": {
            "type": "string",
            "format": "date",
            "description": "Data de entrega (prevista ou realizada)"
          },
          "purchaseOrder": {
            "type": "string",
            "description": "Número da ordem de compra (informado pelo cliente)"
          },
          "quantityItems": {
            "type": "integer",
            "description": "Quantidade total de itens do pedido"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "Data e hora de criação do pedido"
          }
        }
      },
      "OrderTrackingModel": {
        "type": "object",
        "description": "Modelo de rastreio do pedido (rota anônima) com dados do destinatário e envio. PB-405 WI-1: orderId, customerName, amount, purchaseOrder, quantityItems, createdAt, recipientTaxId, recipientPhone, recipientEmail e freightCost não são mais devolvidos por esta rota — removidos deste schema.",
        "properties": {
          "orderNSU": {
            "type": "string",
            "example": "BEE00001383",
            "description": "Código público do pedido — prefixo `BEE` + 8 dígitos. É o mesmo código exibido ao cliente e aceito no filtro `nsu` e na rota `/Orders/{identifier}`."
          },
          "orderStatus": {
            "type": "string",
            "description": "Status atual do pedido"
          },
          "saleDate": {
            "type": "string",
            "format": "date",
            "description": "Data do pedido/venda"
          },
          "deliveryDate": {
            "type": "string",
            "format": "date",
            "description": "Previsão ou data de entrega"
          },
          "recipientName": {
            "type": "string",
            "description": "Nome do destinatário"
          },
          "zipCode": {
            "type": "string",
            "description": "CEP do endereço de entrega"
          },
          "street": {
            "type": "string",
            "description": "Logradouro"
          },
          "number": {
            "type": "string",
            "description": "Número do endereço"
          },
          "complement": {
            "type": "string",
            "description": "Complemento do endereço"
          },
          "neighborhood": {
            "type": "string",
            "description": "Bairro"
          },
          "city": {
            "type": "string",
            "description": "Cidade"
          },
          "state": {
            "type": "string",
            "description": "Estado (UF)"
          },
          "country": {
            "type": "string",
            "description": "País"
          },
          "fullAddress": {
            "type": "string",
            "description": "Endereço completo formatado"
          },
          "trackingCode": {
            "type": "string",
            "description": "Código de rastreamento da transportadora"
          },
          "trackingUrl": {
            "type": "string",
            "description": "URL para rastrear o envio"
          },
          "shipmentStatus": {
            "type": "string",
            "description": "Status do envio na transportadora"
          },
          "carrierName": {
            "type": "string",
            "description": "Nome da transportadora"
          },
          "serviceName": {
            "type": "string",
            "description": "Nome do serviço de envio"
          },
          "postedAt": {
            "type": "string",
            "format": "date-time",
            "description": "Data e hora da postagem do envio"
          },
          "deliveredAt": {
            "type": "string",
            "format": "date-time",
            "description": "Data e hora da entrega (quando realizada)"
          }
        }
      },
      "SimulateRequest": {
        "type": "object",
        "description": "Dados para simulação de frete",
        "required": [
          "zipCode",
          "amount"
        ],
        "properties": {
          "zipCode": {
            "type": "string",
            "description": "CEP de destino (ex: 01310-100)"
          },
          "amount": {
            "type": "number",
            "format": "decimal",
            "description": "Valor total das mercadorias em reais"
          },
          "weight": {
            "type": "number",
            "format": "decimal",
            "description": "Peso total em kg"
          },
          "height": {
            "type": "number",
            "format": "decimal",
            "description": "Altura do pacote em mm"
          },
          "width": {
            "type": "number",
            "format": "decimal",
            "description": "Largura do pacote em mm"
          },
          "length": {
            "type": "number",
            "format": "decimal",
            "description": "Comprimento do pacote em mm"
          },
          "compositions": {
            "type": "array",
            "description": "Lista de itens do pedido com peso e dimensões",
            "items": {
              "$ref": "#/components/schemas/SimulateItemModel"
            }
          }
        }
      },
      "SimulateItemModel": {
        "type": "object",
        "description": "Item para composição do frete",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Identificação do produto"
          },
          "sku": {
            "type": "string",
            "description": "Código do produto (SKU)"
          },
          "amount": {
            "type": "number",
            "format": "decimal",
            "description": "Valor"
          },
          "quantity": {
            "type": "integer",
            "description": "Quantidade"
          },
          "weight": {
            "type": "number",
            "format": "decimal",
            "description": "Peso em kg"
          },
          "height": {
            "type": "number",
            "format": "decimal",
            "description": "Altura em mm"
          },
          "width": {
            "type": "number",
            "format": "decimal",
            "description": "Largura em mm"
          },
          "length": {
            "type": "number",
            "format": "decimal",
            "description": "Comprimento em mm"
          }
        }
      },
      "SimulationModel": {
        "type": "object",
        "description": "Opção de frete retornada na simulação",
        "properties": {
          "id": {
            "type": "string",
            "description": "Identificação do frete"
          },
          "name": {
            "type": "string",
            "description": "Nome do frete/serviço"
          },
          "companyId": {
            "type": "string",
            "description": "Identificação da transportadora"
          },
          "companyName": {
            "type": "string",
            "description": "Nome da transportadora"
          },
          "companyImage": {
            "type": "string",
            "description": "Logo da transportadora"
          },
          "shippingCost": {
            "type": "number",
            "format": "decimal",
            "description": "Valor do frete"
          },
          "deliveryTime": {
            "type": "integer",
            "description": "Prazo de entrega em dias"
          },
          "estimatedDeliveryDate": {
            "type": "string",
            "format": "date",
            "description": "Data estimada de entrega"
          },
          "message": {
            "type": "string",
            "description": "Mensagem do frete"
          },
          "isActive": {
            "type": "boolean",
            "description": "Indica se o frete está ativo"
          }
        }
      },
      "ErrorPayload": {
        "type": "object",
        "description": "Resposta padrão de erro da API",
        "required": [
          "code",
          "errors"
        ],
        "properties": {
          "code": {
            "type": "integer",
            "description": "Código HTTP do erro (400, 401, 403, etc.)"
          },
          "errors": {
            "type": "array",
            "description": "Lista de erros detalhados",
            "items": {
              "type": "object",
              "properties": {
                "errorCode": {
                  "type": "string",
                  "description": "Código interno do erro (ex: ATH0008, CRD0003)"
                },
                "message": {
                  "type": "string",
                  "description": "Mensagem descritiva do erro"
                }
              }
            }
          }
        }
      },
      "IngestResultPayload": {
        "type": "object",
        "description": "Envelope de resposta da criação de pedido",
        "properties": {
          "code": {
            "type": "integer",
            "description": "Código HTTP da resposta",
            "example": 202
          },
          "data": {
            "$ref": "#/components/schemas/IngestResult"
          }
        }
      },
      "IngestResult": {
        "type": "object",
        "description": "Resultado da criação do pedido de integração",
        "properties": {
          "draftId": {
            "type": "string",
            "format": "uuid",
            "description": "ID do rascunho criado (ou do existente, em caso de deduplicação). Guarde para rastreabilidade"
          },
          "status": {
            "type": "string",
            "enum": [
              "Pending",
              "Reviewing",
              "Ready",
              "Converted",
              "Discarded",
              "Failed"
            ],
            "description": "Status do rascunho após a criação. Pending = aguardando revisão no portal; Failed = payload não pôde ser normalizado (detalhe no portal)"
          },
          "deduplicated": {
            "type": "boolean",
            "description": "true quando o pedido já havia sido recebido (mesmo externalId) e o rascunho existente foi retornado"
          }
        }
      },
      "IntegrationOrderSummary": {
        "type": "object",
        "description": "Resumo de um rascunho de pedido de integração (item da listagem)",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Guid do rascunho (draftId)"
          },
          "platform": {
            "type": "string",
            "description": "Plataforma de origem (ex.: OTHER, NUVEMSHOP)"
          },
          "externalNumber": {
            "type": "string",
            "description": "Número visível do pedido na origem"
          },
          "status": {
            "type": "string",
            "description": "Status: Pending, Reviewing, Ready, Converted, Discarded, Failed"
          },
          "total": {
            "type": "number",
            "format": "decimal",
            "description": "Total do pedido"
          },
          "buyerName": {
            "type": "string",
            "description": "Nome do destinatário (comprador)"
          },
          "receivedAt": {
            "type": "string",
            "format": "date-time",
            "description": "Quando o PrintBee recebeu o rascunho"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "Data de criação no PrintBee"
          },
          "itemsCount": {
            "type": "integer",
            "description": "Quantidade de itens"
          },
          "convertedOrderId": {
            "type": "string",
            "format": "uuid",
            "nullable": true,
            "description": "Id do pedido real gerado pela conversão (null enquanto não convertido)"
          },
          "convertedAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Data/hora em que o rascunho foi convertido em pedido (null se não convertido)"
          },
          "canConvert": {
            "type": "boolean",
            "description": "Indica se o rascunho está pronto para conversão (sem item não mapeado, ao menos 1 mapeado e frete definido)"
          }
        }
      },
      "IntegrationOrdersPaginatedResponse": {
        "type": "object",
        "description": "Resposta paginada da listagem de pedidos de integração",
        "properties": {
          "currentPage": {
            "type": "integer"
          },
          "totalPages": {
            "type": "integer"
          },
          "pageSize": {
            "type": "integer"
          },
          "totalCount": {
            "type": "integer"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/IntegrationOrderSummary"
            }
          }
        }
      },
      "IntegrationOrderBuyer": {
        "type": "object",
        "description": "Comprador/destinatário do rascunho (identidade + endereço de envio)",
        "properties": {
          "name": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "phone": {
            "type": "string"
          },
          "taxId": {
            "type": "string"
          },
          "taxIdType": {
            "type": "string"
          },
          "externalCustomerId": {
            "type": "string"
          },
          "zipCode": {
            "type": "string"
          },
          "street": {
            "type": "string"
          },
          "number": {
            "type": "string"
          },
          "complement": {
            "type": "string"
          },
          "neighborhood": {
            "type": "string"
          },
          "city": {
            "type": "string"
          },
          "state": {
            "type": "string"
          },
          "country": {
            "type": "string"
          }
        }
      },
      "IntegrationOrderItem": {
        "type": "object",
        "description": "Item do rascunho (com status de mapeamento e produto vinculado)",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "sortOrder": {
            "type": "integer"
          },
          "externalSku": {
            "type": "string",
            "description": "SKU enviado pela loja"
          },
          "name": {
            "type": "string",
            "description": "Nome do item na origem"
          },
          "quantity": {
            "type": "integer"
          },
          "unitPrice": {
            "type": "number",
            "format": "decimal",
            "description": "Preço unitário na origem (referência)"
          },
          "totalPrice": {
            "type": "number",
            "format": "decimal"
          },
          "imageUrl": {
            "type": "string"
          },
          "mappingStatus": {
            "type": "string",
            "description": "Unmapped, Mapped ou Ignored"
          },
          "mappedProductId": {
            "type": "string",
            "format": "uuid",
            "description": "Produto PrintBee vinculado (quando mapeado)"
          },
          "mappedProductName": {
            "type": "string"
          },
          "mappedProductSKU": {
            "type": "string"
          },
          "mappedProductPrice": {
            "type": "number",
            "format": "decimal",
            "description": "Preço do catálogo PrintBee"
          },
          "isCustomizable": {
            "type": "boolean"
          },
          "customProperties": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "key": {
                  "type": "string"
                },
                "value": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "IntegrationOrderDetail": {
        "type": "object",
        "description": "Detalhe completo de um rascunho de pedido de integração",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "platform": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "description": "Pending, Reviewing, Ready, Converted, Discarded, Failed"
          },
          "externalId": {
            "type": "string"
          },
          "externalNumber": {
            "type": "string"
          },
          "storeId": {
            "type": "string"
          },
          "currency": {
            "type": "string"
          },
          "subtotal": {
            "type": "number",
            "format": "decimal"
          },
          "discount": {
            "type": "number",
            "format": "decimal"
          },
          "shippingTotal": {
            "type": "number",
            "format": "decimal"
          },
          "externalShippingName": {
            "type": "string",
            "nullable": true,
            "description": "Nome do frete/serviço escolhido pelo comprador na loja de origem (ex.: PAC, Loggi Express). Derivado do payload bruto da plataforma no momento da leitura (não é coluna) e presente apenas no detalhe; null quando a plataforma não envia. Informativo: não define o frete PrintBee, escolhido/cotado no editor antes da conversão. O valor do frete da origem continua em shippingTotal"
          },
          "taxTotal": {
            "type": "number",
            "format": "decimal"
          },
          "total": {
            "type": "number",
            "format": "decimal"
          },
          "customerNote": {
            "type": "string"
          },
          "ownerNote": {
            "type": "string",
            "description": "Nota interna do lojista"
          },
          "externalCreatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "externalPaidAt": {
            "type": "string",
            "format": "date-time"
          },
          "receivedAt": {
            "type": "string",
            "format": "date-time"
          },
          "buyer": {
            "$ref": "#/components/schemas/IntegrationOrderBuyer"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/IntegrationOrderItem"
            }
          },
          "externalStatus": {
            "type": "string",
            "description": "Status do pedido na plataforma do cliente (informativo)"
          },
          "properties": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/IntegrationOrderProperty"
            },
            "description": "Informações adicionais do pedido enviadas pela plataforma"
          },
          "requestClientId": {
            "type": "string",
            "description": "Identificação interna do pedido na plataforma do cliente"
          }
        }
      },
      "IntegrationOrderProperty": {
        "type": "object",
        "description": "Informação adicional livre da plataforma do cliente (par chave/valor)",
        "properties": {
          "key": {
            "type": "string",
            "description": "Nome da informação (ex.: Nome para estampar)"
          },
          "value": {
            "type": "string",
            "description": "Valor informado"
          }
        }
      },
      "CreateIntegrationOrderBuyer": {
        "type": "object",
        "description": "Comprador/destinatário do pedido — usado na etiqueta de envio",
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "Nome completo do comprador"
          },
          "email": {
            "type": "string",
            "format": "email",
            "description": "E-mail do comprador (opcional — apenas registrado, não usado em comunicação)"
          },
          "phone": {
            "type": "string",
            "description": "Telefone com DDD (apenas dígitos)"
          },
          "taxId": {
            "type": "string",
            "description": "CPF ou CNPJ (apenas dígitos)"
          },
          "zipCode": {
            "type": "string",
            "description": "CEP (apenas dígitos)",
            "example": "01310100"
          },
          "street": {
            "type": "string",
            "description": "Logradouro (rua, avenida)"
          },
          "number": {
            "type": "string",
            "description": "Número do endereço"
          },
          "complement": {
            "type": "string",
            "description": "Complemento do endereço"
          },
          "neighborhood": {
            "type": "string",
            "description": "Bairro"
          },
          "city": {
            "type": "string",
            "description": "Cidade"
          },
          "state": {
            "type": "string",
            "description": "Estado (UF, 2 letras)",
            "example": "SP"
          },
          "country": {
            "type": "string",
            "description": "País (ISO 3166-1 alpha-2). Ausente → BR",
            "example": "BR"
          }
        }
      },
      "CreateIntegrationOrderItem": {
        "type": "object",
        "description": "Item do pedido como vendido na SUA plataforma — sem relação com o catálogo PrintBee. O vínculo com o produto interno (e a customização) é feito depois, no portal",
        "required": [
          "name",
          "quantity",
          "unitPrice"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "Nome do produto na sua plataforma (ex.: Camiseta do Naruto)"
          },
          "sku": {
            "type": "string",
            "description": "SKU do produto na SUA plataforma (diferente do SKU PrintBee). Opcional; quando enviado, alimenta o auto-vínculo: ao \"lembrar\" um vínculo no portal, pedidos futuros com o mesmo SKU já chegam vinculados"
          },
          "quantity": {
            "type": "integer",
            "minimum": 1,
            "description": "Quantidade vendida"
          },
          "unitPrice": {
            "type": "number",
            "format": "decimal",
            "description": "Valor unitário cobrado na sua plataforma (referência — o pedido de produção usa o preço do catálogo PrintBee)"
          },
          "properties": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/IntegrationOrderProperty"
            },
            "description": "Informações adicionais do item (ex.: personalização escolhida pelo comprador)"
          }
        }
      },
      "CreateIntegrationOrderRequest": {
        "type": "object",
        "description": "Pedido da plataforma do cliente — contrato público de criação",
        "required": [
          "code",
          "buyer",
          "items"
        ],
        "properties": {
          "code": {
            "type": "string",
            "description": "Código único do pedido na sua plataforma (único por cliente). Base da deduplicação e da consulta por identificador"
          },
          "requestClientId": {
            "type": "string",
            "description": "Identificação INTERNA do pedido na sua plataforma (ID técnico do seu sistema), distinta do código visível. Registrada para rastreabilidade e aceita na consulta por identificador"
          },
          "buyer": {
            "$ref": "#/components/schemas/CreateIntegrationOrderBuyer"
          },
          "status": {
            "type": "string",
            "description": "Status do pedido na sua plataforma (texto livre, informativo — ex.: pago, aguardando envio)"
          },
          "freightAmount": {
            "type": "number",
            "format": "decimal",
            "description": "Valor do frete cobrado na sua plataforma"
          },
          "paidAmount": {
            "type": "number",
            "format": "decimal",
            "description": "Valor pago pelo comprador na sua plataforma"
          },
          "items": {
            "type": "array",
            "minItems": 1,
            "items": {
              "$ref": "#/components/schemas/CreateIntegrationOrderItem"
            }
          },
          "properties": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/IntegrationOrderProperty"
            },
            "description": "Informações adicionais do pedido (pares chave/valor livres)"
          }
        }
      }
    }
  },
  "tags": [
    {
      "name": "Pedidos",
      "description": "Consulta e rastreio de pedidos do cliente."
    },
    {
      "name": "Pedidos de Integração",
      "description": "Criação de pedidos via API a partir da loja virtual ou sistema próprio. Entram como rascunhos no portal para revisão, vínculo de produtos e geração do pedido de produção."
    },
    {
      "name": "Frete",
      "description": "Simulação de opções de frete."
    }
  ]
}
