How to refund a payment

Primer enables you to fully or partially refund a settled payment across all your processors in a unified way.

In order to refund a payment, its status must be SETTLED. Once refunded, the payment will continue to have:

  • status = SETTLED
  • amount = original settled amount

but the payment object will be updated to show the refund details. Specifically:

  • the processor refund transaction will be part of the transactions list
  • processor.amountRefunded will be set to the total refunded amount

Below is an example payment object that has been refunded:

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
{    "id": "ehFTWmh3",    "date": "2022-12-05T12:35:46.204690",    "amount": 11000,    "currencyCode": "GBP",    "orderId": "39526",    "status": "SETTLED",    "paymentMethod": {        "paymentMethodToken": "Q-FcqfYCSa2hh2eMqZBjfHwxNjcwMjQzNzQ1",        "isVaulted": false,        "analyticsId": "fm1_-IOlVoK9eY09EP6-YV8w",        "paymentMethodType": "PAYMENT_CARD",        "paymentMethodData": {            "last4Digits": "1111",            "first6Digits": "411111",            "expirationMonth": "12",            "expirationYear": "2025",            "cardholderName": "Joe Bloggs",            "network": "Visa",            "isNetworkTokenized": false,            "binData": {                "network": "VISA",                "issuerCountryCode": "US",                "issuerName": "JPMORGAN CHASE BANK, N.A.",                "regionalRestriction": "UNKNOWN",                "accountNumberType": "UNKNOWN",                "accountFundingType": "UNKNOWN",                "prepaidReloadableIndicator": "NOT_APPLICABLE",                "productUsageType": "UNKNOWN",                "productCode": "UNKNOWN",                "productName": "UNKNOWN"            }        },        "threeDSecureAuthentication": {            "responseCode": "NOT_PERFORMED"        }    },    "processor": {        "name": "STRIPE",        "processorMerchantId": "acct_1MBdnMJdRxA3z8D5",        "amountCaptured": 11000,        "amountRefunded": 11000    },    "transactions": [        {            "date": "2022-12-05T12:35:47.078285",            "amount": 11000,            "currencyCode": "GBP",            "transactionType": "SALE",            "processorTransactionId": "pi_3MBdtgJdRxA3z8D50HwTkJ7A",            "processorName": "STRIPE",            "processorMerchantId": "acct_1MBdnMJdRxA3z8D5",            "processorStatus": "SETTLED"        },        {            "date": "2022-12-06T21:55:02.830051",            "amount": 11000,            "currencyCode": "GBP",            "transactionType": "REFUND",            "processorTransactionId": "re_3MBdtgJdRxA3z8D50WBvqRLy",            "processorName": "STRIPE",            "processorMerchantId": "acct_1MBdnMJdRxA3z8D5",            "processorStatus": "SETTLED"        }    ]}
json
copy

All refund calls are sent to the processor used in the authorization and capture request.

To check the refund status and details of a payment, you can use:

Refund a payment with Primer in three ways:

⌛️

Payments timeline

Manually refund a payment from an easy-to-use dashboard.

🖥

Workflows

Automate sophisicated payment flows to refund your payments.

👨🏻‍💻

Payments API

Programmatically refund your payments via API based on your business logic.

Refund a payment via the Payments Timeline

This is useful to enable your customer support to provide refunds directly from within the dashboard.

Manually refund a specific payment from the Payments Timeline in the Primer Dashboard.

Select the payment from the list view and navigate to the specific payment details page. If the payment has SETTLED, the Refund button in the top right corner will be enabled.

Refund button enabled

Once the Refund button is selected, specify the amount you want to refund in the modal.

Specify refund amount

After the refund is processed and complete, the refunded amount will appear next to the payment amount at the top of the payment details page.

Refunded example

Once the total settled amount is refunded, you will no longer be able to refund the payment and the Refund button will become disabled.

Refund a payment via Workflows

Use Workflows to set up business logic on when and how to refund a payment - without writing a single line of code. Simply add the "Refund payment" Action from the Primer Payments app to a workflow.

Learn more here about the Payments app and the "Refund payment" Action.

Asynchronous refund considerations still apply to the "Refund payment" Action in Workflows. It’s recommended to use Primer’s payment webhooks to confirm when the payment is refunded.

Refund a payment via Payments API

Refund a payment using the Payments API - see the API reference for the details.

12345
curl --request POST \     --url https://api.sandbox.primer.io/payments/<YOUR_PAYMENT_ID>/refund \     --header 'X-API-KEY: <YOUR_API_KEY>' \     --header 'X-API-VERSION: 2.2' \     --header 'X-Idempotency-Key: <YOUR_IDEMPOTENCY_KEY>'
bash
copy

Include the Primer payment ID in the request, which you will have received as part of the payment creation and authorization.

The payload sent in the refund request is completely optional and can be used to partially refund the payment. See the section below to learn more about partial refunds. You can also provide a reason input that can be used for your own records.

Handle asynchronous refund

Refunds are usually processed asynchronously. Once the refund request has been made, the refund, and movement of funds back to the customer, will occur and could take days.

As a result, it’s recommended to set up the refund webhook notification event. Primer notifies you with a PAYMENT.REFUND webhook event when a refund request has been fully processed by a payment processor and the refund has reached a final state.

To determine whether the refund was successful, check the most recent refund transaction in the transactions list. Below is an example of a processor refund transaction:

12345678910
{    "date": "2022-12-06T21:55:02.830051",    "amount": 11000,    "currencyCode": "GBP",    "transactionType": "REFUND",    "processorTransactionId": "re_3MBdtgJdRxA3z8D50WBvqRLy",    "processorName": "STRIPE",    "processorMerchantId": "acct_1MBdnMJdRxA3z8D5",    "processorStatus": "SETTLED"}
json
copy
  • If transactionType = REFUND and processorStatus = SETTLED, the refund was successful and the funds have been returned to the customer
  • If transactionType = REFUND and processorStatus = FAILED, the refund was unsuccessful

Read more here on how to handle webhooks.

Partial refund

Not all processors and payment methods support partial refunds. Please see the details of the specific processor or payment method to learn more about the capabilities supported.

You can partially refund a payment by setting the optional amount input to less than the full settled amount.

For subsequent refund requests, the default amount is then calculated by <amount settled> - <amount already refunded>.

You will not be able to have partial refunds that sum to a greater amount than the settled amount.