docs

Refunds

Reembolso iniciado por você — janelas e tempos de liquidação por método. Hoje single-shot por PaymentIntent.

Refund é o reembolso iniciado por você (merchant). Diferente de chargeback (iniciado pelo emissor), o refund preserva sua reputação com a bandeira e não conta no chargeback ratio.

Criar refund

const refund = await zhex.refunds.create({
  payment_intent: 'pi_3MtwBwLkdI',
  // omita amount para refund total
  reason: 'requested_by_customer',
});
// refund.id → "re_…", refund.status → "succeeded" | "failed"

Sem amount, devolve o valor total da transação (incluindo eventuais ajustes de cupom).

Refund parcial

await zhex.refunds.create({
  payment_intent: 'pi_3MtwBwLkdI',
  amount: 1000,                       // R$ 10,00 dos R$ 49,90 originais
  reason: 'product_unsatisfactory',
});

Single-shot por PaymentIntent — hoje

Cada PaymentIntent aceita um único refund (total ou parcial em valor único). Múltiplos refunds parciais sequenciais sobre o mesmo pi_* são roadmap — quando entrar, o Refund ganha tabela própria e cada chamada gera uma row distinta. Hoje, se você precisa devolver R$ 10 + R$ 30 separadamente, faça uma chamada de R$ 40.

Resposta

{
  "id": "re_3MtwBwLkdIwHu7ix28a3tqPa",
  "object": "refund",
  "livemode": false,
  "amount": 4990,
  "currency": "brl",
  "payment_intent": "pi_3MtwBwLkdIwHu7ix28a3tqPa",
  "charge": "ch_acquirer_…",
  "reason": "requested_by_customer",
  "status": "succeeded",
  "created": 1714060500
}

O id do refund (re_*) é derivado 1:1 do PaymentIntent (pi_*re_*) — útil em logs e correlação.

Janelas e liquidação

MétodoJanela máximaLiquidaçãoComo reverte
PIX90 dias< 1hBACEN MED
PIX Automático90 dias< 1hBACEN MED
Boleto60 diasD+5TED reverso
Cartão BR180 diasD+30Estorno bandeira
Cartão internacional120 dias (Visa) / 180 dias (Master)D+30Estorno bandeira

Janela é contada a partir do momento de liquidação da cobrança original. Após esse prazo, refund via API é rejeitado — alternativa é TED manual (suporte).

Razões (reason)

type RefundReason =
  | 'duplicate'                  // cobrança duplicada
  | 'fraudulent'                 // você identificou fraude
  | 'requested_by_customer'      // cliente pediu
  | 'product_unsatisfactory'     // qualidade abaixo
  | 'service_not_received'       // não entregou
  | 'expired_uncaptured_charge'  // pré-auth expirou
  | 'general';                   // catch-all

reason: 'fraudulent' abre flag interna na sua conta — use só quando tiver certeza. Erro repetido aqui aumenta scoring de risco.

Status do refund

type RefundStatus = 'pending' | 'succeeded' | 'failed' | 'canceled';

Em PIX/cartão BR, o status sai direto em succeeded ou failed na criação. Em cartão internacional, pode entrar pending por alguns segundos enquanto o adquirente confirma.

Listar refunds

// todos os refunds
for await (const r of zhex.refunds.list({ limit: 100 }).autoPagingEach()) {
  /* … */
}

// refund de um PaymentIntent específico
const refunds = await zhex.refunds.list({
  payment_intent: 'pi_…',
  limit: 100,
});

Idempotência

Sempre use Idempotency-Key no refund — retry de network não duplica:

await zhex.refunds.create(
  { payment_intent: 'pi_…' },
  { idempotencyKey: `refund:${orderId}` },
);

Se você não passar, o SDK gera UUIDv4 automaticamente.

Boas práticas

  • Refund parcial em assinatura: não cancela a CustomerSubscription. Para cancelar, use customer_subscriptions.cancel separadamente.
  • Refund de parcelado: a Zhex devolve o total ao cliente; o emissor cancela as parcelas restantes. Você recebe o estorno em D+30 do liquidação original.
  • Refund proativo > chargeback. Se cliente reclamou e você sabe que tem razão, refunde antes que ele abra disputa — chargeback custa valor + taxa + ratio.
  • Comunicação com cliente: envie email transacional confirmando o estorno. Reduz suporte e mostra atenção.
Esta página foi útil?

Atualizado em

Nesta página