Are you looking for test card numbers?

Would you like to contact support?

Marketpay icon

Split a refund

Split a refund between the balance accounts in your platform.

When refunding a split payment, you can either deduct the same amount from the same balance accounts as used in the original payment request, or provide new split data in the ReversalRequest. Refunds can only be deducted from the balance accounts to which the payment was credited.

For example, a payment of EUR 620.00 is split between two balance accounts:

  • EUR 600.00 is booked to your user's balance account (BA00000000000000000000001).
  • EUR 20.00 is booked to your liable balance account as your platform's commission.

To refund this payment, send a Terminal API ReversalRequest. If you do not provide the split data in the SaleData.SaleToAcquirerData object of your request, the split data from the original payment will be used for the refund.

We recommend that you always provide split data for refunds. That way, you are always in control and can support different refund scenarios, such as partial and multiple partial refunds.

When sending split data in a refund request, you must:

  • Only use balance accounts that were part of the original split.
  • Use the same reference values as the original split.

To provide split information in your refund request:

Step 1: Prepare the split data

You must include the following information in the request:

Key Description Example
split.api Version of the Split API: 1. split.api=1
split.totalAmount Amount to be split, in minor units. Must be equal to the transaction amount which is the sum of the split amounts. split.totalAmount=62000
split.currencyCode Currency of the amount you intend to split. split.currencyCode=EUR
split.nrOfItems Number of times you split the payment. Must match the number of split items in the request. split.nrOfItems=2
currency Currency of the split amount. Must match the value provided in split.currencyCode. currency=EUR

