Tokenization

Before Spreedly can run a transaction against configured payment gateways, merchants must securely collect and store their users' payment method information.

Tokenization is the process of safely capturing this sensitive cardholder data, including card number and CVV, and exchanging it for a secure, non-sensitive payment method token. Spreedly manages the details of securely storing this data in our vault, ensuring that raw card data never touches merchant servers or enters application memory. This can help to drastically reduce PCI compliance of a merchant environment, however, it is ultimately up to each merchant to evaluate what level of PCI compliance is required for their business.

Spreedly provides multiple methods to tokenize users' cardholder data as SDKs. When a user submits their payment details through any of these SDKs, no purchase transactions are immediately executed. Instead, merchants receive a tokenized payment method which can then be used to invoke an authorization or purchase from a secure, server-side backend using that token.

Spreedly provides two primary UI integration paths across all platforms recommended to most merchants to minimize payment page PCI scope: Headless (Hosted Fields) Checkout & Drop-in Components (Express) Checkout. There are other methods for collecting payment information which may be considered for specific checkout requirements, however, those options may not be as secure and can increase PCI scope.


Before you begin

All tokenization methods require some form of authentication and authorization to securely vault tokenized payment method data. This is typically a Spreedly environment key and access secret. Review the app guide for details on obtaining these API credentials.

Mobile applications that securely collect credit card information can require additional details to execute. By their nature, mobile devices can be compromised by their owner via methods like jailbreaking and brute-force attacks. In these situations, the app maintainer often has no ability to detect intrusions. Because of this limitation, data stored on the device should be considered open to compromise. No secret or password values should be stored by a mobile application, including Spreedly's access secrets.

Secure tokenization

To securely initialize any of Spreedly's client-side SDKs (Web, iOS, Android, and React Native) without exposing API secrets, merchants must use a server-generated authentication signature. Because these credentials are time-sensitive and single-use, the secure backend must dynamically generate them for each individual payment session and pass them to the client application.

The following parameters are required across all SDKs to securely authenticate each tokenization request:

  • Environment key: The public identifier that tells the SDK which specific Spreedly environment (test or production) to connect to.
  • Nonce: A unique, single-use random string generated by the backend for each session, used to prevent malicious replay attacks.
  • Timestamp: A UTC timestamp recording exactly when the signature was generated, ensuring the authentication request is strictly time-bound.
  • Signature: A secure HMAC signature generated on your backend using Spreedly API secret, environment key, nonce, and timestamp. This cryptographically proves to Spreedly that the client's request was explicitly authorized by the correct merchant server.
  • Certificate token: A token provisioned through Spreedly that is used to authenticate and enforce security within the tokenization environment

Headless (hosted fields & custom forms) checkout

Headless checkout SDKs include secure input components allowing complete control over the layout, style, and flow of a payment page and suer experience. Merchants build the surrounding UI and form logic, while the SDK injects secure text fields exclusively for capturing PCI-sensitive data. To implement headless checkout, select a preferred solution below to suit the needs of each payment experience:

SolutionSummaryLink
Web SDKThe Web SDK injects secure iframes for the card number and CVV fields directly into a custom HTML form. Merchants collect non-sensitive fields and pass them to the SDK's submit method to combine with iframe data for tokenizationhttps://github.com/spreedly/web-sdk-sample-app/blob/main/docs/tokenization/hosted-fields/INTEGRATION_GUIDE.md
iOS SDKBuild fully customized native payment forms using individual SPLTextField components. Each field automatically handles its own validation, formatting, and secure encrypted storage, allowing for brand-specific designs and non-standard field arrangements.https://github.com/spreedly/checkout-ios-example/blob/main/docs/guides/custom-payment-forms.md
Android SDKThis approach uses a hybrid Jetpack Compose architecture where Spreedly's secure SPLTextField composable components manage sensitive card data, and merchants use custom text fields for non-sensitive billing information.https://github.com/spreedly/checkout-android-example/blob/main/docs/guides/custom-payment-forms.md
React Native SDKBuild custom checkout flows natively using the <SPLTextField> secure component for PCI compliance. You can mix these secure fields with standard React Native text inputs for collecting names, emails, and addresseshttps://github.com/spreedly/checkout-react-native-example/blob/main/docs/guides/hosted_fields_guide.md

Securing Headless checkout

  • Validate Authentication: All SDKs require server-generated authentication details (nonce, signature, certificate token, and timestamp). Fetch these credentials dynamically from a secure backend for each session—never hardcode them into the client app.
  • Web: Always load the SDK using Subresource Integrity (SRI) hashes to ensure files haven't been tampered with. Enforce HTTPS, and configure a strict Content Security Policy (CSP) to protect against clickjacking. Review the payment page security guide for PCI considerations and other best-practices.
  • Mobile (iOS/Android/React Native): It is mandatory to use the secure SPLTextField components for the Card Number, CVV, and Expiration Date; never use standard text inputs for these fields.
  • Screenshot prevention: Apply screen prevention modifiers (.screenPrevention() for iOS, SecureScreen() or FLAG_SECURE for Android, and ScreenSecurity module for React Native) to the root view of custom forms to block screenshots and screen recording apps from capturing card data.
  • Token handling: Never store the resulting payment tokens in insecure local storage (like AsyncStorage, UserDefaults, or SharedPreferences). Send tokens immediately to the backend.

