Are you looking for test card numbers?

Would you like to contact support?

Point-of-sale icon

Referenced refund

Issue a point-of-sale refund connected to the original payment.

To return funds to a shopper after a payment is Approved, you need to refund the payment. Referenced refunds are connected to the original payment, using the unique identifier of that payment.

When you make an in-store payment, the Terminal API response returns the transaction identifier of the payment in the format tenderReference.pspReference. To make a referenced refund, you specify this transaction identifier in your refund request. This lets us validate the refund against the original payment, to ensure that it hasn't already been refunded.

You can make a:

  • Full refund to return the total value of the purchase to the shopper.
  • Partial refund to return part of the purchase to the shopper. For example, when a shopper returns one of the items they purchased. You can also make multiple partial refunds. For example, when a shopper returns several items at different times.

Make a referenced refund

Select a tab to see the parameters that you need to specify for a full referenced refund, or a partial referenced refund.

Here we describe the basic referenced refund request for the full amount. To refund an offline payment or to refund an ecommerce payment, the request is a little different.

  1. Get the TransactionID and the TimeStamp of the original payment. You received these values in the payment response, in the POIData.POITransactionID object.

  2. 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 cash register.
      POIID -white_check_mark- The unique ID of the terminal that you want to send this request to. Format: [device model]-[serial number].
    • ReversalRequest: the request body. Specify:
      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 in UTC format of the original payment. For example, 2000-01-01T00:00:00.000Z
      ReversalReason -white_check_mark- MerchantCancel

    The next example shows how to make a full referenced refund.

    {
        "SaleToPOIRequest":{
            "MessageHeader":{
                "ProtocolVersion":"3.0",
                "MessageClass":"Service",
                "MessageCategory":"Reversal",
                "MessageType":"Request",
                "SaleID":"POSSystemID12345",
                "ServiceID":"0207111107",
                "POIID":"V400m-324688179"
            },
            "ReversalRequest":{
                "OriginalPOITransaction":{
                    "POITransactionID":{
                        "TransactionID":"BV0q001643892070000.VK9DRSLLRCQ2WN82",
                        "TimeStamp":"2022-01-31T12:08:45.004Z"
                    }
                },
                "ReversalReason":"MerchantCancel"
            }
        }
    }
    String saleID = "YOUR_CASH_REGISTER_ID";
    String serviceID = "YOUR_UNIQUE_ATTEMPT_ID";
    String POIID = "YOUR_TERMINAL_ID";
    String transactionID = "YOUR_UNIQUE_TRANSACTION_ID";
    
    SaleToPOIRequest saleToPOIRequest = new SaleToPOIRequest();
    MessageHeader messageHeader = new MessageHeader();
    messageHeader.setProtocolVersion("3.0");
    messageHeader.setMessageClass( MessageClassType.SERVICE );
    messageHeader.setMessageCategory( MessageCategoryType.REVERSAL );
    messageHeader.setMessageType( MessageType.REQUEST );
    messageHeader.setSaleID(saleID);
    messageHeader.setServiceID(serviceID);
    messageHeader.setPOIID(POIID);
    saleToPOIRequest.setMessageHeader(messageHeader);
    
    ReversalRequest reversalRequest = new ReversalRequest();
    OriginalPOITransaction originalPOITransaction = new OriginalPOITransaction();
    TransactionIdentification pOITransactionID = new TransactionIdentification();
    pOITransactionID.setTransactionID(transactionID);
    pOITransactionID.setTimeStamp(DatatypeFactory.newInstance().newXMLGregorianCalendar(new GregorianCalendar()));
    originalPOITransaction.setPOITransactionID(pOITransactionID);
    reversalRequest.setOriginalPOITransaction(originalPOITransaction);
    reversalRequest.setReversalReason( ReversalReasonType.MERCHANT_CANCEL );
    saleToPOIRequest.setReversalRequest(reversalRequest);
    terminalAPIRequest.setSaleToPOIRequest(saleToPOIRequest);

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

  3. 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"
                }
            }
        }
    }

    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.
  4. Wait for the CANCEL_OR_REFUND webhook to learn the outcome. Refunds are always processed asynchronously. If successful, the refund is issued to the shopper's account.

