Devoluções
Tratamento de devoluções (RMA) encaminhadas ao seller pela plataforma: aprovação, rejeição, geração de coleta reversa e decisão do desfecho (solicitar estorno ou encerrar sem estorno).
Você decide o desfecho; o financeiro da plataforma executa o estorno. Depois que o produto volta (
received), você solicita o estorno (/request-refund) ou encerra o caso sem estorno (/close-without-refund). O pagamento do estorno em si é processado pela plataforma. Veja Reembolsos ao final.
Como devoluções chegam ao seller
O fluxo de devolução começa do lado do cliente, não do seller. A plataforma faz uma triagem inicial: algumas devoluções são resolvidas automaticamente (ex.: pedidos com seguro, casos óbvios de extravio). Outras são encaminhadas ao seller com status forwarded_to_seller (o "encaminhar" transfere a tomada de decisão, não a visibilidade): a API lista todas as devoluções da loja desde a abertura, para a operação acompanhar mesmo quando a decisão ainda é da plataforma.
Status possíveis:
| Status | Significa |
|---|---|
pending | Solicitação recém-criada pelo cliente, ainda em triagem. |
forwarded_to_seller | A plataforma encaminhou; sua loja precisa aprovar ou rejeitar. |
approved | Seller aprovou. A coleta reversa pode ser gerada. |
rejected | Seller recusou. Cliente vê o motivo. |
cancelled | Cliente desistiu antes de qualquer decisão. |
label_generated | Coleta reversa gerada (em qualquer modo); aguardando coleta/etiqueta. Daqui você já pode confirmar o recebimento quando o produto chegar. |
return_in_progress | Coleta em andamento (em qualquer modo). |
received | Produto chegou de volta à loja (confirmado via /mark-received). É o ponto de decisão do desfecho. |
refunded | Solicitação de estorno criada; o financeiro da plataforma está processando o reembolso. |
closed | Caso encerrado. O campo resolution diz como: refunded (estorno concluído) ou resolved_externally (resolvido fora da plataforma, sem estorno). |
O desfecho (quem decide, quanto é estornado em devoluções parciais, e o caso "resolvido por fora") tem guia próprio: Devoluções: Resolução.
1. Listagem
GET/api/v1/sellers/orders/returns
Sem filtros, devolve todas as devoluções da loja, inclusive as que ainda estão em triagem na plataforma (pending) e as já encerradas. Use os filtros para recortar o que interessa:
| Para… | Use |
|---|---|
| Fila aguardando sua decisão | ?status=forwarded_to_seller |
| Todas as devoluções de um pedido | ?order_id=01JX8K3M9PEDIDO000000000AB |
| Apenas as recusadas | ?status=rejected |
| Buscar por número de pedido | ?q=ORD-0001 |
| Janela de datas | ?date_from=2026-04-01&date_to=2026-04-30 |
Resposta paginada (?per_page=15 é o default):
{
"success": true,
"message_code": "SUCCESS",
"data": {
"meta": {
"pagination": {
"page": 1,
"per_page": 15,
"last_page": 1,
"has_prev_page": false,
"has_next_page": false,
"records": { "from": 1, "to": 1, "records": 1 }
}
},
"data": [
{
"id": "01JX8K3M9DEVOLUCAO00000000",
"order_id": "01JX8K3M9PEDIDO000000000AB",
"order_number": "ORD-000123",
"status": "forwarded_to_seller",
"notes": "Produto com defeito",
"seller_response_deadline_at": "2026-04-28T10:15:00-03:00",
"sla_exceeded": false,
"created_at": "2026-04-26T10:15:00-03:00"
}
]
}
}
seller_response_deadline_atesla_exceededindicam o SLA configurado na plataforma (returns.seller_response_sla_hours, default 48h). Use para destacar visualmente devoluções com prazo estourado.
2. Detalhe da devolução
GET/api/v1/sellers/orders/returns/{id}
Devolve o registro completo: observação do cliente (notes), itens devolvidos (items[]), endereço de coleta (pickup_address), janela e contato (preenchidos quando vai haver coleta), histórico de timestamps (approved_at, rejected_at, cancelled_at, etc.).
O motivo vem em dupla: return_reason_key (chave para lógica) e return_reason_label (rótulo humano; é o que você exibe na tela). A lista de motivos é configurável pela operação da plataforma, então não fixe um enum próprio no seu sistema: trate return_reason_key como um identificador que pode ganhar novos valores. Cada item de items[] vem enriquecido com os dados do item do pedido correspondente: title, sku, variation, unit_price, thumbnail_url e o próprio reason_label, prontos para renderizar sem consulta extra ao pedido.
{
"data": {
"id": "01JX8K3M9DEVOLUCAO00000000",
"return_reason_key": "product_defect",
"return_reason_label": "Defeito de fabricação",
"items": [
{
"order_item_id": "01JX8K3M9ITEM0000000000001",
"quantity": 2,
"reason_key": "product_defect",
"reason_label": "Defeito de fabricação",
"title": "Furadeira de Impacto 650W",
"sku": "FUR-650-IMP",
"variation": "220V",
"unit_price": 189.90,
"thumbnail_url": "https://cdn.../sm/furadeira.webp"
}
]
}
}É o que a tela "Detalhe da devolução" consome para mostrar todas as informações antes do seller decidir.
3. Decidir: aprovar ou rejeitar
Aprovar
POST/api/v1/sellers/orders/returns/{id}/approve
{
"seller_notes": "Defeito confirmado nas fotos. Reembolso autorizado."
}seller_notes é opcional (máx 1000 caracteres) e fica só no histórico interno; não é exibido ao cliente. Use para registrar a justificativa interna ("conferi com o setor X", "concordo com o atendimento que abriu o ticket").
Depois de aprovar, a próxima ação é gerar a coleta reversa (passo 4 abaixo).
Rejeitar
POST/api/v1/sellers/orders/returns/{id}/reject
{
"reason": "Produto fora do prazo de devolução (entregue há mais de 60 dias)."
}reason é obrigatório (máx 1000 caracteres) e é exibido ao cliente como justificativa. Escreva pensando que o cliente vai ler: explicação clara, sem jargão interno.
4. Coleta reversa
Aprovada a devolução, falta trazer o produto de volta. Dois modos:
carrier: usa um transportador parceiro da plataforma. Você escolhe da lista de elegíveis, a plataforma cria o shipment reverso (comtracking_codeetc.) e o cliente recebe a etiqueta.manual: você organiza a coleta por fora (motoboy próprio, cliente leva na loja, retirada combinada). Nenhum shipment é criado; só o estado da devolução avança e suas anotações ficam no histórico.
4a. Listar carriers elegíveis (modo carrier)
GET/api/v1/sellers/orders/returns/{id}/reverse/eligible-carriers
Lista os transportadores que cobrem o CEP do cliente e o frete estimado de cada um. Use para montar a UI de escolha do transportador.
{
"data": {
"has_coverage": true,
"zip_code": "01310-100",
"carriers": [
{ "id": "01HM0Z6E...", "name": "Correios PAC", "estimated_freight": 18.90, "has_drivers": true },
{ "id": "01HM0X1A...", "name": "Loggi Reverso", "estimated_freight": 22.50, "has_drivers": false }
]
}
}has_coverage=false significa que nenhum carrier parceiro atende o endereço do cliente. Nesse caso, o modo carrier não está disponível; só resta manual (ou negociar suporte da plataforma).
Prefira carrier com
has_drivers: true. A coleta só chega a alguém se o transportador escolhido tiver motorista vinculado. Escolher um sem motorista não dá erro: a coleta é criada, a devolução avança paralabel_generatede o pacote simplesmente nunca é buscado. Se o único carrier com cobertura vierhas_drivers: false, o caminho seguro é a coletamanual.
4b. Gerar coleta
POST/api/v1/sellers/orders/returns/{id}/reverse/generate
Modo carrier:
{
"method": "carrier",
"carrier_id": 7,
"freight_cost": 18.90,
"pickup_contact_phone": "+5511999999999",
"pickup_window_from": "2026-04-28T09:00:00-03:00",
"pickup_window_to": "2026-04-28T18:00:00-03:00"
}| Campo | Quando preencher |
|---|---|
method | Obrigatório.carrier ou manual. |
carrier_id | Obrigatório se method=carrier. Use o id de eligible-carriers. |
freight_cost | Valor que vai ser cobrado/reservado para o frete. Default 0. Normalmente o estimated_freight retornado por eligible-carriers. |
notes | Observações livres (máx 1000 caracteres). Útil em manual. |
pickup_window_from / pickup_window_to | Janela acordada com o cliente. Opcionais, mas se enviar ambos, o "to" precisa ser ≥ "from". |
pickup_contact_phone | Telefone no endereço de coleta. Opcional (máx 32 caracteres). |
Resposta em modo carrier:
{
"data": {
"order_return": { "id": "01JX8K3M9DEVOLUCAO00000000", "status": "label_generated" },
"shipment": {
"id": 9921,
"id": "01HM1Z3...",
"tracking_code": null,
"status": "pending"
}
}
}Modo manual:
{
"method": "manual",
"notes": "Cliente vai trazer pessoalmente sexta-feira à tarde."
}Em manual não há shipment; a resposta traz só o order_return atualizado.
5. Confirmar recebimento
POST/api/v1/sellers/orders/returns/{id}/mark-received
O destino da coleta reversa é o endereço da loja (quem recebe o pacote fisicamente é você). Quando o produto chegar, confirme o recebimento: a devolução vira received e passa a ser seu o ponto de decisão do desfecho (solicitar estorno ou encerrar sem estorno).
Disponível a partir de label_generated ou return_in_progress, sem corpo na requisição. Na coleta manual não existe rastreio nenhum, então esta confirmação é a única forma de a devolução avançar: sem ela o caso fica parado e o cliente sem resposta.
POST /api/v1/sellers/orders/returns/01JX8K3M9DEVOLUCAO00000000/mark-received6. Ações possíveis (workflow dirigido pela API)
GET/api/v1/sellers/orders/returns/{id}/possible-actions
Em vez de replicar a máquina de estados no seu sistema, pergunte à API o que pode ser feito agora. A resposta lista as ações válidas para o status atual (approve/reject em forwarded_to_seller, generate_reverse_label em approved, mark_received em label_generated/return_in_progress, request_refund/close_without_refund em received), cada uma com endpoint, method e os campos esperados em requires_input. is_terminal=true indica que a devolução encerrou e não há mais nada a fazer.
Em received, as ações de desfecho aparecem aqui: request_refund (cria a solicitação de estorno) e close_without_refund (encerra resolvida por fora, com notes obrigatório). A execução do estorno segue no financeiro da plataforma; acompanhe pelos campos status, resolution e pelo bloco refund.
Cenários comuns
"Recebi devolução por defeito de fabricação, vou aprovar e gerar coleta"
POST /api/v1/sellers/orders/returns/01JX8K3M9DEVOLUCAO00000000/approve
{ "seller_notes": "Defeito visível nas fotos. Reembolso autorizado." }GET /api/v1/sellers/orders/returns/01JX8K3M9DEVOLUCAO00000000/reverse/eligible-carriersEscolha um carrier baseado em estimated_freight e prazo, depois:
POST /api/v1/sellers/orders/returns/01JX8K3M9DEVOLUCAO00000000/reverse/generate
{ "method": "carrier", "carrier_id": 7, "freight_cost": 18.90 }"Vou recusar, cliente está fora do prazo legal de 7 dias"
POST /api/v1/sellers/orders/returns/01JX8K3M9DEVOLUCAO00000000/reject
{
"reason": "O prazo legal de 7 dias para devolução sem motivo (Art. 49 CDC) já expirou. Recebimento confirmado em 12/03; solicitação aberta em 28/03."
}"Cliente mora numa cidade que nenhum carrier atende"
GET /reverse/eligible-carriers retorna has_coverage=false. Resolva manualmente:
POST /api/v1/sellers/orders/returns/01JX8K3M9DEVOLUCAO00000000/reverse/generate
{
"method": "manual",
"notes": "Sem cobertura de carrier. Combinado com cliente: motoboy contratado pela loja vai retirar dia 29/04."
}"A coleta era manual e o produto chegou na loja"
POST /api/v1/sellers/orders/returns/01JX8K3M9DEVOLUCAO00000000/mark-receivedA devolução vira received e passa a ser sua a decisão do desfecho. Sem essa confirmação, a devolução em coleta manual não avança.
"O produto voltou e conferi o defeito. Vou autorizar o estorno"
POST /api/v1/sellers/orders/returns/01JX8K3M9DEVOLUCAO00000000/request-refundSem corpo. A devolução vira refunded, a solicitação de estorno (valor dos itens devolvidos) vai para o financeiro processar, e o caso fecha em closed quando o estorno concluir. Acompanhe pelo bloco refund do detalhe.
"Reenviei outro produto ao cliente. Não quero estornar"
POST /api/v1/sellers/orders/returns/01JX8K3M9DEVOLUCAO00000000/close-without-refund
{ "notes": "Reenviei um produto novo via transportadora própria. Acordo com o cliente em 28/04." }Encerra sem movimentar pagamento: closed com resolution=resolved_externally e a justificativa em resolution_notes.
"Cliente acha que vai dar tudo certo mas quero ver o histórico"
GET /api/v1/sellers/orders/returns?order_id=01JX8K3M9PEDIDO000000000ABDevolve todas as devoluções do pedido 01JX8K3M9PEDIDO000000000AB, em qualquer status.
"Quero ver minhas devoluções recusadas no último mês"
GET /api/v1/sellers/orders/returns?status=rejected&date_from=2026-04-01&date_to=2026-04-30Reembolsos
A partir de received, você decide o desfecho: POST /request-refund cria a solicitação de estorno, ou POST /close-without-refund encerra sem estorno (resolvido por fora). Quem executa o estorno (o pagamento em si, com conciliação de pagamento e regras de repasse) é o financeiro da plataforma: você toma a decisão, a plataforma processa. Isso mantém o dinheiro do cliente sob um único passo controlado, que só liquida depois que o produto voltou. Acompanhe pelos campos status, resolution e pelo bloco refund da devolução.
Pela ótica do seller, o ciclo final é:
| Status | O que significa para o reembolso |
|---|---|
received | Produto chegou de volta à loja. É onde você decide o desfecho (/request-refund ou /close-without-refund). |
refunded | Solicitação de estorno criada. O financeiro da plataforma está processando. O valor corresponde aos itens devolvidos (devolução parcial estorna só a parte devolvida). |
closed + resolution=refunded | Estorno concluído. O valor (e eventuais descontos de frete reverso) entra no seu extrato/repasse. |
closed + resolution=resolved_externally | Encerrada sem estorno: o caso foi resolvido fora da plataforma (ex.: você reenviou o produto direto ao cliente). A justificativa fica em resolution_notes. |
Pontos a ter em mente:
- Você inicia o estorno, mas não o cancela pela API. A solicitação parte de você (
/request-refund); depois de criada, cancelar ou ajustar o valor é com a operação/suporte da plataforma. Casos excepcionais (divergência de valor) também são tratados pela operação e refletem na devolução viaresolution. - O frete reverso pode impactar o repasse. O
freight_costinformado na geração da coleta é o valor que entra no acerto financeiro daquela devolução. - Aprovar a devolução não é o mesmo que reembolsar. Aprovar (
/approve) autoriza a volta do produto; o desfecho financeiro só é decidido no fim do trilho, após o recebimento. - Devoluções parciais podem coexistir. O cliente pode abrir outra devolução para o restante dos itens mesmo com uma em andamento; o limite é o saldo devolvível de cada item, que já desconta as devoluções ativas. Detalhes e exemplos em Devoluções: Resolução.
Cuidados
reject.reason é visto pelo cliente. Escreva como se fosse uma resposta no SAC: profissional, clara, sem jargão interno. Para anotações internas use approve.seller_notes (que não é visto pelo cliente).
Coleta reversa só depois de approved. Tentar gerar coleta antes de aprovar retorna 422 com A devolução precisa estar aprovada para gerar a coleta reversa.. O fluxo é: forwarded_to_seller → approve (vira approved) → reverse/generate.
freight_cost é o valor real (não estimativa). Use o estimated_freight como base, mas se você negociou um valor diferente com o carrier, mande o valor negociado. Esse é o número que entra no extrato/repasse.
pickup_address é montado a partir do snapshot do pedido. Você não precisa enviar; ele vem do endereço que estava no pedido original. Se for diferente (cliente mudou), edite no shipment via operação depois de gerar.
Aprovar é um caminho só de ida. Não há "des-aprovar". A razão é que, assim que você aprova, o cliente já é avisado e a coleta reversa passa a poder ser gerada; voltar atrás depois disso confundiria o cliente e a logística. Por isso, uma vez approved, a devolução segue o trilho da coleta reversa. Se aprovou por engano, não é algo que você reverte pela API. É caso de operação (contate o suporte).
Datas inválidas em date_from/date_to são ignoradas silenciosamente. Não há erro; o filtro simplesmente não é aplicado. Se a busca não está filtrando, cheque o formato (ISO 8601).

