> ## Documentation Index
> Fetch the complete documentation index at: https://docs.rinne.com.br/llms.txt
> Use this file to discover all available pages before exploring further.

# Refunds

> Refund a Tap on Phone sale with a card re-tap through the same checkout contract, or from your backend through the transactions API.

A Tap on Phone refund is a card re-tap: the cardholder presents the same card again and the full amount of the sale goes back to it. You launch the same `Checkout.Contract` you use for a sale, with `type = REFUND` and the sale's `requestId` as `originalRequestId`, and you receive the same `PaymentResult`.

## Refund with a card re-tap

```kotlin theme={null}
import com.rinne.sdk.TransactionType
import com.rinne.sdk.checkout.CheckoutRequest

checkout.launch(
    CheckoutRequest(
        amountCents = sale.amountCents,          // the full amount, always
        type = TransactionType.REFUND,
        paymentMethod = sale.paymentMethod,      // the same modality as the sale
        originalRequestId = sale.requestId,      // the purchase this returns
    ),
)
```

The rules the SDK enforces before anything reaches the card reader:

| Rule                                         | What happens otherwise                                                                                           |
| -------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| `originalRequestId` is required              | `IllegalArgumentException` before the screen opens                                                               |
| `requestId` is absent on a refund            | `IllegalArgumentException` before the screen opens                                                               |
| `amountCents` is the full amount of the sale | The refund is refused; partial refunds are not accepted on Tap on Phone                                          |
| One completed refund per sale                | Another refund is refused once one refund of the sale has completed; a declined or failed attempt can be retried |

The SDK keeps no history. The `requestId` of the sale comes from your own order records, which is also where you decide whether a sale may still be refunded.

### What the screens show

Every headline changes with the transaction type, in the device language: "Aproxime para estornar", "Processando estorno", "Estorno aprovado" (or "Tap to refund", "Processing refund", "Refund approved"). The descriptor under the amount reads "Estorno · Crédito · à vista", and the certified PIN pad shows "Estorno" under the amount when the card asks for a PIN, so a PIN prompt is never mistaken for a charge. Your `tapTitle` still wins over the default headline.

Walk through a refund in the [simulator](/tap-on-phone/android/simulator): choose **REFUND** in the Sale section.

### Handle the result

The same `when` you use for a sale applies:

```kotlin theme={null}
private val checkout = registerForActivityResult(Checkout.Contract()) { result ->
    when (result) {
        is PaymentResult.Approved -> markRefunded(sale, result.transactionId)
        is PaymentResult.Declined -> showDeclined(result.code)
        is PaymentResult.Failed -> showError(result.code, result.message)
        is PaymentResult.Cancelled -> Unit
    }
}
```

`Approved` means the refund was authorised and registered with Rinne, linked to the sale through the `originalRequestId` you sent. Confirm it on the API by looking the sale up with its `requestId`; a [`transaction.status-changed`](/guides/webhooks) webhook fires when the sale's status changes.

<Note>
  `Declined` and `Failed` are different answers. A declined refund means the issuer refused it, and the sale keeps its status. A failed refund is a technical fault, so the operator can try again where the code allows it, exactly as for a sale.
</Note>

## Refund from your backend

When the cardholder is not present, refund the sale from your backend through the transactions refund endpoint, `POST /v1/merchants/{merchantId}/transactions/{transactionId}/refunds`, for the full amount. The standard refund rules apply: the sale must be approved, it can have only one completed refund, and the refund follows the sale's settlement window. See [Transactions](/concepts/transactions) for the refund lifecycle and the [API reference](/api-reference/introduction) for the request.

<Warning>
  Refund the full amount either way. A refund request for less than the sale amount is refused for Tap on Phone sales, on the device and on the API.
</Warning>

## Next steps

<CardGroup cols={2}>
  <Card title="Results and errors" icon="circle-check" href="/tap-on-phone/android/results-and-errors">
    Every `PaymentResult` variant and `ErrorCode`, and the retry rule for each.
  </Card>

  <Card title="Testing in the sandbox" icon="flask" href="/tap-on-phone/android/testing">
    Which amounts approve, decline or fail in the sandbox.
  </Card>
</CardGroup>