For a complete list of fields you can pass and receive for a referenced refund, see the ReversalRequest API reference and the ReversalResponse API reference.

Refunding an offline point-of-sale payment

An offline point-of-sale payment has a tender reference, which is generated by the terminal. But the PSP reference is missing because it is generated on the Adyen payments platform, and that could not be reached. To refund an offline point-of-sale payment, you need to know the tender reference and the date of the original payment. In most cases you also need to know the unique identifier of the terminal that processed the original payment.

Compared to a basic full referenced refund, note the following request parameters:
Parameter Required Description
OriginalPOITransaction.POITransactionID -white_check_mark- An object with TransactionID: the tender reference of the original payment. For example, BV0q001643892070000
OriginalPOITransaction.POIID If using a different terminal than for the original payment. The unique ID of the terminal that processed the original payment. With the POIID, we can find the missing information.
{
  "SaleToPOIRequest":{
    "MessageHeader":{
      "ProtocolVersion":"3.0",
      "MessageClass":"Service",
      "MessageCategory":"Reversal",
      "MessageType":"Request",
      "SaleID":"POSSystemID12345",
      "ServiceID":"207111108",
      "POIID":"V400m-324688179"
    },
    "ReversalRequest":{
      "OriginalPOITransaction":{
        "POITransactionID":{
          "TransactionID":"BV0q001643892070000",
          "TimeStamp":"2022-01-31T12:08:45.004Z"
        },
        "POIID":"P400Plus-275008565"
      },
      "ReversalReason":"MerchantCancel"
    }
  }
}

Refunding an ecommerce payment

An ecommerce payment does have a PSP reference, but the tender reference is missing because it is generated by the terminal. To refund an ecommerce payment, you need to know the PSP reference, the date, and the currency of the original payment.

Compared to a basic full referenced refund, note the following request parameters:
Parameter Required Description
OriginalPOITransaction.POITransactionID -white_check_mark- An object with TransactionID: the PSP reference of the original payment, in the format .pspReference. Don't forget the leading dot (.). For example: .VK9DRSLLRCQ2WN82
SaleData.SaleToAcquirerData -white_check_mark- The currency of the refund, in the format currency=ABC where ABC is the three-letter currency code. This must match the currency of the original payment.
SaleData.SaleTransactionID -white_check_mark- An object with:
  • TransactionID: Your unique reference for the refund. In your Customer Area and Adyen reports, this will show as the merchant reference.
  • TimeStamp: Date and time in UTC format of the refund.
{
  "SaleToPOIRequest":{
    "MessageHeader":{
      "ProtocolVersion":"3.0",
      "MessageClass":"Service",
      "MessageCategory":"Reversal",
      "MessageType":"Request",
      "SaleID":"POSSystemID12345",
      "ServiceID":"207111108",
      "POIID":"V400m-324688179"
    },
    "ReversalRequest":{
      "OriginalPOITransaction":{
        "POITransactionID":{
          "TransactionID":".VK9DRSLLRCQ2WN82",
          "TimeStamp":"2022-01-31T12:08:45.004Z"
        }
      },
      "ReversalReason":"MerchantCancel",
      "SaleData":{
        "SaleToAcquirerData":"currency=EUR",
        "SaleTransactionID":{
          "TimeStamp":"2022-02-03T15:04:14.004Z",
          "TransactionID":"rev-708"
        }
      }
    }
  }
}
When you receive the ReversalResponse, note that the Response.AdditionalResponse includes:
  • posOriginalAmountValue: 0 (zero)
  • posAuthAmountValue: 0 (zero)
That is because at this moment we don't know the original amount of the ecommerce payment, and thus also don't know the refund amount that we will try to get authorised.

See also