Devoluções
Tratamento de devoluções (RMA) encaminhadas ao seller pela plataforma — aprovação, rejeição e geração de coleta reversa — e o acompanhamento do reembolso ao cliente.
Pré-requisitos: leia primeiro Pedidos: visão geral. A devolução é um recurso vinculado a um pedido; ela só existe depois que o cliente solicita devolução de um pedido entregue.
Reembolso é processado pela plataforma, não pelo seller. Não há endpoint de estorno nesta API — o seller acompanha o reembolso pelo status da devolução (
refunded). 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 — "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 (OrderReturnStatusEnum):
| 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:00Z",
"sla_exceeded": false,
"created_at": "2026-04-26T10:15:00Z"
}
]
}
}
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: motivo informado pelo cliente (reason), 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 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": 7, "uid": "01HM0Z6E...", "name": "Correios PAC", "estimated_freight": 18.90 },
{ "id": 9, "uid": "01HM0X1A...", "name": "Loggi Reverso", "estimated_freight": 22.50 }
]
}
}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).
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:00Z",
"pickup_window_to": "2026-04-28T18:00:00Z"
}| 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,
"uid": "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 a plataforma assume a decisão do desfecho (estorno ou encerramento 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), 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.
A decisão de estorno (após received) é exclusiva da plataforma e nunca aparece aqui — acompanhe pelos campos status e resolution.
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 a plataforma decide o desfecho. Sem essa confirmação, a devolução em coleta manual não avança.
"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
Você não vai encontrar um endpoint de estorno nesta API — e isso é de propósito. O reembolso mexe com dinheiro do cliente, conciliação de pagamento e regras de repasse, então a plataforma centraliza esse passo para garantir que o estorno só aconteça quando o produto realmente voltou e o caso fechou. Do seu lado, em vez de "emitir" um reembolso, você acompanha o desfecho pelos campos status e resolution da devolução.
Pela ótica do seller, o ciclo final é:
| Status | O que significa para o reembolso |
|---|---|
received | Produto chegou de volta à loja. A plataforma decide o desfecho. |
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ê não inicia nem cancela um reembolso pela API. Casos excepcionais (divergência de valor, acordo direto com o cliente) são tratados pela operação/suporte da plataforma — e refletem na devolução via
resolution. - 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 sucessivas são possíveis. Encerrada uma devolução, o cliente pode abrir outra para o restante dos itens — cada uma com seu próprio desfecho. 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).

