Skip to main content

Refunds

Payment may be refunded multiple times for a total amount not exceeding the payment amount and it is allowed only for payments in status CONFIRMED. Paynow accepts refunds with a minimum amount 1 PLN for CARD payment, for other 0.01 PLN.

Notice

To be able to make a standard refund by API your shop must have enabled "Once a day" variant of payout schedule for given shop. The funds needed to make the return will be taken from your balance.

If there are not enough funds on your balance to make a refund (e.g. your shop has few or no recent sales), you can use a refund with bank transfer. Such refund is not taken from your balance – it is funded by a dedicated bank transfer made for that specific refund.

You can also receive notifications when a refund reaches its final status.

Awaiting refunds - optional​

Awaiting refund is a special type of refund which can be initialized even if the refund amount exceeds your balance. After initialization, such refund will be in NEW status. When enough funds have been accumulated on your balance, refunds will be processed using FIFO algorithm (that means the refunds are being processed in the order in which they were initialized).

If you do not accumulate the necessary funds for a refund on your balance for 120 hours (5 days, default value), the refund status will change to CANCELLED.

You can change the time after which awaiting refunds will be cancelled - the unit of this parameter is an hour.

To enable this feature for your shop and/or change the default awaiting refund cancellation time (optional) go to Settings > Awaiting refunds tab in the Merchant Panel.

Awaiting refund or refund with bank transfer?

An awaiting refund waits for funds from future sales to accumulate on your balance. A refund with bank transfer does not use your balance at all – it is funded by a bank transfer made for that specific refund. Use it when you do not expect enough sales to cover the refund in time.

Flow diagram​

The following picture shows the positive refund flow:

business flow image

Flow of statuses​

The following picture shows all the statuses that a refund can take, and possible transitions between those statuses:

business flow image

Explanation:

CodeDescription
NEWRefund has been accepted.
PENDINGPaynow starts to process the request.
SUCCESSFULRefund has been successfully processed by Paynow and money has been transferred to the buyers account.
FAILEDRefund encountered a problem during the processing. Money has not been transferred to the Buyer.
CANCELLEDRefund was cancelled. Money has not been transferred to the Buyer. Only refunds in status NEW can be cancelled.

Make a refund​

For the purpose of this guide, let's assume that your keys are:

  • Api-Key = 97a55694-5478-43b5-b406-fb49ebfdd2b5
  • Signature-Key = b305b996-bca5-4404-a0b7-2ccea3d2b64b

Let's also assume, that paymentId is NOR3-FUN-D4U-LOL

Step 1: Prepare a refund request message. Throughout this example, we'll use a simple message containing only required fields which look as follows:

{
"amount": 100,
"reason": "RMA"
}

The provided amount should be given in the smallest unit of refund currency (grosz in case of PLN). This means that the above request defines a refund for 1.00 PLN. Description field should contain reason of refund. Full specification for refund request message can be found below.

Optionally, you can add the notificationUrl field. If provided, Paynow will send a notification to this address when the refund reaches its final status. See Refund status notifications.

{
"amount": 100,
"reason": "RMA",
"notificationUrl": "https://shop.example.com/paynow/refund-notifications"
}

Step 2: Attach Api-Key header with the value of Api-Key available in the Merchant Panel.

Step 3: Calculate signature and attach it as the Signature header. For given example correct signature is o5HQfxngBqr68sLOEtJu0fd1Cl/GzfehZEswk6KMb0w=

Important

If you are trying to calculate the signature from the example in your code and are getting a different result, make sure that your JSON message is formatted the same way as the message in the example, i.e. with four-space indentation and no newline character at the end.

Step 4: Generate random string with maximum length of 45 characters for an Idempotency-Key header.

Step 5: Make a POST with prepared message on refund request endpoint

curl --location 'https://api.sandbox.paynow.pl/v3/payments/NOM3-VWX-YS7-J43/refunds' \
--header 'Api-Key: 97a55694-5478-43b5-b406-fb49ebfdd2b5' \
--header 'Signature: o5HQfxngBqr68sLOEtJu0fd1Cl/GzfehZEswk6KMb0w=' \
--header 'Content-Type: application/json' \
--data '{
"amount": 100
}'
Notice

Bear in mind, that the request must include Host and Accept headers as described here. They are not listed above explicitly as the curl command includes them by default.

Step 6: Handle the returned response:

{
"refundId": "RE6-9YD-ULU-MRL",
"status": "PENDING"
}

The response contains ID of the refund generated by Paynow and the current status of the refund. Returned refundId should be saved by Merchant for further reference.

Step 7: Query the status of refund. See get refund status endpoint description.

  curl --location --request GET 'https://api.sandbox.paynow.pl/v3/refunds/RE6-9YD-ULU-MRL/status' \
--header 'Api-Key: 97a55694-5478-43b5-b406-fb49ebfdd2b5' \
--header 'Idempotency-Key: 6228e8f1-4fd9-40bc-9660-37b03c968590' \
--header 'Signature: Aqy2xIQAZghJX4jdzeMZa7I/3WcI2saIAt0qzLoZiMU='

Instead of querying the status, you can pass notificationUrl in Step 1 and wait for a notification.

To see more details about statuses, please refer to the Flow Diagram

Cancel awaiting refund​

If you have enabled awaiting refunds mechanism every new balance refund will be executed with some delay. When refund is in status NEW (awaiting) you can cancel it using an API request. The same request cancels a refund with bank transfer that is still waiting for the bank transfer. Below you can see how to do it.

For this guide purposes let's assume that:

  • Your Api-Key is: 97a55694-5478-43b5-b406-fb49ebfdd2b5
  • Your Refund Id is: RE1-K7E-206-31J

