Payments

Refund payment (payment reversal)

POST /v2/payments/reversal Bearer token

This endpoint enables you to initiate a full or partial refund for a specific payment. It allows you to process payment reversals efficiently, ensuring that refunds are handled seamlessly.


Request

Method: POST URL: https://api.sandbox.bobpay.co.za/v2/payments/reversal


Request body parameters

Key Description Type Required
id ID of the payment record to refund. integer Conditional*
custom_payment_id Your custom identifier for the payment to refund. string Conditional*
payment_method_id Payment method record ID, used together with payment_method. integer Conditional*
payment_method The payment method of the payment, used together with payment_method_id. string Conditional*
reversal_amount The amount to refund, for partial refunds. Must be greater than zero and may not exceed the amount still outstanding on the payment. Defaults to the full payment amount. float No
reverse_directly_to_bank If true, the funds are reversed directly to the payer's bank or card instead of their Bob Pay account balance. Only supported for card, Apple Pay, Google Pay, Scan to Pay and Capitec Pay payments. Defaults to true for those payment methods and to false for all others. Set it to false on a second or later refund of the same payment (see "Partial refunds" below). boolean No

* Note: Identify the payment using one of id, custom_payment_id, or payment_method_id together with payment_method.

Example:

{
    "id": 72052
}

Partial refunds

Partial refunds are supported. Send reversal_amount with the amount you want to refund — that is the only additional field required. Identify the payment exactly as you would for a full refund. Leave reversal_amount out to refund the full amount.

{
    "id": 72052,
    "reversal_amount": 50.00
}

Rules

  • reversal_amount must be greater than zero and may not exceed the original payment amount, or the amount still outstanding if the payment is already partially_refunded.
  • The payment must have a status of success or partially_refunded. A payment that is already refunded cannot be refunded again.
  • After the first partial refund, the payment and its payment intent move to partially_refunded.
  • Once the partial refunds together add up to the full payment amount, the payment and its payment intent move to refunded.
  • Your account balance must cover the refund amount plus the reversal fee.
  • Test payments and account top-up payments cannot be refunded.

Second and later refunds

Only one refund per payment can be sent back to the payer's bank or card. On any refund after the first, set reverse_directly_to_bank to false so that the refund is credited to the payer's Bob Pay account balance.

{
    "id": 72052,
    "reversal_amount": 50.00,
    "reverse_directly_to_bank": false
}

If you leave reverse_directly_to_bank out, it defaults to true for card, Apple Pay, Google Pay and Capitec Pay payments, and the request fails with cannot reverse a <payment method> payment more than once.

Scan to Pay is the exception: it accepts more than one refund to the payer's bank, but only within 72 hours of the payment. After 72 hours the refund is credited to the payer's Bob Pay account balance instead. Check reversed_directly_to_bank in the response to confirm where the funds were sent.

Refunds that complete asynchronously

For Scan to Pay and Capitec Pay refunds to bank, the refund is confirmed by the bank after the request returns. The payment moves to refund_pending first, and then to its final refunded status once the bank confirms the refund. Capitec Pay accepts only one refund per payment.


Response

Status code: 200 OK Content-Type: application/json



Response fields

Key Description Type
payment_method Object with details about the reversed payment. object
payment_method.id Unique payment record ID. integer
payment_method.payment_intent_id Payment intent ID linked to this payment. integer
payment_method.payment_intent_reference Short payment intent reference. string
payment_method.account_id Originating account ID. integer
payment_method.account Object with originating account details. object
payment_method.recipient_account_id Recipient account ID. integer
payment_method.recipient_account Object with recipient account details. object
payment_method.amount Amount refunded. float
payment_method.status Status of the refund (should be "refunded"). string
payment_method.transaction_date Transaction date and time. string (date)
payment_method.type Type of transaction (e.g., "payment"). string
payment_method.time_created Time created. string (date)
payment_method.time_modified Time last modified. string (date)
payment_method.custom_payment_id Custom payment identifier. string
payment_method.jurisdiction Payment jurisdiction. string
payment_method.card_association Card association (e.g., VISA). string
payment_method.is_debit_card True if debit card used. boolean
reversed_directly_to_bank True if funds were reversed directly to bank. boolean

Note:

  • The fields of the payment_method object depend on the payment method being refunded. The example above shows a card refund; fields such as jurisdiction, card_association, and is_debit_card are card-specific.
  • The response also contains deprecated PaymentMethod and ReversedDirectlyToBank keys (duplicates of payment_method and reversed_directly_to_bank). Ignore these; they will be removed in a future version.

Common errors

All of the errors below are returned with status code 400.

Message Cause
id or custom_payment_id or payment_method_id and payment_method is required The request does not identify a payment.
reversal_amount must be greater than 0 reversal_amount was zero or negative.
Reversal amount cannot be greater than the payment amount reversal_amount is more than the original payment.
Reversal amount cannot be greater than the remaining payment amount The payment is partially_refunded and reversal_amount is more than the amount still outstanding.
Payment has already been refunded The payment is already fully refunded.
Only successful payments or partially refunded payments can be reversed The payment status is not success or partially_refunded.
cannot reverse a <payment method> payment more than once A second refund was requested with reverse_directly_to_bank set to (or defaulting to) true. Send false instead.
Only card, scan to pay, and PayShap RTP payments can be reversed to bank reverse_directly_to_bank was set to true for a payment method that cannot refund to bank.
Unable to process the refund due to insufficient account balance Your balance does not cover the refund amount plus the reversal fee.
Test payments cannot be reversed The payment belongs to a test payment intent.
Account topup payments cannot be refunded The payment was an account top-up.
the specified payment does not belong to this account The payment was not received by your account.