Adyen-for-platform icon

Refund with split instructions

Split a refund between the balance accounts in your platform.

You can always be in control of funds movements in your platform if you provide split instructions in your refund requests, and you can support different refund scenarios, such as partial and multiple partial refunds.

You can split a refund into:

  • The sale amount that is refunded
  • Your platform's commission that is now refunded
  • The transaction fees incurred by the refund

Requirements

In addition to the general requirements for in-person payments with an Adyen for Platforms integration, take into account the following information.

Requirement Description
Integration type A Terminal API integration with payment terminals or with a Mobile solution.
The standalone solution does not support adding split instructions to individual referenced refund requests.
Webhooks Listen to the following webhook events:
Limitations Take into account:
  • Some payment methods do not support partial refunds and/or multiple partial refunds. You can check this in the overview of payment methods.
  • Refunds can only be deducted from the balance accounts to which the payment was credited.

Make a partial refund with split instructions

The process is the same as for providing split instructions in a Terminal API payment request:

  • You gather the split instructions and format these either as a JSON object converted to a Base64-encoded string, or as a string of concatenated key-value pairs.
  • Then you pass the resulting string in the SaleToAcquirerData field.

The main difference is that for a refund you need to use a reversal request, not a payment request.

  1. Collect the following information:

  2. Gather the split instructions, taking into account the following:

    • For the split.item[ITEM_NUMBER].reference values in the reversal request, you must use the same reference values as in the payment that you are refunding.
    • The amounts that the refund will be split into will be deducted from the relevant balance accounts.
    • Refunds can only be deducted from the balance accounts to which the payment was credited.
  3. Format the split instructions in one of the following ways:

    • Option 1: as a string of form-encoded key-value pairs (using & as a separator).
    • Option 2: as a JSON object converted to a Base64-encoded string.

    As an example, we issue a partial refund of USD 40.00 for an original split payment of USD 80.00.

    • A refund amount of USD 37.50 is debited from the user's balance account BA00000000000000000000001.
    • A commission of USD 2.50 is debited from your liable balance account.
  4. Make a Terminal API reversal request specifying:

    • The standard SaleToPOIRequest.MessageHeader object, with MessageClass set to Service and MessageCategory set to Reversal.

      Parameter Required Description
      ProtocolVersion -white_check_mark- 3.0
      MessageClass -white_check_mark- Service
      MessageCategory -white_check_mark- Reversal
      MessageType -white_check_mark- Request
      ServiceID -white_check_mark- Your unique ID for this request, consisting of 1-10 alphanumeric characters. Must be unique within the last 48 hours for the terminal (POIID) being used.
      SaleID -white_check_mark- Your unique ID for the POS system component to send this request from.
      POIID -white_check_mark- The unique ID of the terminal to send this request to. Format: [device model]-[serial number].
    • The ReversalRequest object with:

      Parameter Required Description
      OriginalPOITransaction.POITransactionID Required An object with:
      • TransactionID: The transaction identifier of the original payment in the format tenderReference.pspReference. For example, BV0q001765198054002.CWBC43ZX2VTFWR82
      • TimeStamp: The date and time of the original payment request in UTC format.
      ReversalReason Required Set to MerchantCancel.
      ReversedAmount Conditionally required Required for partial refunds.
      The refunded amount. If not included, defaults to the authorized amount of the referenced payment.
      Specify the amount as a number (not a string) with a decimal point. Do not use minor units. For example, for an amount of USD 10 specify 10.00 (not 1000).

      SaleData.SaleToAcquirerData Conditionally required The formatted string of split instructions for the refund.

      For a partial refund, the string must also include the currency of the partial refund. This must match the currency of the original payment and must be provided in the format "currency":"ABC" (or currency=ABC if using key-value pairs), where ABC is the three-letter currency code.
      SaleData.SaleTransactionID Conditionally required Required for partial refunds.
      An object with:
      • TransactionID: Your reference to identify the refund. We recommend using a unique value per (partial) refund.
      • TimeStamp: The date and time of the request in UTC format.

    The payment terminal shows a waiting screen until you receive a response.

  5. When you receive the ReversalResponse note the following:

    Parameter Description
    Response.Result Success means we received your request. The refund itself will be processed asynchronously.
    Response.ReversedAmount The partial refund amount that we will try to get authorized.
    POIData.POITransactionID.TransactionID The PSP reference for this refund request.
    PaymentReceipt The generated receipt data. This includes REFUND REQUESTED.
    Response.AdditionalResponse This includes:
    • posOriginalAmountValue: The amount (in minor units) of the original payment.
    • posAuthAmountValue: The refund amount (in minor units) that we will try to get authorized.
    • merchantReference: The SaleData.SaleTransactionID.TransactionID from the partial refund request.
    • pspReference: The PSP reference for this refund request.

    If your request failed, the ReversalResponse.Response contains:

    • Result: Failure
    • AdditionalResponse: This includes a message explaining why the request failed. For example:
      • Original pspReference required for this operation: Messages like this tell you how to fix the request so you can try again.
      • Transaction is already voided: This message tells you that we already received a full reversal request for the original transaction.
  6. Wait for the CANCEL_OR_REFUND webhook event to learn the outcome of the refund request. Refunds are always processed asynchronously.

Full refund with split instructions

To refund the full amount of the original payment, your Terminal API reversal request requires less parameters than to refund a partial amount. Other than that, the procedure is the same.

The following example shows a reversal request for a full refund of a USD 80.00 payment, where the split instructions differ from the payment:

  • A refund amount of USD 76.00 is debited from the user's balance account BA00000000000000000000001.
  • A commission of USD 4.00 is debited from your liable balance account.

As you can see, for a full refund with split instructions the ReversalRequest object only needs these parameters:

Parameter Required Description
OriginalPOITransaction.POITransactionID Required An object with:
  • TransactionID: The transaction identifier of the original payment in the format tenderReference.pspReference. For example, BV0q001765198054002.CWBC43ZX2VTFWR82
  • TimeStamp: The date and time of the original payment request in UTC format.
ReversalReason Required Set to MerchantCancel.
SaleData.SaleToAcquirerData Conditionally required The formatted string of split instructions for the refund.
There is not need to add a separate currency parameter.

The ReversalResponse does not contain a ReversedAmount because the full amount from the payment referenced in the POITransactionID of the reversal request will be refunded.

Track fund movements

To track the status of the funds transfers initiated by a refund:

  1. Listen to the following webhooks:
  2. Acknowledge the webhooks. We send these webhooks for every split item in the payment.
  3. In the payload of the balancePlatform.transfer.updated webhook, note that:
    • The event array includes all previous transfer events.
    • The sequenceNumber defines the number of webhooks sent for the transfer, including the current one.

Examples

Your server receives webhooks for each split of the refund amount. The following examples are based on a refund request with split instructions use case.

See also