Skip to main content
Webhooks are event-based notifications that you receive when a specific event related to a wallet transfer occurs.
In rare cases, such as network retries, read timeouts, processing delays, or delivery failures, Cashfree may send the same webhook more than once for the same event. To prevent unintended side effects, implement idempotency (ensuring a duplicate webhook produces the same result as processing it once) in your webhook handler to handle duplicate deliveries.

Webhook signature

Cashfree includes the webhook signature in the request header. The following is a sample header from a webhook request.
Header nameHeader value
content-length1099
x-webhook-attempt1
content-typeapplication/json
x-webhook-signature07r5C3VMwsGYeldGOCYxe5zoHhIN1zLfa8O0U/yngHI=
x-webhook-timestamp1746427759733
x-webhook-version2025-01-01
Always capture the webhook payload in its raw text format before parsing into JSON. Parsing and re-serialising the payload can change the structure (for example, array ordering, spacing, or null handling) and cause a signature mismatch during verification. Use the exact raw body string from the request when computing the signature.
Verifying the signature is mandatory before processing any webhook. Refer to Signature Verification for more details.

Transfer webhook events

Cashfree triggers the following events at different stages of a wallet transfer:
EventDescription
PPI_TRANSFER_SUCCESSThe transfer is successfully credited to the beneficiary’s account.
PPI_TRANSFER_FAILEDThe transfer cannot be processed due to an error or rejection by the bank.
PPI_TRANSFER_REVERSEDThe beneficiary bank returns the transfer after initial processing.
PPI_TRANSFER_REJECTEDCashfree rejects the transfer before it reaches the bank due to a validation failure.
The following examples show the webhook payload for each event type.
{
  "event_type": "PPI_TRANSFER_SUCCESS",
  "event_time": "2026-05-18T10:00:45Z",
  "data": {
    "user_id": "usr_001",
    "wallet_id": "wlt_001",
    "cf_transfer_id": "1003",
    "transfer_id": "txn_ext_003",
    "amount": 500.00,
    "transfer_mode": "IMPS",
    "actual_mode": "IMPS",
    "sub_wallet": {
      "cf_sub_wallet_id": "swlt_001",
      "name": "Primary Wallet",
      "type": "PRIMARY",
      "status": "ACTIVE",
      "balance": 4500.00,
      "available_balance": 4500.00,
      "funds_on_hold": 0.00
    },
    "status": "SUCCESS",
    "status_code": "ACKNOWLEDGED_VIA_BENE_BANK",
    "bank_reference_number": "BNKREF789012",
    "bene_details": {
      "bene_id": "bene_001",
      "bene_instrument_id": "instr_001"
    },
    "purpose": "salary",
    "remarks": "Monthly salary",
    "initiated_at": "2026-05-18T10:00:00Z",
    "processed_at": "2026-05-18T10:00:45Z",
    "notes": null
  }
}
{
  "event_type": "PPI_TRANSFER_FAILED",
  "event_time": "2026-05-18T10:00:01Z",
  "data": {
    "user_id": "usr_001",
    "wallet_id": "wlt_001",
    "cf_transfer_id": "1004",
    "transfer_id": "txn_ext_004",
    "amount": 500.00,
    "transfer_mode": "IMPS",
    "actual_mode": null,
    "sub_wallet": {
      "cf_sub_wallet_id": "swlt_001",
      "name": "Primary Wallet",
      "type": "PRIMARY",
      "status": "ACTIVE",
      "balance": 5000.00,
      "available_balance": 5000.00,
      "funds_on_hold": 0.00
    },
    "status": "FAILED",
    "status_code": "INSUFFICIENT_BALANCE",
    "bank_reference_number": null,
    "bene_details": {
      "bene_id": "bene_001",
      "bene_instrument_id": "instr_001"
    },
    "purpose": "salary",
    "remarks": "Monthly salary",
    "initiated_at": "2026-05-18T10:00:00Z",
    "processed_at": "2026-05-18T10:00:01Z",
    "notes": null
  }
}
{
  "event_type": "PPI_TRANSFER_REVERSED",
  "event_time": "2026-05-18T10:05:00Z",
  "data": {
    "user_id": "usr_001",
    "wallet_id": "wlt_001",
    "cf_transfer_id": "1005",
    "transfer_id": "txn_ext_005",
    "amount": 500.00,
    "transfer_mode": "IMPS",
    "actual_mode": "IMPS",
    "sub_wallet": {
      "cf_sub_wallet_id": "swlt_001",
      "name": "Primary Wallet",
      "type": "PRIMARY",
      "status": "ACTIVE",
      "balance": 5000.00,
      "available_balance": 5000.00,
      "funds_on_hold": 0.00
    },
    "status": "REVERSED",
    "status_code": "RETURNED_FROM_BENE",
    "bank_reference_number": "BNKREF_REV001",
    "bene_details": {
      "bene_id": "bene_001",
      "bene_instrument_id": "instr_001"
    },
    "purpose": "salary",
    "remarks": "Monthly salary",
    "initiated_at": "2026-05-18T10:00:00Z",
    "processed_at": "2026-05-18T10:05:00Z",
    "notes": null
  }
}
{
  "event_type": "PPI_TRANSFER_REJECTED",
  "event_time": "2026-05-18T10:00:01Z",
  "data": {
    "user_id": "usr_001",
    "wallet_id": "wlt_001",
    "cf_transfer_id": "1006",
    "transfer_id": "txn_ext_006",
    "amount": 500.00,
    "transfer_mode": "IMPS",
    "actual_mode": null,
    "sub_wallet": {
      "cf_sub_wallet_id": "swlt_001",
      "name": "Primary Wallet",
      "type": "PRIMARY",
      "status": "ACTIVE",
      "balance": 5000.00,
      "available_balance": 5000.00,
      "funds_on_hold": 0.00
    },
    "status": "REJECTED",
    "status_code": "BENE_BLACKLISTED",
    "bank_reference_number": null,
    "bene_details": {
      "bene_id": "bene_001",
      "bene_instrument_id": "instr_001"
    },
    "purpose": "salary",
    "remarks": "Monthly salary",
    "initiated_at": "2026-05-18T10:00:00Z",
    "processed_at": "2026-05-18T10:00:01Z",
    "notes": null
  }
}