Step 1: Generate random string with maximum length of 45 characters for an Idempotency-Key header.

Step 2: Make this call to our API:

curl --location --request POST 'https://api.sandbox.paynow.pl/v3/refunds/RE6-9YD-ULU-MRL/cancel' \
-H 'Api-Key: 97a55694-5478-43b5-b406-fb49ebfdd2b5' \
-H 'Signature: e3JjMoexXydWjfBX8ArbExJu8YhTycwKEk0uWc9rXuM='

Please, keep in mind that with this call you can only cancel refunds that are in NEW status: awaiting refunds from balance and refunds with bank transfer for which the transfer has not been booked yet.

Refund with bank transfer​

Refund with bank transfer lets you refund a payment even if there are not enough funds on your balance. Instead of taking the money from your balance, Paynow returns the details of a bank transfer that must be made to cover the refund. When the transfer is booked on the Paynow refund account, the refund is processed and the money is transferred to the buyer.

How it works​

  1. (Optional) You request a standard refund and receive the INSUFFICIENT_BALANCE_FUNDS error, which means that there are not enough funds on the balance.
  2. You request a refund with bank transfer and set how long Paynow should wait for the transfer (validityTime, from 3 to 10 days).
  3. Paynow creates the refund in NEW status and returns the bank transfer details (bankTransferData): account number, amount, currency, title and recipient details. The refund is not processed yet.
  4. You make the bank transfer.
  5. When the transfer is booked on the Paynow refund account, the refund is processed and the money is transferred to the buyer.
  6. If the transfer is not booked within validityTime, the refund is cancelled (CANCELLED).
  7. If you provided notificationUrl, Paynow sends a notification when the refund is completed, failed or cancelled.
Important

The transfer must exactly match the returned bankTransferData – the same amount and currency, to the given account number and with the given title. Otherwise Paynow will not be able to match the transfer with the refund and the refund will not be processed.

Make a refund with bank transfer​

Required headers are the same as for a standard refund: Api-Key, Signature, Idempotency-Key, Content-Type, Host and Accept.

Step 1: Prepare a refund request message:

{
"amount": 10000,
"reason": "RMA",
"validityTime": 432000,
"notificationUrl": "https://shop.example.com/paynow/refund-notifications"
}
  • amount (required) – refund amount in the smallest currency unit (e.g. grosz for PLN).
  • validityTime (required) – time in seconds that Paynow waits for the bank transfer (259200 to 864000, i.e. from 3 to 10 days).
  • reason (optional) – refund reason (RMA, REFUND_BEFORE_14, REFUND_AFTER_14, OTHER).
  • notificationUrl (optional) – URL for refund status notifications.

Step 2: Attach Api-Key header, calculate signature and attach it as the Signature header, generate an Idempotency-Key.

Step 3: Make a POST with prepared message on refund with bank transfer endpoint:

curl --location 'https://api.sandbox.paynow.pl/v3/payments/NOM3-VWX-YS7-J43/refunds/accounts' \
--header 'Api-Key: 97a55694-5478-43b5-b406-fb49ebfdd2b5' \
--header 'Signature: {calculated-signature}' \
--header 'Idempotency-Key: {idempotency-key}' \
--header 'Content-Type: application/json' \
--data '{
"amount": 10000,
"reason": "RMA",
"validityTime": 432000,
"notificationUrl": "https://shop.example.com/paynow/refund-notifications"
}'

Step 4: Handle the returned response:

{
"refundId": "RE6-9YD-ULU-MRL",
"status": "NEW",
"bankTransferData": {
"accountNumber": "{refund-account-number}",
"amount": 10000,
"currency": "PLN",
"title": "{transfer-title}",
"recipientName": "{recipient-name}",
"recipientAddress": "{recipient-address}"
}
}

Step 5: Make the bank transfer using bankTransferData – the exact amount and currency, to the given account number and with the given title.

Step 6: Wait for a notification or query the refund status as described in Make a refund, Step 7. Until the transfer is booked, the refund stays in NEW status.

To cancel a refund with bank transfer before the transfer is booked, use the cancel request.

Refund status notifications​

Paynow can notify you when a refund reaches its final status, in the same way as for payments. Notifications work for all types of refunds. They are especially useful for refunds with bank transfer and awaiting refunds, which may be completed even several days after they were requested – instead of querying the refund status repeatedly, you can rely on the notification.

To receive notifications, provide the optional notificationUrl field when you request a refund – both a standard refund (including an awaiting refund) and a refund with bank transfer. The address is set for each refund separately. If you do not provide it, no notifications will be sent for that refund.

Notifications are sent only when the refund changes its status to one of the final statuses:

CodeDescription
SUCCESSFULRefund has been successfully processed and money has been transferred to the buyer.
FAILEDRefund encountered a problem during the processing.
CANCELLEDRefund was cancelled via API or because validityTime has expired.

Paynow makes a POST request with Content-Type: application/json and Signature header to the given notificationUrl:

{
"refundId": "RE6-9YD-ULU-MRL",
"status": "SUCCESSFUL"
}

When status is FAILED, the notification also includes failureReason (CARD_BALANCE_ERROR, BUYER_ACCOUNT_CLOSED or OTHER):

{
"refundId": "RE6-9YD-ULU-MRL",
"status": "FAILED",
"failureReason": "OTHER"
}
  • Verify the Signature header in the same way as for payment notifications – see Notifications signature. If the signature does not match, do not process the message.
  • Respond with 200 OK or 202 Accepted and an empty body. Any other response is treated as a delivery failure.
  • Failed deliveries are retried according to the same schedule as for payments. If all attempts fail, query the refund status.
  • The same notification may be delivered more than once – make sure your handler is idempotent.