Search

Are you looking for test card numbers?

Would you like to contact support?

Point-of-sale icon

Refund a payment

Learn how to issue a point of sale refund.

Not refunding point-of-sale payments often?

If you want to return funds to a shopper after a payment has been Approved, you need to refund the payment.

We offer two types of refund:

  • Referenced refund: A ReversalRequest. Referenced refunds are connected to the original payment, using a unique identifier of that payment.
  • Unreferenced refund: A PaymentRequest with PaymentType Refund. Unreferenced refunds need to be manually reconciled, and let you return any amount to any card presented in-store. You can use this for example to issue a refund to someone who did not make the original payment, such as a gift recipient.

You can implement one or both types of refund.

Referenced refunds offer the following advantages over unreferenced refunds:

  • Simpler reconciliation: A refund can be matched against a payment, using the pspReference.
  • Lower risk of return fraud: A payment can't be refunded multiple times, or for an amount exceeding 100% of the payment value.
  • Support for refunds to QR code payment methods, such as Alipay and WeChat Pay.
  • Cross-channel refunds: Refunds can be issued in-store, from your call center, or your fulfillment center.
  • Refunding BankAxept payments requires an additional contract with the BankAxept scheme and is only possible in stores where the shopper has made a purchase.

  • The following card schemes only support unreferenced refunds.
    • Dankort
    • Interac

Processing refunds

Refunds are not processed synchronously. When you send a request for a referenced or unreferenced refund, the Terminal API response confirms we received the request. Then we try to process the refund asynchronously, and will inform you of the result through a REFUND webhook notification.

When a refund has been processed, it is deducted from your in-process funds, and will appear in your shopper's account within a few days.

Referenced refunds

When you make an in-store payment, the 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.

Depending on what the shopper is returning, you can either make a:

  • Full refund: Returns the total value of the purchase to the shopper.
  • Partial refund: Returns 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