Specify each split as a split.item{item#} starting at 1: split.item1, split.item2, and so on. In each split item, include:

Key Description Example
split.item{item#}.amount Amount of each split item, in minor units. You do not need to specify the amount for the fees, since this is not known at the time of payment. split.item1.amount=62000
split.item2.amount=0
split.item{item#}.type Split type.
  • BalanceAccount: books the sale amount against the specified balance account.
  • Commission: books the commission against your liable account.
split.item1.type=BalanceAccount
split.item2.type=Commission
split.item{item#}.account Account that will receive (or be charged) the split. This is the balanceAccountID of one of your user's balance accounts or your own liable account. You don't need to specify this field when the split.item{item#}.type is Commission. split.item1.account=BA00000000000000000000001
split.item{item#}.reference The reference for that specific transaction split, which is returned in our reporting. Required if the split.item{item#}.type is BalanceAccount. split.item1.reference=reference_split_1
split.item2.reference=reference_commission
split.item{item#}.description The description for that specific transaction split, which is returned in our reporting. split.item1.description=description_split_1
split.item2.description=description_commission

Step 2: Pass the split data

Pass the split data in the SaleData.SaleToAcquirerData object.

You can pass the split data in the SaleData.SaleToAcquirerData object of your terminal API request as concatenated key-value pairs separated by an ampersand (&) character, or in Base64-encoded format.

The format you choose in your request is the format that will be returned in the AdditionalResponse. To always receive the AdditionalResponse in the same format, contact our POS Support Team

1. Define the pairs of split payment data:
Split payment data in pairs
   currency=USD
   split.api=1
   split.nrOfItems=2
   split.totalAmount=62000
   split.currencyCode=EUR
   split.item1.amount=62000
   split.item1.type=BalanceAccount
   split.item1.account=BA00000000000000000000001
   split.item1.reference=reference_split_1
   split.item1.description=description_split_1
   split.item2.amount=0
   split.item2.type=Commission
   split.item2.reference=reference_commission
   split.item2.description=description_commission
2. Concatenate the pairs using ampersands (**&**) to a string. ~~~~raw currency=USD&split.api=1&split.nrOfItems=2&split.totalAmount=62000&split.currencyCode=USD&split.item1.amount=62000&split.item1.type=BalanceAccount&split.item1.account=BA00000000000000000000001&split.item1.reference=reference_split_1&split.item1.description=description_split_1&split.item2.amount=0&split.item2.type=Commission&split.item2.reference=reference_commission&split.item2.description=description_commission ~~~~ 3. Pass this string in the `SaleToAcquirerData` object of your request.

Step 3: Make a payment request

Make a POST request to a Terminal API endpoint, specifying:

  • MessageHeader: the standard SaleToPOIRequest.MessageHeader object. This includes:
    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].
  • ReversalRequest: The request body. This includes:

    Parameter Required Description
    OriginalPOITransaction.POITransactionID -white_check_mark- An object with:
    • TransactionID: Transaction identifier of the original payment in the format tenderReference.pspReference. For example, BV0q001643892070000.VK9DRSLLRCQ2WN82
    • TimeStamp: date and time of the original payment request in UTC format.
    ReversalReason -white_check_mark- Set to MerchantCancel.
    ReversedAmount -white_check_mark- The refunded amount.
    Specify the amount with a decimal point. Do not use minor units. For example, for an amount of 10 USD specify 10.00 (not 1000).

    SaleData.SaleToAcquirerData -white_check_mark- Provides the split refund data as concatenated key-value pairs separated by an ampersand (&) character, or in Base64-encoded format. See the tables below for details
    SaleData.SaleTransactionID -white_check_mark- An object with:
    • TransactionID: your reference to identify the refund. We recommend using a unique value per refund.
    • TimeStamp: date and time of the request in UTC format.

Below is an example terminal API request to split a refund of EUR 620.00 between the balance accounts on your platform, using key-value pairs.
In this example, we are deducting different amounts from the balance accounts than what was defined in the original payment request.

  • EUR 620.00 is debited from BA00000000000000000000001.
  • EUR 0.00 is debited from your liable account.
Refund request with split data
{
    "SaleToPOIRequest":{
        "MessageHeader":{
            "ProtocolVersion": "3.0",
            "MessageClass": "Service",
            "Message Category": "Reversal",
            "MessageType": "Request",
            "SaleID": "YOUR_POS_SYSTEM_ID",
            "ServiceID": "YOUR_UNIQUE_REFERENCE",
            "POIID": "YOUR_TERMINAL_ID"
        },
        "ReversalRequest":{
            "OriginalPOITransaction":{
                "POITransactionID":{
                    "TransactionID": "ORIGINAL_TRANSACTION_REFERENCE",
                    "TimeStamp": "DATE_TIME_ORGINAL_TRANSACTION"
                }
            },
            "ReversalReason": "MerchantCancel",
            "ReversedAmount": "TOTAL_REFUND_AMOUNT",
            "SaleData":{
                "SaleToAcquirerData": "currency=EUR&split.api=1&split.nrOfItems=2&split.totalAmount=62000&split.currencyCode=EUR&split.item1.amount=62000&split.item1.type=BalanceAccount&split.item1.account=BA00000000000000000000001&split.item1.reference=reference_split_1&split.item1.description=description_split_1&split.item2.amount=0&split.item2.type=Commission&split.item2.reference=reference_commission&split.item2.description=description_commission",
                "SaleTransactionID":{
                    "TimeStamp": "DATE_TIME_REFUND_REQUEST",
                    "TransactionID": "YOUR_REFUND_REFERENCE"
                }
            }
        }
    }
}

The refund request is routed to the terminal, where the customer can present their card. The payment terminal shows a waiting screen until you receive a response.

Step 4: Check the result

Response

When you receive the ReversalResponse, check if we received your request. Note the following:

  • Response.Result: Success. This means we received your request. The refund itself will be processed asynchronously.
  • POIData.POITransactionID.TransactionID: the PSP reference for this refund request.
  • PaymentReceipt: the generated receipt data. This includes REFUND REQUESTED.
  • Response.AdditionalResponse with:
    • posOriginalAmountValue: the amount (in minor units) of the original payment.
    • posAuthAmountValue: the refund amount (in minor units) that we will try to get authorised.
    • pspReference: the PSP reference for this refund request.
Response when we received your full reversal request
{
    "SaleToPOIResponse": {
        "MessageHeader": {
            "MessageCategory": "Reversal",
            "MessageClass": "Service",
            "MessageType": "Response",
            "POIID": "V400m-324688179",
            "ProtocolVersion": "3.0",
            "SaleID": "POSSystemID12345",
            "ServiceID": "207111107"
        },
        "ReversalResponse": {
            "POIData": {
                "POITransactionID": {
                    "TimeStamp": "2022-02-03T15:04:15.004Z",
                    "TransactionID": "TF995R5G6L2GWR82"
                }
            },
            "PaymentReceipt": [...],
            "Response": {
                "AdditionalResponse": "tid=47069832&transactionType=GOODS_SERVICES&posadditionalamounts.originalAmountValue=1025&giftcardIndicator=false&posAmountGratuityValue=0&pspReference=TF995R5G6L2GWR82&store=YOUR_STOREL&iso8601TxDate=2022-02-03T15%3a04%3a13.0000000%2b0000&posOriginalAmountValue=1025&txtime=16%3a04%3a13&paymentMethod=mc&txdate=03-02-2022&merchantReference=2022-02-03%2016%3a04%3a13&posadditionalamounts.originalAmountCurrency=EUR&transactionReferenceNumber=TF995R5G6L2GWR82&posAuthAmountCurrency=EUR&posAmountCashbackValue=0&posEntryMode=CLESS_CHIP&posAuthAmountValue=1025",
                "Result": "Success",
                "ReversedAmount": 620
            }
        }
    }
}

If your request failed, the ReversalResponse contains:

  • Response.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.

Webhook

Wait for the CANCEL_OR_REFUND webhook to learn the outcome. Refunds are always processed asynchronously.