Express checkout

Express checkout is a complete, pre-built payment form that handles all UI, state management, and field validation automatically. This integration path requires minimal development effort and is the fastest way to get a standard, optimized e-commerce payment flow running. It maintains the same level of standards for handling and vaulting payment data, helping merchants to offload PCI scope. To implement express checkout, select a preferred solution below to suit the needs of each payment experience:

SolutionSummaryLink
Web SDKDrop a complete payment form into any webpage with minimal code. It can be rendered as an embedded inline component or a focused modal dialog overlay, with customizable text and styling/theme APIs.https://github.com/spreedly/web-sdk-sample-app/blob/main/docs/tokenization/express-checkout/INTEGRATION_GUIDE.md
iOS SDKUse the pre-built CardFormDropIn component to render a full checkout form. It features automatic validation, error display, and a built-in "Save card for future payments" checkbox option.https://github.com/spreedly/checkout-ios-example/blob/main/docs/guides/custom-payment-forms.md
Android SDKLaunch the Express Checkout payment form to instantly present a secure, fully-featured payment interface that adapts automatically to light and dark modes.https://github.com/spreedly/checkout-android-example/blob/main/docs/guides/custom-payment-forms.md
React Native SDKCall the API to present a native payment form on any page. It manages form state automatically and supports comprehensive global theme customization.https://github.com/spreedly/checkout-react-native-example/blob/main/docs/guides/express_checkout_guide.md

Securing Express checkout

  • Validate authentication: Express checkout components across all SDKs require server-generated authentication details (nonce, signature, certificate token, and timestamp). Fetch these credentials dynamically from a secure backend for each session—never hardcode them into the client app.
  • Automatic security: Mobile drop-in components automatically handle secure memory cleanup, clipboard blocking (preventing copy/paste of CVVs), and memory-only encryption natively.
  • Screenshot prevention: While Android's PaymentSheet calls SecureScreen() internally to protect the UI out-of-the-box, iOS apps should still apply the .screenPrevention() modifier when presenting the CardFormDropIn sheet. React Native implementations must also manually activate the ScreenSecurity module upon initialization for this feature.

Direct API

For merchants operating in a non-browser, server-to-server environment, there is an option to use Spreedly's Direct API to submit payment information using the create payment method call. This method allows merchants to use different programming languages to pass credit card or bank account data directly to Spreedly's endpoint. It is typically used for migrating cards the merchants already have on file or processing payments from a secure backend.

Warning: Because this method requires handling raw cardholder data before transmitting it to Spreedly, this method accepts the greatest amount of PCI scope. Whenever possible, we highly recommend using the Headless or Express Checkout paths on the client side to keep sensitive data off your infrastructure entirely.


CVV Number

The Card Verification Value (CVV) is a 3 or 4 digit number located on a card, depending on card type or brand. It is a security code used for card-not-present transactions.

The Payment Card Industry Data Security Standard (PCI DSS) prohibits the storage of the CVV. Spreedly pass along the CVV for the first authorize, purchase, or verify event on a given card. Future transactions using that vaulted card do not include the CVV.

Because CVV cannot be stored, Spreedly will only hold the CVV in memory for three minutes. In summary:

  • CVV will be cached for three minutes unless recache or used
    • Recache is an action you can take where you supply Spreedly the CVV and we reset the three minutes. See documentation here
    • Used means it was successfully used in a gateway, deliver, or export transaction.
  • The wipe after use can be bypassed with the continue_caching property on a transaction. continue_caching does not extend or reset the three minutes, it just does not wipe it early. See documentation here.

Note: CVV is not verified when a new payment method is added, as a transaction is not executed. Although a token is returned, a purchase or authorization must be invoked from a secure, server-side environment to verify CVV for that payment method.


Event lifecycle

While specific lifecycle details vary slightly by platform, the general event lifecycle follows a consistent pattern across Spreedly's SDKs. Full event-handling and platform or framework-specific details can be found in each SDK repository. This event lifecycle is consistent for merchants implementing either Headless (Hosted Fields) checkout or the Component (Express checkout):

Headless checkout events

