Aliquot

Refunds

Refunds pull por meio de um link de resgate privado — por que não são automáticos, como o link chega ao comprador, a taxa de rede e os transfers com token errado.

Última atualização 27 de out. de 2026

Qualquer dinheiro que chega a um endereço de depósito e não é devido ao vendedor fica retido para o comprador em LIABILITY:REFUND_ESCROW:<invoice> e se torna um refund:

reasonQuando
OVERPAYMENTA invoice é paga com mais do que o seu total: o excedente (invoice OVERPAID).
EXPIRED_UNDERPAIDUm pagamento parcial quando a invoice expira (invoice EXPIRED_UNDERPAID, depois REFUNDED quando é devolvido).
LATE_PAYMENTUm transfer confirmado depois que a invoice expirou, foi liquidada ou anulada.
WRONG_TOKENOutro token canônico da mesma rede enviado ao endereço (USDC para uma invoice em USDT).

Pull, não push

Os refunds nunca são devolvidos automaticamente ao endereço que pagou. Esse endereço costuma ser a hot wallet de uma exchange ou um contrato que não consegue receber (nem creditar) o dinheiro. Em vez disso, o comprador resgata o refund: ele abre um link privado, cola uma wallet que controla na rede do pagamento, e o worker envia o valor para lá.

<CRYPTO_CHECKOUT_BASE_URL>/pay/<invoice id>/refund/<claim token>. O token (256 bits) é a única credencial do comprador, por isso é mantido fora de todo lugar por onde o id da invoice circula:

  • O checkout público (GET /api/v1/public/pay/:id, a página /pay/:id) mostra que há um refund retido, de quanto, o seu status e de onde vem o link — refund.delivery é email ou seller — mas nunca o link.
  • Com buyer_email na invoice, o comprador recebe o link por email quando o refund se torna resgatável (delivery: "email").
  • Caso contrário, o vendedor o encaminha (delivery: "seller"). O merchant o lê em GET /api/v1/crypto/invoices/:id (refunds[].claim_url), GET /api/v1/crypto/refunds, no webhook refund.claimable (que também traz buyer_email) ou no botão Copy claim link do dashboard. A visualização da resposta bruta no dashboard o oculta.

Os endpoints públicos de refund são identificados apenas pelo claim token: GET /api/v1/public/refunds/:claimToken e POST /api/v1/public/refunds/:claimToken/claim.

Resgatando

POST …/claim { "destination_address": "0x…" } verifica o endereço (válido, checksum EIP-55 quando há maiúsculas e minúsculas, não é um dos endereços do próprio gateway, não é um contrato — um contrato responde 422), fixa a taxa de rede e o valor líquido, e move o refund CLAIMABLE → PROCESSING (202). Resgatar de novo para o mesmo endereço é idempotente.

A taxa de rede é o custo de enviar o refund, cobrado do próprio refund: gas estimado × max fee per gas × CRYPTO_NATIVE_PRICE_USD_<FAMILY> (Polygon 0.50, BSC 600, Base 3000 por padrão), no mínimo 0.01, lançada como REVENUE:REFUND_NETWORK_FEE. O portal mostra o valor retido, a taxa e o "você recebe" antes de o comprador confirmar. Quando a taxa consumiria todo o refund (poeira), o resgate é recusado com 422.

O worker só envia um refund depois que todos os transfers daquela invoice e daquele token passaram pelo sweep e o sweep está confirmado, e então o marca como COMPLETED ao atingir o limiar de confirmações da rede (webhook refund.completed). Uma invoice EXPIRED_UNDERPAID se torna REFUNDED.

Token errado

Um transfer de outro token canônico nunca detecta, paga nem liquida a invoice. Uma vez confirmado, ele fica em escrow no seu próprio token (REFUND_ESCROW:<invoice>:<network>:<token>) com um refund WRONG_TOKEN pago de volta nesse token, qualquer que seja o status da invoice. Nada é creditado a nenhum vendedor nesse token. Os sweeps rodam por invoice × token, então o refund espera apenas o sweep do seu próprio token. Tokens que não estão no registry não são monitorados.

[!NOTE] Um refund que falha on chain se torna FAILED e o seu escrow continua devido. Ainda não há botão de retry; é preciso um operador.

Nesta página