Full and partial refund requests are very similar, but there are a few additional parameters for a partial refund.

  1. Make a POST request to a Terminal API endpoint, to initiate a referenced refund for the full amount or a partial amount. Select a tab to see the parameters that you need to specify.

    • ReversalRequest: The request body with:

      Parameter Required Description
      OriginalPOITransaction.POITransactionID -white_check_mark- An object with:
      • TransactionID: Transaction identifier (ideally tender reference and PSP reference) of the original payment that you want to refund. See the allowed formats.
      • TimeStamp: Date and time in UTC format of the original payment. For example, 2000-01-01T00:00:00.000Z
      ReversalReason -white_check_mark- MerchantCancel
      POIID Unique terminal ID of the terminal that processed the original payment.

      Include this when you only know the tender reference part of the TransactionID.

      SaleData.SaleToAcquirerData The currency of the refund, in the format currency=EUR. This must match the currency of the original payment.

      Include this when you only know the PSP reference part of the TransactionID.

      To specify the original TransactionID, use one of the following formats:

      Format Example
      tenderReference.pspReference 7JLX001566393198001.851556019495143C

      Recommended format

      .pspReference .851556019495143C

      Don't forget the leading dot (.). Use this together with the SaleData.SaleToAcquirerData.currency field when you don't know the tender reference.

      tenderReference 7JLX001566393198001

      Use this together with the POIID field when you don't know the PSP reference.

    The next example shows how to make a full refund, with the TransactionID in the recommended format.

    {
          "SaleToPOIRequest":{
             "MessageHeader":{
                "ProtocolVersion":"3.0",
                "MessageClass":"Service",
                "MessageCategory":"Reversal",
                "MessageType":"Request",
                "SaleID":"POSSystemID12345",
                "ServiceID":"0207111107",
                "POIID":"V400m-324688179"
              },
             "ReversalRequest":{
                "OriginalPOITransaction":{
                   "POITransactionID":{
                      "TransactionID":"7JLX001566393198001.851556019495143C",
                      "TimeStamp":"2019-03-07T10:11:04+00:00"
                   }
                },
                "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);

    Refunding an offline point-of-sale payment

    The next example shows how to make a full refund when you don't know the PSP reference of the original payment. Use this to refund an offline payment: Because the PSP reference is generated on the Adyen payments platform, it is missing for offline payments.
    The request must include:

    • TransactionID in the format tenderReference
      For example: 7JLX001566393198001
    • POIID: Unique terminal ID of the terminal that processed the original payment. With the POIID, we can find the missing information. In case of a full refund on the same terminal that processed the original transaction, you can omit the POIID field.
    Reversal request when the PSP reference is unknown
    {
       "SaleToPOIRequest":{
          "MessageHeader":{
             "ProtocolVersion":"3.0",
             "MessageClass":"Service",
             "MessageCategory":"Reversal",
             "MessageType":"Request",
             "SaleID":"POSSystemID12345",
             "ServiceID":"207111108",
             "POIID":"V400m-324688179"
          },
          "ReversalRequest":{
             "OriginalPOITransaction":{
                "POITransactionID":{
                   "TransactionID":"7JLX001566393198001",
                   "TimeStamp":"2019-03-07T10:11:04+00:00"
                }
             },
             "POIID":"P400Plus-275008565",
             "ReversalReason":"MerchantCancel"
          }
       }
    }

    Refunding an ecommerce payment

    The next example shows how to make a full refund when you know the PSP reference of the original payment, but don't know the tender reference. Use this to refund an ecommerce payment: Because the tender reference is generated by the terminal, it is missing for ecommerce payments.
    The request must include:

    • TransactionID in the format .pspReference
      Don't forget the leading dot (.), for example: .851556019495143C
    • A SaleData.SaleToAcquirerData field with the currency of the original payment.
    Reversal request when the tender reference is unknown
    {
       "SaleToPOIRequest":{
          "MessageHeader":{
             "ProtocolVersion":"3.0",
             "MessageClass":"Service",
             "MessageCategory":"Reversal",
             "MessageType":"Request",
             "SaleID":"POSSystemID12345",
             "ServiceID":"207111108",
             "POIID":"V400m-324688179"
          },
          "ReversalRequest":{
             "OriginalPOITransaction":{
                "POITransactionID":{
                   "TransactionID":".851556019495143C",
                   "TimeStamp":"2019-03-07T10:11:04+00:00"
                }
             },
             "SaleData": {
                "SaleToAcquirerData": "currency=EUR"
            },
            "ReversalReason":"MerchantCancel"
          }
       }
    }
    • ReversalRequest: The request body with:

      Parameter Required Description
      OriginalPOITransaction.POITransactionID -white_check_mark- An object with:
      • TransactionID: Transaction identifier (ideally tender reference and PSP reference) of the original payment that you want to refund. See the allowed formats.
      • TimeStamp: Date and time in UTC format of the original payment. For example, 2000-01-01T00:00:00.000Z
      ReversalReason -white_check_mark- MerchantCancel
      POIID Unique terminal ID of the terminal that processed the original payment.

      Include this when you only know the tender reference part of the TransactionID.

      ReversedAmount -white_check_mark- The amount being returned to the shopper in the partial refund.
      SaleData.SaleToAcquirerData -white_check_mark- The currency of the refund, in the format currency=EUR. This must match the currency of the original payment.
      SaleData.SaleTransactionID An object with:
      • TransactionID: Your unique reference for the partial refund. In your Customer Area and Adyen reports, this will show as the merchant reference.
      • TimeStamp: Date and time in UTC format of the partial refund.

      To specify the original TransactionID, use one of the following formats:

      Format Example
      tenderReference.pspReference 7JLX001566393198001.851556019495143C

      Recommended format

      .pspReference .851556019495143C

      Don't forget the leading dot (.). Use this together with the SaleToAcquirerData.currency field when you don't know the tender reference.

      tenderReference 7JLX001566393198001

      Use this together with the POIID field when you don't know the PSP reference.

    This example shows how to make a partial refund of 6.00 EUR.

    {
          "SaleToPOIRequest":{
             "MessageHeader":{
                "ProtocolVersion":"3.0",
                "MessageClass":"Service",
                "MessageCategory":"Reversal",
                "MessageType":"Request",
                "SaleID":"POSSystemID12345",
                "ServiceID":"207111108",
                "POIID":"V400m-324688179"
             },
             "ReversalRequest":{
                "OriginalPOITransaction":{
                   "POITransactionID":{
                      "TransactionID":"pZtU001251034513719.881566567357804C",
                      "TimeStamp":"2019-08-12T15:40:03+00:00"
                   }
                },
                "ReversalReason":"MerchantCancel",
                "ReversedAmount":6.00,
                "SaleData":{
                   "SaleToAcquirerData":"currency=EUR",
                   "SaleTransactionID":{
                      "TimeStamp":"2019-08-15T12:00:00+00:00",
                      "TransactionID":"27911"
                   }
                }
             }
          }
        }
     }
    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 );
    reversalRequest.setReversedAmount(6.0);
    
    SaleData saleData = new SaleData();
    saleData.setSaleToAcquirerData("currency=EUR");
    TransactionIdentification saleTransactionID = new TransactionIdentification();
    saleTransactionID.setTimeStamp(DatatypeFactory.newInstance().newXMLGregorianCalendar(new GregorianCalendar()));
    saleTransactionID.setTransactionID(transactionID);
    saleData.setSaleTransactionID(saleTransactionID);
    reversalRequest.setSaleData(saleData);
    saleToPOIRequest.setReversalRequest(reversalRequest);
    terminalAPIRequest.setSaleToPOIRequest(saleToPOIRequest);

    Partially refunding an offline point-of-sale payment

    The next example shows how to make a partial refund when you don't know the PSP reference of the original payment. Use this to partially refund an offline payment: Because the PSP reference is generated on the Adyen payments platform, it is missing for offline payments.
    The request must include:

    • TransactionID in the format tenderReference
      For example: 7JLX001566393198001
    • POIID: Unique terminal ID of the terminal that processed the original payment. With the POIID, we can find the missing information.
    Partial reversal when the PSP reference is unknown
     {
          "SaleToPOIRequest":{
             "MessageHeader":{
                "ProtocolVersion":"3.0",
                "MessageClass":"Service",
                "MessageCategory":"Reversal",
                "MessageType":"Request",
                "SaleID":"POSSystemID12345",
                "ServiceID":"207111108",
                "POIID":"V400m-324688179"
             },
             "ReversalRequest":{x
                "OriginalPOITransaction":{
                   "POITransactionID":{
                      "TransactionID":"pZtU001251034513719",
                      "TimeStamp":"2019-08-12T15:40:03+00:00"
                   }
                },
                "POIID":"P400Plus-275008565",
                "ReversalReason":"MerchantCancel",
                "ReversedAmount":6.00,
                "SaleData":{
                   "SaleToAcquirerData":"currency=EUR",
                   "SaleTransactionID":{
                      "TimeStamp":"2019-08-15T12:00:00+00:00",
                      "TransactionID":"27911"
                   }
                }
             }
          }
        }
     }

    Partially refunding an ecommerce payment

    The next example shows how to make a partial refund when you know the PSP reference of the original payment, but don't know the tender reference. Use this to refund an ecommerce payment: Because the tender reference is generated by the terminal, it is missing for ecommerce payments.
    The request must include:

    • TransactionID in the format .pspReference
      Don't forget the leading dot (.), for example: .851556019495143C
    • A SaleData.SaleToAcquirerData field with the currency of the original payment.
    Partial reversal when the tender reference is unknown
    {
          "SaleToPOIRequest":{
             "MessageHeader":{
                "ProtocolVersion":"3.0",
                "MessageClass":"Service",
                "MessageCategory":"Reversal",
                "MessageType":"Request",
                "SaleID":"POSSystemID12345",
                "ServiceID":"207111108",
                "POIID":"V400m-324688179"
             },
             "ReversalRequest":{
                "OriginalPOITransaction":{
                   "POITransactionID":{
                      "TransactionID":".881566567357804C",
                      "TimeStamp":"2019-08-12T15:40:03+00:00"
                   }
                },
                "ReversalReason":"MerchantCancel",
                "ReversedAmount":6.00,
                "SaleData":{
                   "SaleToAcquirerData":"currency=EUR",
                   "SaleTransactionID":{
                      "TimeStamp":"2019-08-15T12:00:00+00:00",
                      "TransactionID":"27911"
                   }
                }
             }
          }
        }
     }
  2. Check whether we received your request for a full or partial refund.

    • If we received your request, the ReversalResponse contains:

      • POIData.POITransactionID.TransactionID: The PSP reference for this refund request.
      • Response.Result: Success
    Response when we received your reversal request
    {
       "SaleToPOIResponse":{
          "ReversalResponse":{
             "POIData":{
                "POITransactionID":{
                   "TimeStamp":"2019-05-23T10:32:32.928Z",
                   "TransactionID":"881566557882697F"
                }
             },
             "Response":{
                "Result":"Success",
                ...
             }
          },
          ...
       }
    }
    • If your request failed, the ReversalResponse contains:

      • Response.Result: Failure
      • AdditionalResponse: Includes a message explaining why the request failed. Use this to fix the request and try again.
    Response for a failed reversal request
    {
       "SaleToPOIResponse":{
          "ReversalResponse":{
             "Response":{
                "Result":"Failure",
                "AdditionalResponse":"tid=24687685&...&message=Original%20pspReference%20required%20for%20this%20operation&posAmountCashbackValue=0&posEntryMode=UNKNOWN&posAuthAmountValue=0",
                "ErrorCondition":"NotAllowed"
             }
          },
          ...
          }
       }
    }
  3. Wait for the REFUND webhook notification to learn the result.
    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.

