Create Refund

5 minute read

Ping Payments supports both full and partial Refunds through a single, unified API endpoint — regardless of the original Payment method. Most Refunds are processed asynchronously. Once a Refund is initiated, Ping will send callback notifications to your system, following the same pattern as with the InitiatePayment endpoint.

Refund Flow Overview

This sequence diagram shows the basic API calls and responses for Refunds. Later sections cover each step in depth, with full schemas, examples, and callback details.

API Parameters

Request Parameters

NameDescription
amountThe amount in Minor Currency Unit which is to be refunded.
currencyISO 4217 currency code for the Refund (e.g. EUR, SEK). Must be the same as the Payment currency.
descriptionShort description to clarifying why the Refund is performed
messageMessage that will be shown to the original Payer
order_itemsAn updated version of how the order_item list will look after that the Refund has been created. It is important that the sum of the order_items and the provided amount sums to the full Payment amount.

This parameter is crucial to perform partial Refunds and is how we can refund certain order_items or part of order_items.
reasonEnum which describes the reason for refund.

Note: Unlike from the InitiatePayment, the callback URL is not set when creating the Refund. Instead it's configured on Tenant level. See Update Tenant to learn how to configure this callback URL.

Response Parameters

NameDescription
idThe ID of the Refund. This will be provided in the Refund status callback.
currencyThe currency of the Refund, same as in the request parameter
amountThe amount of the Refund, same as in the request parameter
providerThe provider which facilitated the Refund. Will be the same as the provider Payment that is being refunded.
statusThe initial status of the Refund.

Example - Full Refund

Minimal example displaying how to perform a full Refund.

In this example, lets assume that the full Payment amount is 299.00 SEK.

Request

curl --location 'https://sandbox.pingpayments.com/payments/api/v1/payment_orders/<YOUR-PAYMENT-ORDER-ID>/payments/<YOUR-PAYMENT-ID>/refund' \
--header 'tenant_id: <YOUR-TENANT-ID>' \
--header 'x-api-secret: <YOUR-API-SECRET>' \
--header 'Content-Type: application/json' \
--data '{
    "amount": 29900,
    "currency": "SEK",
    "description": "Test refund",
    "reason": "requested_by_customer",
    "order_items": []
}'

In example order_items is an empty list and the amount is the full Payment amount, which is indicating that we are performing a full Refund.

Response

{
    "id": "e2fbcec8-4858-40f0-ba7f-7fcf82653f58",
    "status": "PENDING",
    "currency": "SEK",
    "provider": "swish",
    "amount": 29900
}

Example - Partial Refund

Minimal example displaying how to perform a partial Refund.

In this example, let's assume that the full Payment amount is 299.00 SEK and only want to refund 100.00 SEK.

Request

curl --location 'https://sandbox.pingpayments.com/payments/api/v1/payment_orders/<YOUR-PAYMENT-ORDER-ID>/payments/<YOUR-PAYMENT-ID>/refund' \
--header 'tenant_id: <YOUR-TENANT-ID>' \
--header 'x-api-secret: <YOUR-API-SECRET>' \
--header 'Content-Type: application/json' \
--data '{
    "amount": 10000,
    "currency": "SEK",
    "description": "Test refund",
    "reason": "requested_by_customer",
    "order_items": [
      {
          "amount": 19900,
          "metadata": {},
          "name": "Test Purchase",
          "merchant_id": <YOU-MERCHANT-ID>,
          "vat_rate": "0",
          "tags": []
        }
		]
}'

In this example, an amount less than the original Payment amount was provided. This requires a new set of order_items to be provided.

Notice that the Refund amount and order_items amount sum to the original Payment amount.

Once this PaymentOrder is Settled, only 199.00 SEK will be allocated to the Merchant instead of the original 299.00 SEK.

Response

{
    "id": "e2fbcec8-4858-40f0-ba7f-7fcf82653f58",
    "status": "PENDING",
    "currency": "SEK",
    "provider": "swish",
    "amount": 10000
}

Status callback

Ping will post callbacks regarding the Refund status to the configured callback URL to let you now the exact state of the refund enabling you to react accordingly.

Note: To ensure robust callbacks ping will make up to 20 attempts with exponential back off to make sure the callback is allays delivered.

Possible refund statuses

StatusTypeDescription
PENDINGnon-terminatedIf the refund is successfully initiated the status will transition to PENDING, which indicates that the Payment is ongoing.
COMPLETEDterminatedThe original payer has successfully been refunded
DECLINEDterminatedThe refund was declined by the original Payment provider. See details field information of why the Refund was declined.
FAILEDterminatedThe original Payment provider failed to perform the Refund. See details field information of why the Refund was failed.

Note: Once a Refund is terminated, no more status-callbacks will be sent regarding that Refund