Transfer webhook payload fields

The webhook payload contains important metadata in its top-level fields.
FieldTypeDescription
event_typestringType of transfer event: PPI_TRANSFER_SUCCESS, PPI_TRANSFER_FAILED, PPI_TRANSFER_REVERSED, or PPI_TRANSFER_REJECTED
event_timestringThe UTC timestamp when the event occurred, in ISO 8601 format
dataobjectTransfer-specific event details

Transfer data fields

Transfer webhook events contain the following fields inside data:
FieldTypeDescription
user_idstringIdentifier of the user who initiated the transfer
wallet_idstringIdentifier of the wallet from which the transfer was made
transfer_idstringYour unique identifier for the transfer transaction
cf_transfer_idstringCashfree’s unique identifier for the transfer transaction
amountnumberTransfer amount in INR
transfer_modestringTransfer mode requested: RTGS, NEFT, IMPS, or UPI
actual_modestringTransfer mode actually used to process the transaction. Set only when the transfer reaches the bank (SUCCESS or REVERSED); null otherwise
sub_walletobjectDetails of the sub-wallet from which funds were transferred
sub_wallet.cf_sub_wallet_idstringCashfree’s unique identifier for the sub-wallet
sub_wallet.namestringName of the sub-wallet
sub_wallet.typestringType of the sub-wallet (for example, PRIMARY, FULL_KYC_PPI, GIFT_PPI)
sub_wallet.statusstringCurrent status of the sub-wallet (for example, ACTIVE, SUSPENDED)
sub_wallet.balancenumberTotal balance in the sub-wallet in INR
sub_wallet.available_balancenumberBalance available for new transfers after accounting for funds on hold, in INR
sub_wallet.funds_on_holdnumberAmount reserved for in-flight transfers not yet settled, in INR
statusstringCurrent status of the transfer: SUCCESS, FAILED, REVERSED, or REJECTED
status_codestringGranular status code for the transfer (for example, ACKNOWLEDGED_VIA_BENE_BANK, INSUFFICIENT_BALANCE, RETURNED_FROM_BENE, BENE_BLACKLISTED)
bank_reference_numberstringBank reference number for the transaction. Set only when the transfer reaches the bank (SUCCESS or REVERSED); null otherwise
bene_detailsobjectBeneficiary details for the transfer
bene_details.bene_idstringYour unique identifier for the beneficiary
bene_details.bene_instrument_idstringYour unique identifier for the beneficiary instrument
purposestringPurpose of the transfer
remarksstringAdditional remarks for the transfer
notesobject | nullCustom key-value pairs provided during transfer creation. Returns null if no notes were set.
initiated_atstringTimestamp when the transfer was initiated
processed_atstringTimestamp when the transfer reached a terminal state