docs
Webhooks

CashInReversal

Visão Geral

O evento CashInReversal é enviado quando um PIX recebido anteriormente é estornado, devolvendo o valor ao pagador original. Normalmente ocorre quando você chama a API de Refund-In (POST /api/pix/refund-in/:id), mas também pode ocorrer quando a devolução é iniciada pelo PSP, como na devolução de um MED.

O movementType para CashInReversal é DEBIT, pois você está devolvendo dinheiro que havia entrado na sua conta.

CampoValor
eventCashInReversal
movementTypeDEBIT
SignificadoVocê devolveu dinheiro que havia recebido

Payload Completo

{
  "event": "CashInReversal",
  "status": "CONFIRMED",
  "transactionType": "PIX",
  "movementType": "DEBIT",
  "transactionId": "11111",
  "externalId": "refund-678689ca-3e16-4f5e-a08f-09a984a97781",
  "endToEndId": "D07136847202512112011O5222ZRBI5A",
  "pixKey": null,
  "feeAmount": 0.01,
  "originalAmount": 0.3,
  "finalAmount": 0.31,
  "mismatchAmount": null,
  "processingDate": "2025-12-11T20:11:13.289Z",
  "errorCode": null,
  "errorMessage": null,
  "providerId": "r1e2f3u4n5",
  "metadata": {},
  "parentTransaction": {
    "transactionId": "12345",
    "externalId": "PIX-5482123298-EJUYFSMU1UU",
    "endToEndId": "E00416968202512111942rjzxxzSSTD9",
    "processingDate": "2025-12-11T19:42:04.080Z",
    "wasTotalRefunded": false,
    "remainingAmountForRefund": 0.2,
    "providerId": "a1b2c3d4e5",
    "metadata": {},
    "counterpart": {
      "name": "Carlos Oliveira",
      "document": "*.345.678-**",
      "bank": {
        "bankISPB": null,
        "bankName": null,
        "bankCode": null,
        "accountBranch": null,
        "accountNumber": null
      }
    }
  }
}

Campos Específicos do CashInReversal

O CashInReversal inclui o objeto parentTransaction com dados da transação original que está sendo estornada.

parentTransaction

parentTransactionobjectobrigatorio

Dados da transação PIX In original que está sendo estornada.

parentTransaction.transactionIdstring

ID numérico da transação PIX In original (retornado como string).

parentTransaction.externalIdstring | null

ID externo da transação original.

parentTransaction.endToEndIdstring | null

ID End-to-End da transação original.

parentTransaction.processingDatestring

Data de criação da transação original (ISO 8601 UTC).

parentTransaction.wasTotalRefundedboolean

Indica se o valor total da transação original foi estornado.

  • true: Estorno total (não pode estornar mais)
  • false: Estorno parcial (ainda pode estornar o restante)
parentTransaction.remainingAmountForRefundnumber

Valor restante que ainda pode ser estornado (em reais).

Exemplo: 0.2 (ainda pode estornar R$ 0,20)

parentTransaction.providerIdstring | null

Identificador da transação original no PSP. null se ausente.

parentTransaction.metadataobject

metadata da transação original.

parentTransaction.counterpartobject

Dados do pagador original que receberá o estorno (mesma estrutura do counterpart do CashIn).


Estorno Total vs Parcial

Estorno Total

Quando você devolve 100% do valor recebido:

{
  "parentTransaction": {
    "wasTotalRefunded": true,
    "remainingAmountForRefund": 0
  }
}

Estorno Parcial

Quando você devolve apenas parte do valor:

{
  "parentTransaction": {
    "wasTotalRefunded": false,
    "remainingAmountForRefund": 0.2
  }
}

Você pode fazer múltiplos estornos parciais até que wasTotalRefunded seja true.


Casos de Uso

1. Devolução de Pagamento Duplicado

async function handleCashInReversal(payload) {
  const refundId = payload.transactionId;
  const originalOrderId = payload.parentTransaction.externalId;

  await refundService.markAsCompleted({
    refundId,
    originalOrderId,
    amount: payload.originalAmount,
    completedAt: payload.processingDate
  });

  // Notificar cliente sobre a devolução
  await notificationService.sendRefundConfirmation({
    orderId: originalOrderId,
    amount: payload.originalAmount
  });
}

2. Controle de Estornos Parciais

async function handleCashInReversal(payload) {
  const { parentTransaction } = payload;

  await refundService.updateStatus({
    originalTransactionId: parentTransaction.transactionId,
    totalRefunded: parentTransaction.wasTotalRefunded,
    remainingAmount: parentTransaction.remainingAmountForRefund
  });

  if (parentTransaction.wasTotalRefunded) {
    console.log('Transação totalmente estornada');
  } else {
    console.log(`Ainda disponível para estorno: R$ ${parentTransaction.remainingAmountForRefund}`);
  }
}

Fluxo Típico

sequenceDiagram
    participant SeuSistema
    participant FyPay
    participant PagadorOriginal

    Note over SeuSistema,PagadorOriginal: Transação original (CashIn)
    PagadorOriginal->>FyPay: PIX recebido anteriormente
    FyPay->>SeuSistema: Webhook CashIn

    Note over SeuSistema,PagadorOriginal: Estorno (CashInReversal)
    SeuSistema->>FyPay: POST /api/pix/refund-in/:id
    FyPay->>PagadorOriginal: Devolve PIX
    FyPay->>SeuSistema: Webhook CashInReversal
    SeuSistema-->>FyPay: HTTP 2xx

Próximos Passos

Nesta página