Pular para o conteúdo

Estados da transação

Uma transação da Lootfy percorre dois caminhos independentes: o do pagamento — o comprador pagou? — e o da entrega — o servidor entregou o item? Desde 2026-09-09 esses dois caminhos são campos separados, e não um único status. Entender por que são dois é entender o desenho inteiro: pagar e entregar são responsabilidades de atores diferentes (o comprador e o PSP de um lado, o servidor do outro), acontecem em momentos diferentes e podem falhar por motivos diferentes. Um valor único misturaria os três eixos e apagaria estado — foi exatamente o que motivou a separação.

Para o dono de servidor: pense em dois semáforos, não um. O primeiro diz se o dinheiro chegou; o segundo, se o item saiu. Uma venda só está de fato concluída quando os dois estão no verde e o relógio de liberação marcou.

Uma transação carrega dois enums e um timestamp:

  • paymentStatus — onde está o pagamento.
  • deliveryStatus — onde está a entrega. É null enquanto o pagamento não foi confirmado: antes de pagar não há o que entregar.
  • completedAt — o timestamp de liberação (ISO-8601 UTC), ou null. É o terceiro eixo, o que distingue “item entregue” de “venda liberada”.

O antigo valor CONCLUIDA deixou de existir como estado. Ele agora é uma conjunção que o cliente deriva:

CONCLUIDA ≡ deliveryStatus === 'ENTREGUE' && completedAt != null
ValorSignificado
AGUARDANDOTransação criada, o comprador ainda não pagou. É onde ela nasce.
PENDENTEA cobrança Pix foi emitida; aguardando a confirmação do pagamento.
PAGOPagamento confirmado. A partir daqui existe entrega — deliveryStatus deixa de ser null.
EXPIRADOO prazo do pedido venceu sem pagamento.
CANCELADOA transação foi cancelada.
ESTORNADOO valor pago foi devolvido ao comprador.
ValorSignificado
nullAinda não há entrega — o pagamento não foi confirmado.
AGUARDANDO_SERVIDORPago; a Lootfy aguarda o servidor transferir o item.
ENTREGUEO servidor confirmou a entrega (POST /v1/api/transactions/{transactionId}/delivery). Com completedAt preenchido, é a venda CONCLUIDA.
FALHOUO servidor reportou que não conseguiu entregar. OUT_OF_STOCK no reporte de falha de entrega (POST /v1/api/transactions/{transactionId}/delivery-failure) leva a este estado e dispara estorno.
EM_DISPUTAA entrega não resolveu no prazo e caiu em disputa. Ver a nota abaixo.

No eixo do pagamento, o caminho feliz é AGUARDANDO → PENDENTE → PAGO: a transação nasce em AGUARDANDO, vai a PENDENTE quando a cobrança Pix é emitida no checkout e a PAGO quando o provedor de pagamento confirma. Fora do caminho feliz, de AGUARDANDO ela pode ir a EXPIRADO (prazo vencido) ou CANCELADO; e de PAGO pode ir a ESTORNADO quando o valor é devolvido.

No eixo da entrega, tudo começa quando o pagamento é confirmado: no PAGO, o deliveryStatus sai de null para AGUARDANDO_SERVIDOR. Dali, o servidor confirma a entrega e vai a ENTREGUE, ou reporta falha de entrega. A falha tem dois sabores e eles decidem o rumo: OUT_OF_STOCK leva a FALHOU e estorna a transação; TEMPORARY mantém em AGUARDANDO_SERVIDOR e devolve a ordem para a fila, para nova tentativa. O EM_DISPUTA é o destino previsto de uma entrega que não resolve — hoje só alcançável por resolução manual, não por timeout.

Quando a entrega chega a ENTREGUE e o timestamp de liberação é gravado, a venda é CONCLUIDA. Todo estado terminal — CONCLUIDA, ESTORNADA, EXPIRADA, CANCELADA — dispara o webhook de estado terminal (evento transaction_terminal), para o servidor destravar o item; o parceiro deriva o terminal do par paymentStatus + deliveryStatus, não de um campo status (que não existe mais).

Do lado da integração, você acompanha os dois eixos por duas vias: o webhook transaction_terminal, que a plataforma dispara quando a transação chega a um desfecho, e a consulta GET /v1/api/transactions/{transactionId}, que devolve o par paymentStatus + deliveryStatus a qualquer momento. O comprador vê os mesmos estados no checkout web, mas isso é da tela da Lootfy — não é uma superfície que o seu servidor lê.