Unreferenced refunds

If you are using unreferenced refunds, we highly recommend that your cash register system is able to reconcile a refund against an original purchase. This reduces the risk of return fraud (a payment being refunded multiple times), and human error (store staff enter the wrong refund amount).

It's not possible to make an unreferenced refund to a QR code payment method, such as Alipay and WeChat Pay. To refund these payment methods you must make a referenced refund.

Enable unreferenced refunds

Before you can make unreferenced refunds, contact our POS Support Team team and ask them to:

  • Enable unreferenced refunds for your merchant account.
  • Optional Set a refund delay so you have time to cancel an unreferenced refund when necessary.

Make an unreferenced refund

For an unreferenced refund to a gift card, you need to specify more parameters than we describe here. Refer to Make a refund to a gift card.

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

    • PaymentRequest: The request body with:

      Parameter Required Description
      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.

        If the original payment was an offline payment, you can make reconciliation easier by including the tender reference of the offline payment.

      • TimeStamp: Date and time of the refund in UTC format.
      PaymentTransaction.AmountsReq -white_check_mark- An object with:
      • Currency: The transaction currency.
      • RequestedAmount: The amount being refunded to the card.
      PaymentData.PaymentType Refund

    The example below shows how to refund 10.99 EUR to a card.

    {
        "SaleToPOIRequest":{
            "MessageHeader":{
                "ProtocolVersion":"3.0",
                "MessageClass":"Service",
                "MessageCategory":"Payment",
                "MessageType":"Request",
                "SaleID":"POSSystemID12345",
                "ServiceID":"12392",
                "POIID":"V400m-324688179"
            },
            "PaymentRequest":{
                "SaleData":{
                    "SaleTransactionID":{
                        "TimeStamp":"2019-04-23T12:15:01+00:00",
                        "TransactionID":"YOUR_REFUND_REFERENCE"
                    }
                },
                "PaymentTransaction":{
                    "AmountsReq":{
                        "Currency":"EUR",
                        "RequestedAmount":10.99
                    }
                },
                "PaymentData":{
                    "PaymentType":"Refund"
                }
            }
        }
    }
    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.PAYMENT );
    messageHeader.setMessageType( MessageType.REQUEST );
    messageHeader.setSaleID(saleID);
    messageHeader.setServiceID(serviceID);
    messageHeader.setPOIID(POIID);
    saleToPOIRequest.setMessageHeader(messageHeader);
    
    PaymentRequest paymentRequest = new PaymentRequest();
    SaleData saleData = new SaleData();
    TransactionIdentification saleTransactionID = new TransactionIdentification();
    saleTransactionID.setTimeStamp(DatatypeFactory.newInstance().newXMLGregorianCalendar(new GregorianCalendar()));
    saleTransactionID.setTransactionID(transactionID);
    saleData.setSaleTransactionID(saleTransactionID);
    paymentRequest.setSaleData(saleData);
    
    PaymentTransaction paymentTransaction = new PaymentTransaction();
    AmountsReq amountsReq = new AmountsReq();
    amountsReq.setCurrency("EUR");
    amountsReq.setRequestedAmount( BigDecimal.valueOf(10.99) );
    paymentTransaction.setAmountsReq(amountsReq);
    paymentRequest.setPaymentTransaction(paymentTransaction);
    
    PaymentData paymentData = new PaymentData();
    paymentData.setPaymentType( PaymentType.REFUND );
    paymentRequest.setPaymentData(paymentData);
    saleToPOIRequest.setPaymentRequest(paymentRequest);
    terminalAPIRequest.setSaleToPOIRequest(saleToPOIRequest);

    The refund request is routed to the terminal.

  2. Present the card to the terminal, and follow the instructions on the terminal screen.

  3. Check whether we received your refund request. If we received it:

    • Approved is shown on the terminal.
    • You receive a JSON response with:
    {
        "SaleToPOIResponse": {
            "PaymentResponse": {
                "POIData": {
                    "POITransactionID": {
                        "TimeStamp": "2019-06-03T15:49:36.000Z",
                        "TransactionID": "4rVu001559576976000.881559576981487A"
                    },
                    ...
                },
                ...
                "Response": {
                    "Result": "Success",
                    ...
                }
            },
            ...
        }
    }
  4. Wait for the REFUND webhook notification to learn the result.
    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 an unreferenced refund, see the PaymentRequest API reference and the PaymentResponse API reference.