Because each merchant owns the surrounding UI and form logic on their payment page, the headless checkout implementation requires listening to field-level events to manually trigger payment submission.

  1. Ready / Initialization: After you initialize the SDK and mount the secure fields, a ready event fires to indicate that the fields are successfully rendered and ready for user input.
  2. Validation: As the user types, the SDK emits validation events (e.g., onValidationChange) that report whether input in a specific field is valid or invalid. Use these events to dynamically update the UI accordingly, such as by enabling a "pay now" button or showing error text to the cardholder.
  3. Submission: Call the SDK's submit method (e.g., submit() or createCreditCard()) when the user clicks a custom payment button.
  4. Result (Token or Error): The SDK communicates with the Spreedly API for an immediate processing result (e.g., PaymentProcessingResult) to confirm that request passed client-side validation and has begun processing. The final result event (e.g., tokenGenerated, error, or via a PaymentResult publisher/delegate) will provide the payment method token on success, or an error payload detailing why the tokenization request failed.

Component (Express) checkout events

Because the SDK provides a pre-built UI that handles its own state, the component lifecycle is largely automated, reducing the number of events to manage directly.

  1. Ready / Presentation: Once the SDK initializes and renders the payment form, modal, or bottom sheet, a ready event fires to indicate the form is interactive.
  2. Processing & Validation: The component automatically handles field-level validation internally. When the user clicks the built-in submit button, the SDK may emit a processing event (e.g., onProcessingResult) to confirm that validation passed and a network request has started, allowing merchants to show a loading indicator to the cardholder. If validation fails, the component automatically displays the errors to the user.
  3. Result (Token or Error): The final result event (e.g., tokenGenerated or PaymentResult) is generated after processing over the Spreedly API. Merchants receive a payment method token on success, or failure details if the transaction was not completed.
  4. Dismissal / Close: If the form is presented as a modal or bottom sheet, events such as close or paymentSheetDismissed will fire when the UI is dismissed by the user or programmatically closed after a successful payment event.

Additional events

Depending on the integration, merchants may also encounter lifecycle events for specific payment flows:

  • CVV Recaching: After enabling recache mode to update a saved card, the SDK will emit a recacheReady event when the UI is prepared for CVV input, followed by a recacheSuccess event once the CVV is updated.
  • 3D Secure (3DS): If a payment requires 3DS authentication, the SDK will manage a separate challenge lifecycle, emitting events when the challenge UI is presented (e.g., onChallenge), when the gateway requests a backend confirmation (onTriggerCompletion), and when the challenge finally succeeds or fails (ThreeDSChallengeResult). For complete details on Spreedly's 3DS solutions, review the guide.

Alternative payment methods

Spreedly supports a variety of different payment methods, many of which can be tokenized using these SDKs. Today, all solutions support credit cards alongside a wide array of global alternative payment methods (APMs). The integration flow varies slightly depending on the payment type, underlying gateway, and SDK of choice.

Credit card tokenization is supported across all SDKs using either headless hosted fields or the pre-built express form, and can be integrated using the SDKs secure UI components to collect cardholder data. APMs, by comparison, can be categorized into distinct integration paths based on how the checkout UI is presented to an end user:

  • Offsite payments: This path supports PayPal payment methods as well as many popular Latin American payment methods via EBANX such as Pix, Boleto, NuPay and OXXO. These offsite payments are implemented by calling the SDK's submitOffsitePayment method to generate a token, then used to initiate purchase with a provided redirect_url. That token launches a secure browser in-app experience to complete the transaction.
  • Braintree APM: Utilizes Braintree's native SDK to present specific payment UI for PayPal and Venmo payment methods. There is no initial tokenization step here. Instead, the backend creates a pending purchase directly on Braintree to obtain a client_token, then passed to the SDK to launch the intended Braintree UI. Once a user completes the flow, the SDK returns a nonce that must be send by the backend to Spreedly's endpoint to finalize the transaction.
  • Stripe APM: This option leverages native Stripe APM functionality to handle popular European and other regional payment methods such as iDEAL, Bancontact, SEPA, P24, EPS. There is no tokenization step here, instead using the backend to create a pending purchase using stripe_apm payment method for a client_secret. This secret is used to render the native Stripe experience for the user to complete payment. The SDK handles any internal redirects and allows Spreedly to sync final transaction state.

Using a payment method token

The culmination of the SDK event lifecycle is the secure delivery of a payment method token. This token serves as a safe, non-sensitive reference to the raw cardholder data that is now securely stored within Spreedly's PCI-compliant vault. Because the client-side tokenization process only stores the card data and does not automatically execute a charge, merchants must bridge this result to their broader Spreedly integration to finalize the payment.

Upon receiving the successful event payload from the SDK, the client application immediately transmits the payment method token to the merchant's secure backend server. That token can be used across the Spreedly ecosystem:

  • Connect: That backend server completes a standard API call to Spreedly (such as a purchase or authorize request) to execute the transaction against a designated payment gateway.
  • Vault: If the token was created with the retained flag, it remains safely in the Spreedly vault. This allows merchants to use the same token for future MIT transactions, recurring subscription billing, or CVV recaching flows without the user needing to re-enter their full card details.
  • Optimize: Because Spreedly vaults the token independently of any underlying gateway, merchants can dynamically route each transaction to different gateways based on workflow rules, pass the token through integrated fraud providers (like Forter or Kount), or trigger 3DS challenges.