> ## 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.

# API reference

> Every public type of the Tap on Phone Android SDK: Payments, Checkout.Contract, CheckoutRequest, CheckoutConfig, PaymentResult, ReadyResult, ErrorCode, Environment, AntennaSetup, Nfc and DeviceReadiness.

The public surface of the SDK. Everything lives under `com.rinne.sdk`, and the managed checkout under `com.rinne.sdk.checkout`. Anything not on this page is internal and may change without notice.

## Payments

`object com.rinne.sdk.Payments`, the terminal's lifecycle.

```kotlin theme={null}
fun getReady(
    context: Context,
    accessTokenProvider: suspend () -> String,
    config: CheckoutConfig = CheckoutConfig(),
    environment: Environment = Environment.default,
    installerPackageNames: List<String> = emptyList(),
    onResult: (ReadyResult) -> Unit,
)

fun dispose()
fun checkDeviceReadiness(context: Context): DeviceReadiness

val isReady: Boolean
val isPreparing: Boolean
val isCharging: Boolean
val checkoutConfig: CheckoutConfig
```

<ParamField path="accessTokenProvider" type="suspend () -> String" required>
  Supplies the token your backend minted at `POST /v1/terminal/token`. Called once per handshake and never stored. If the backend refuses it mid-handshake the SDK asks once more and retries that request, then reports `ACCESS_TOKEN_REJECTED`.
</ParamField>

<ParamField path="config" type="CheckoutConfig" default="CheckoutConfig()">
  The branding of the screens and the certified PIN pad. Applied when the terminal is created; to change it, `dispose()` and prepare again. See [Customization](/tap-on-phone/android/customization).
</ParamField>

<ParamField path="environment" type="Environment" default="Environment.default">
  The Rinne environment to prepare against. Must be one the installed artifact reaches, or `getReady` throws `IllegalStateException`.
</ParamField>

<ParamField path="installerPackageNames" type="List<String>" default="emptyList()">
  Installer packages to accept besides Google Play, for fleets distributed through a device-management tool. A build installed by an unlisted installer fails attestation in production.
</ParamField>

<ParamField path="onResult" type="(ReadyResult) -> Unit" required>
  Delivered once, on the main thread.
</ParamField>

`getReady` is idempotent: on a prepared terminal it completes at once with `Ready`, and two concurrent calls share one handshake. `dispose()` releases the terminal so the next `getReady` creates a new one with the current `CheckoutConfig`.

The managed checkout, launched through `Checkout.Contract`, is the supported way to take a payment during the closed beta.

## Checkout.Contract

`class com.rinne.sdk.checkout.Checkout.Contract : ActivityResultContract<CheckoutRequest, PaymentResult>`

```kotlin theme={null}
private val checkout = registerForActivityResult(Checkout.Contract()) { result -> /* PaymentResult */ }
checkout.launch(request)

// Without registerForActivityResult (bridges):
val intent = Checkout.Contract().createIntent(context, request)
val result = Checkout.Contract().parseResult(resultCode, data)
```

The only way to open the managed checkout. The result travels through Android's activity-result machinery, so it survives the process being killed while the payment screen is up. Exactly one `PaymentResult` is delivered per launch, after the operator dismisses the outcome screen.

## CheckoutRequest

`data class com.rinne.sdk.checkout.CheckoutRequest`, one sale described.

| Field               | Type                 | Default    | Rules                                                                                  |
| ------------------- | -------------------- | ---------- | -------------------------------------------------------------------------------------- |
| `amountCents`       | `Long`               | required   | Positive. BRL only.                                                                    |
| `type`              | `TransactionType`    | `PURCHASE` | `REFUND` is a card re-tap for the full amount of a sale.                               |
| `paymentMethod`     | `PaymentMethod`      | required   | The operator's credit-or-debit choice, recorded as the transaction's payment method.   |
| `installments`      | `Int`                | `1`        | Values above 1 are relayed to the acquirer.                                            |
| `requestId`         | `String?`            | `null`     | Required on a purchase, absent on a refund. Your idempotency key.                      |
| `originalRequestId` | `String?`            | `null`     | Required on a refund, absent on a purchase. The sale's `requestId`.                    |
| `metadata`          | `Map<String, Any?>?` | `null`     | Stored with the transaction. Capped at 4 KB; rejected when a key looks like card data. |

A request that breaks these rules throws `IllegalArgumentException` before the screen opens.

## CheckoutConfig

`data class com.rinne.sdk.CheckoutConfig`, the branding of the screens and the PIN pad.

| Field              | Type             | Default      |
| ------------------ | ---------------- | ------------ |
| `primaryColor`     | `Int` (ARGB)     | `0xFF7A4CFF` |
| `headerTextColor`  | `Int` (ARGB)     | `0xFFFFFFFF` |
| `iconColor`        | `Int` (ARGB)     | `0xFF15181E` |
| `backgroundType`   | `BackgroundType` | `FULL`       |
| `displayFontResId` | `@FontRes Int?`  | `null`       |
| `labelFontResId`   | `@FontRes Int?`  | `null`       |
| `merchantName`     | `String?`        | `null`       |
| `tapTitle`         | `String?`        | `null`       |
| `tapSubtitle`      | `String?`        | `null`       |
| `pinPadType`       | `PinPadType`     | `SHIFTED`    |

`enum class BackgroundType { FULL, TRANSPARENT }` and `enum class PinPadType { SHIFTED, SHUFFLED }`. What each field does, with a live preview: [Customization](/tap-on-phone/android/customization).

## TransactionType and PaymentMethod