Refund notifications

When we receive your refund request, we send you a webhook notification to inform you whether this request was processed. This notification contains:

  • eventCode: REFUND
  • pspReference: Matches the TransactionID of the refund request.
  • success: Indicates whether the refund request was processed:

    • true: We processed your refund request. This usually results in the refund being issued.
    • false: We did not process your refund request. This means you do not have sufficient in-process funds to issue the refund. You should increase your in-process funds, and request the refund again.

In rare cases, after your refund request is processed you can receive a notification indicating that this refund:

An overview of failed and reversed refunds is available in your Payment accounting report.

Refund failed

Although rare, a refund can fail after we have sent it for processing to the card scheme or third-party processor. When a refund fails, you receive a notification webhook with:

  • eventCode: REFUND_FAILED
  • originalReference: The pspReference of the payment you are refunding.
  • pspReference: Our unique identifier for the refund that failed.

Most of the time Adyen can fix the issue, so that the shopper will eventually receive the funds. Sometimes, however, you need to take action yourself. To learn why a refund can fail and what, if anything, you need to do in each case, refer to Failed captures and refunds.

Refunded reversed

If we try and refund a payment, and the shopper's account is no longer valid (for example, they have closed their account), we send you a notification that contains:

  • eventCode: REFUNDED_REVERSED
  • originalReference: The pspReference of the refund that failed.
  • success: true

This means that the funds have been returned to Adyen, and are back in your merchant account.

See also