Logística
Shipments do pedido, geração e download de etiquetas de envio. Operação assíncrona com polling.
Pré-requisitos: leia primeiro Pedidos: visão geral. As etiquetas só fazem sentido depois que o pedido tem um documento fiscal; veja Pedidos: fiscal.
O modelo mental
Um pedido pode ter um ou mais shipments. Cada shipment representa um pacote físico que sai da loja e tem um destino, transportador e (quando aplicável) código de rastreio. Para a maioria dos pedidos é 1 shipment, mas pode ter mais (ex.: produto de um SKU vem de uma origem e outro de outra; ou um pedido com retirada parcial e envio parcial).
Cada shipment tem zero, uma ou mais etiquetas (labels). A etiqueta é o PDF que vai colado na caixa. Pode ter mais de uma quando o transportador exige formatos diferentes (ex: A4 + impressão térmica) ou para shipments com múltiplos volumes.
Você como seller dispara a geração (fila um job em background), faz polling até as etiquetas ficarem prontas, e baixa cada uma via URL S3 assinada.
GET /orders/{id}/shipments devolve { "shipments": [ … ] }. Cada shipment:
{
"id": 4421,
"uid": "shp_a1b2c3",
"type": "sales_order", // tipo: sales_order | return | transfer | pickup
"status": "ready_to_ship", // ← status do shipment (valores abaixo)
"tracking_code": "BR123…BR", // rastreio fica aqui, não na etiqueta
"carrier": {…}, // transportadora (id, name)
"labels": [{…}], // etiquetas deste shipment
"labels_ready": 1, // quantas já prontas
"labels_total": 1 // total esperado
}Os valores de status do shipment: pending, processing, ready_to_ship, in_transit, delivered, cancelled, return_in_progress, returned, awaiting_return, failed, error.
E cada label dentro de labels:
{
"id": "lbl_xyz",
"format": "a4", // formato: a4 | zebra | thermal (+ format_label em pt-BR)
"status": "completed", // ← pending | processing | completed | error
"is_ready": true, // já pode baixar? (pronto = completed)
"completed_at": "2026-04-26T16:02:00Z"
}Fluxo completo
1. Disparar geração
POST/api/v1/sellers/orders/{id}/shipment-labels/generate
Sem body. Enfileira um job para cada shipment do pedido. Resposta 202:
{
"success": true,
"code": 202,
"data": {
"queued_shipments": [4421, 4422],
"total": 2
}
}queued_shipments lista os IDs efetivamente enfileirados. Pode ser menor que o número total de shipments do pedido quando algum tem label_generation_blocked=true (ver "Cuidados" abaixo).
Chamar de novo regenera. Se a primeira geração falhou ou se você corrigiu algo no shipment e quer outra rodada, basta chamar
/generatede novo: as etiquetas anteriores são descartadas e novos jobs são disparados.
2. Polling
GET/api/v1/sellers/orders/{id}/shipments
Consulta a lista de shipments com etiquetas embutidas. O que você procura em cada shipment é labels_ready === labels_total:
{
"data": {
"shipments": [
{
"id": 4421,
"uid": "shp_a1b2c3",
"type": "sales_order",
"status": "ready_to_ship",
"tracking_code": "BR123456789BR",
"carrier": { "id": 12, "name": "Correios" },
"labels": [
{
"id": "lbl_xyz",
"format": "a4",
"format_label": "A4 (PDF)",
"status": "completed",
"is_ready": true,
"completed_at": "2026-04-26T16:02:00Z"
}
],
"labels_ready": 1,
"labels_total": 1
}
]
}
}Cadência recomendada: primeiros 15 segundos a cada 2s, depois a cada 5s, com timeout em 2 minutos. A geração típica leva 5–20 segundos por shipment dependendo do transportador.
3. Baixar a etiqueta
Quando is_ready=true, baixe via URL S3:
GET/api/seller/logistics/shipments/{id}/labels/{labelId}/download
{id} é o shipment.id (numérico). {labelId} é o label.id.
{
"success": true,
"code": 200,
"data": {
"label_id": "lbl_xyz",
"format": "a4",
"url": "https://s3.amazonaws.com/.../label_4421.pdf?X-Amz-Signature=...",
"expires_in": "15 minutos"
}
}A url é S3 assinada, válida por 15 minutos. Não armazene a URL; chame a rota de novo se precisar de outra cópia.
Se a etiqueta ainda não estiver pronta no momento do download, retorna 422 UNPROCESSABLE_ENTITY com Status: Em processamento. Volte para o polling antes de tentar de novo.
Rota alternativa (só labels)
Quando você já tem o shipment.id em mãos e só quer a lista de etiquetas (sem trazer o resto do shipment):
GET/api/seller/logistics/shipments/{id}/labels
É a mesma informação que vem dentro do shipment em /orders/{id}/shipments, mas servida isoladamente. Útil quando você está numa tela "detalhe do shipment" e não quer recarregar todos os shipments do pedido.
A resposta traz também o shipment_id e a lista formats_pending[] (formatos ainda em processamento), e cada label vem com source/source_label (de onde a etiqueta veio) e status_label em pt-BR — bom para exibir direto na tela.
Quando gerar (e quando não)
Antes de gerar, o documento fiscal precisa existir (NF-e registrada ou Declaração emitida). O motivo é prático: nenhum transportador aceita despachar uma encomenda sem nota acompanhando. A API não vai te impedir de gerar a etiqueta antes do fiscal — não é um erro técnico — mas o shipment vai ficar travado na hora do despacho. Por isso a ordem importa: resolva o fiscal primeiro e a etiqueta depois.
Ordem recomendada no fluxo padrão:
paid → preparing → [emite fiscal] → /shipment-labels/generate → ready_to_ship → shippedGere as etiquetas em preparing (depois do fiscal), imprima, cole na caixa, marque ready_to_ship quando o pacote estiver na transportadora.
Cuidados
Shipment com label_generation_blocked=true é pulado. Esse flag fica em true quando o sistema sabe que a etiqueta tem um problema impossível de resolver automaticamente (ex.: dados de endereço inválidos, conta com o transportador suspensa, peso fora do contrato). Você vai ver o shipment em queued_shipmentsvazio ou com total menor que o número real de shipments. Resolva o problema no shipment via operação antes de tentar gerar de novo.
Chamar /generate várias vezes regenera tudo. Não é incremental: uma chamada apaga as etiquetas anteriores e dispara jobs novos para todos os shipments não bloqueados. Use com consciência: se 1 de 3 shipments deu errado, chamar /generate vai regerar os outros 2 também.
A URL S3 expira em 15 minutos. Se você está montando uma tela de impressão em massa, gere as URLs sob demanda (no momento em que o usuário clica em "Imprimir"), não antes.
Tracking code aparece no shipment, não na label. Para ver o tracking_code, leia shipments[].tracking_code em /orders/{id}/shipments ou use GET /orders/{id}/tracking para a versão consolidada por pedido.
Pedido com workflow in_store_pickup pode não ter shipment de saída. Faz sentido: se o cliente vai retirar na loja, não há nada para despachar, então também não há etiqueta a imprimir. Se você chamar /generate num pedido sem nenhum shipment, a resposta é 404 com a mensagem "Nenhum shipment encontrado para este pedido.".

