Skip to main content

Prerequisites

  • An active Payrails session (see Quick Start)
  • A session init payload with vaultConfiguration and a saveInstrument link (provided by the Payrails backend — contact Payrails to enable vault configuration for your merchant account)
  • Kotlin + Jetpack Compose for rendering the card form

Steps

1. Initialize a session

2. Create a card form (no payment button required)

A CardPaymentButton is not needed for tokenization. The card form collects and validates card fields independently.

3. Render the card form and a save button

session.tokenize(...) is the primary tokenization API (mirroring the iOS SDK). TokenizationRequest.Card(cardForm) selects the card currently entered in the form.

Callback variant (without coroutines)

If you are not calling from a coroutine, use the callback overload. Exactly one of the three callbacks fires once, on the main thread:
onCancelled fires only on cancellation (coroutine/session-scope) — card validation and network failures are delivered to onFailed.
ShortcutcardForm.tokenize(options) is a convenience wrapper equivalent to session.tokenize(TokenizationRequest.Card(cardForm), options). Use whichever reads better in your code.

4. Choose a FutureUsage value

5. Use the returned instrument ID

The response.id is the instrument identifier. Pass it to setStoredInstrument for future payments, or use it with the instrument management API:

Tokenize with Google Pay

Google Pay tokenization uses the same session.tokenize(...) API with a TokenizationRequest.GooglePay case. Because a Google Pay token can only be obtained through an Activity-result launcher that Android requires to be registered up front, you create a presenter in your Composable and pass it to tokenize:
Tapping the button opens the Google Pay sheet; on authorization the SDK saves the instrument and returns a SaveInstrumentResponse. User dismissal cancels (the callback overload’s onCancelled, or a CancellationException from the suspend variant). For a compliant, Google-branded button with no wiring, use GooglePayTokenizeButton instead — it renders only when Google Pay is available for the session:
Google’s brand guidelines require the official Google Pay button to launch the Google Pay flow. Prefer GooglePayTokenizeButton (or a Google Pay–branded button) over a fully custom button.

Verify it worked

Check that the response contains a valid ID and "active" status:

Troubleshooting

Problem: PayrailsError.invalidCardData is thrown Solution: Card form validation failed. The form automatically shows inline field errors — the user needs to correct the highlighted fields before retrying. No manual error display is needed. Problem: PayrailsError.missingData("Vault configuration with providerConfigId is required...") Solution: The session init payload does not include vaultConfiguration. Contact Payrails to enable vault configuration for your merchant account. Problem: PayrailsError.missingData("holderReference is required...") Solution: The session init payload does not include holderReference. Ensure your client-init request includes a holder reference.

Alternative: pay directly with the saved instrument

Once a card is tokenized, you can charge it through the button flow shown above (payButton.setStoredInstrument(...) + payButton.Render()), or skip the button entirely and charge it from your own UI with PayrailsPaymentLauncher:
launcher.authorize(storedInstrument = ...) is the way to charge an existing stored instrument from a custom layout or ViewModel-driven flow — and, because the launcher holds a presenter, it transparently handles a 3DS step-up if the issuer requires one. See How to Run a Payment Without an SDK Button.

See also

Last modified on September 30, 2026