```kotlin theme={null}
enum class TransactionType { PURCHASE, REFUND }
enum class PaymentMethod { CREDIT, DEBIT }
```

## PaymentResult

`sealed interface com.rinne.sdk.PaymentResult`, delivered once per checkout.

| Variant     | Fields                                          | Meaning                                       |
| ----------- | ----------------------------------------------- | --------------------------------------------- |
| `Approved`  | `transactionId: String?`, `cardScheme: String?` | Authorised.                                   |
| `Declined`  | `transactionId: String?`, `code: ErrorCode`     | The issuer or the card refused.               |
| `Failed`    | `code: ErrorCode`, `message: String?`           | A technical fault.                            |
| `Cancelled` | `code: ErrorCode = CANCELLED`                   | Ended deliberately before an outcome existed. |

Every variant also carries `raw: String?`, a JSON snapshot of the card reader's response, and `diagnostics: EmvDiagnostics?`, decoded card diagnostics for support triage. Neither contains cardholder data. Full behaviour: [Results and errors](/tap-on-phone/android/results-and-errors).

## ReadyResult

```kotlin theme={null}
sealed interface ReadyResult {
    data object Ready : ReadyResult
    data class Failed(val code: ErrorCode, val message: String? = null) : ReadyResult
}
```

## ErrorCode and ErrorCatalog

`enum class com.rinne.sdk.ErrorCode`, thirteen values in a fixed order that only ever grows:

`TERMINAL_NOT_READY`, `ATTESTATION_FAILED`, `CARD_READ_TIMEOUT`, `PIN_FAILED`, `DECLINED_BY_ISSUER`, `NETWORK`, `CANCELLED`, `UNKNOWN`, `LOCATION_UNAVAILABLE`, `SECURE_ENTRY_BLOCKED`, `ACCESS_TOKEN_REJECTED`, `TAP_ON_PHONE_NOT_ENABLED`, `EMV_CONFIG_UNAVAILABLE`.

`ErrorCatalog[code]` returns an `ErrorInfo(message, retryHint, retriable)` with English defaults for hosts that build their own error screens. The managed checkout uses its own localized copy for the same codes. Meanings, retry rules and operator text: [Results and errors](/tap-on-phone/android/results-and-errors).

## Environment

```kotlin theme={null}
enum class Environment { LOCAL, DEV, SANDBOX, PRODUCTION }
```

The sandbox artifact reaches `LOCAL`, `DEV` and `SANDBOX`; the production artifact reaches `PRODUCTION` only. `Environment.supported` lists what the installed artifact reaches and `Environment.default` is its default, which for the sandbox artifact is `DEV`, so pass `SANDBOX` explicitly.

## AntennaSetup.Contract

`class com.rinne.sdk.checkout.AntennaSetup.Contract : ActivityResultContract<Unit, Boolean>`

Opens the antenna guide. Needs no terminal or token, reads no card data, inherits the last `CheckoutConfig`, and returns `true` when the merchant confirms the position with a test tap. See [Device setup](/tap-on-phone/android/device-setup).

## Nfc

`object com.rinne.sdk.Nfc`, platform helpers with no kernel and no credentials.

| Member                        | Returns         | Notes                                                                                                                               |
| ----------------------------- | --------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| `status(context)`             | `NfcStatus`     | `READY`, `DISABLED` or `UNAVAILABLE`.                                                                                               |
| `antennaInfo(context)`        | `AntennaInfo?`  | `null` below API 34 or when the device reports no antennas. Never guess a position in that case.                                    |
| `enableTapTest(activity) { }` | `Unit`          | Fires the callback when any contactless card touches the antenna; reads nothing. Pair with `disableTapTest(activity)` in `onPause`. |
| `keepAwake(activity)`         | `AutoCloseable` | Keeps the screen on until closed. The managed checkout does this itself.                                                            |

```kotlin theme={null}
data class AntennaInfo(
    val deviceWidthMm: Int,
    val deviceHeightMm: Int,
    val foldable: Boolean,
    val antennas: List<Antenna>,   // Antenna(xMm, yMm), from the top-left of the back
)
```

## DeviceReadiness

Returned by `Payments.checkDeviceReadiness(context)`.

```kotlin theme={null}
data class DeviceReadiness(val checks: List<ReadinessCheck>) {
    val blocking: List<ReadinessCheck>   // outcome FAIL on a blocking check
    val warnings: List<ReadinessCheck>   // outcome WARN
    val isReady: Boolean                 // no blocking failures
}

data class ReadinessCheck(val id: ReadinessCheckId, val outcome: ReadinessOutcome, val detail: String? = null)

enum class ReadinessCheckId { OS_PATCH_LEVEL, PLAY_SERVICES, CONNECTIVITY, NFC, LOCATION }
enum class ReadinessOutcome { PASS, WARN, FAIL }
```

`OS_PATCH_LEVEL` only warns; the other four block. Readiness is not attestation: a device can pass every check and still be refused with `ATTESTATION_FAILED`.

## RinneApplication

`abstract class com.rinne.sdk.RinneApplication : Application`. Subclass it and put your startup work in `onRinneCreate()`. `onCreate()` is final: the card reader runs its cryptography in an isolated process that re-enters `Application.onCreate`, and the SDK returns early there before any host code runs.

## Next steps

<CardGroup cols={2}>
  <Card title="Quickstart" icon="rocket" href="/tap-on-phone/android/quickstart">
    Every type above, in the order you use them.
  </Card>

  <Card title="Simulator" icon="play" href="/tap-on-phone/android/simulator">
    See what each `CheckoutConfig` and `CheckoutRequest` field does on the screens.
  </Card>
</CardGroup>
