Transfer Bank Reversal

Webhook sent when a previously successful SNAP disbursement is reversed

Webhook: transfer.bank.reversal

This is a server-to-server callback (webhook) sent by Durianpay to your system when a SNAP disbursement that was previously reported as successful is later reversed. You do not need to poll or request status from our API. Configure your webhook listener endpoint and Durianpay will push the reversal directly to your server via POST request. It can be configured via menu Settings - Webhook.

This is the only event that lets you distinguish a reversal from an ordinary failed transfer. If you have not subscribed to it, reversals are still delivered through Transfer Bank Notify as 06 / failed. See Fallback Without This Webhook.


Webhook Specifications

  • Method: POST
  • Content-Type: application/json
  • Retries: 2, 5, 10, 90, 210 minutes after the initial attempt if no 200 OK is received
  • Configuration: Set your webhook URL in Dashboard > Settings > Webhook and subscribe to the transfer.bank.reversal event
  • Availability: SNAP Disbursement API only, production only

Subscribed Event

Event NameDescription
transfer.bank.reversalSent when a previously successful disbursement is reversed

Reversal Behaviour

  • The disbursement status becomes failed. This is the status shown on the Dashboard and returned by status inquiry.
  • The full reversed amount, including the disbursement fee, is credited back to your Durianpay balance.
  • A reversal can arrive up to 9 working days after the original success. In most cases it is processed on D+1.
  • A reversal is final and cannot be undone. To pay the beneficiary again, submit a new disbursement.
❗️

A reversal is reported at two levels

The disbursement status becomes failed, while latestTransactionStatus in this webhook is 04 / Refunded.

Use latestTransactionStatus 04 to identify a reversal. The disbursement status itself will never read Refunded.


Field Definition

FieldTypeDescription
originalPartnerReferenceNostringReference you sent when submitting the original bank / e-wallet transfer request
originalReferenceNostringDurianpay's reference returned when submitting the original transfer request (dis_item_xxx)
latestTransactionStatusstring(2)Current transaction status. Always 04 for this event
transactionStatusDescstringDescription of the current transaction status. Always Refunded for this event
amount.valuestringString representing value of the transaction: "20000.00"
amount.currencystringCurrency of the transaction: "IDR"
beneficiaryAccountNostringThe account number of the recipient
beneficiaryAccountNamestringThe account holder name of the recipient
beneficiaryBankCodestringThe bank code of the recipient account
additionalInfo.failureReasonstringReason for the reversal, for example "Reversal Transaction"
🚧

Payload structure differs from Transfer Bank Notify

latestTransactionStatus and transactionStatusDesc are at the top level of this payload, not nested inside additionalInfo as in transfer-bank.notify. This payload also does not include responseCode, responseMessage, or sourceAccountNo.

If you route both events to one handler, parse the two payloads separately.


Webhook Payload Example

{
  "originalPartnerReferenceNo": "1000-1000-1000-1180",
  "originalReferenceNo": "dis_item_Jl2HIglkQN4340",
  "latestTransactionStatus": "04",
  "transactionStatusDesc": "Refunded",
  "amount": {
    "value": "10000.00",
    "currency": "IDR"
  },
  "beneficiaryAccountNo": "3370018285",
  "beneficiaryAccountName": "John Doe",
  "beneficiaryBankCode": "014",
  "additionalInfo": {
    "failureReason": "Reversal Transaction"
  }
}

📘 Status Handling

Inspect latestTransactionStatus at the top level of the payload:

"latestTransactionStatus": "04",
"transactionStatusDesc": "Refunded"
latestTransactionStatustransactionStatusDescDisbursement statusMeaning
00donesuccessTransaction successful
03PendingprocessingTransaction is still being processed
04RefundedfailedTransaction was previously successful and is now reversed
06failedfailedTransaction failed

Handling steps:

  1. Verify the digital signature before processing the payload.
  2. Look up the original transaction using originalReferenceNo or originalPartnerReferenceNo.
  3. Mark the transaction as reversed (a failed disbursement with a reversal reason) and adjust your settlement, ledger, or finance records.
  4. Make processing idempotent. The event may be retried, so guard against applying the same reversal twice.
  5. Respond with HTTP 200 OK.

✅ Action Required:
Always respond with HTTP 200 OK to acknowledge receipt of the webhook. If not acknowledged, Durianpay will retry based on this schedule: 2, 5, 10, 90, 210 minutes.


Fallback Without This Webhook

If you have not subscribed to transfer.bank.reversal, the reversal is delivered through transfer-bank.notify with additionalInfo.latestTransactionStatus 06 / failed. This is indistinguishable from a transfer that failed outright, and no reversal reason is provided.

Your transfer-bank.notify handler must therefore accept a transition from 00 / done to 06 / failed for the same originalReferenceNo, not only from pending to failed. A handler that ignores notifications for transactions already recorded as successful will miss reversals and drift from your Durianpay balance.


🔐 Digital Signature Verification

Durianpay signs every webhook to ensure integrity and authenticity. You must validate the signature before processing. The scheme is identical to transfer-bank.notify.

Webhook Headers:

HeaderDescription
X-SIGNATUREBase64-encoded RSA-2048 signature (SHA-256)
X-TIMESTAMPTimestamp used to sign the payload

Signature Format:

POST:<relative path>:<lowercase hex sha256 of minified JSON body>:<X-TIMESTAMP>

Use Durianpay's public key (Live/Sandbox-specific) to verify the signature. A complete Go implementation is available on Transfer Bank Notify and applies unchanged to this event.


Related