Skip to main content
The embedded checkout renders from a URL, so any mobile app can display it in a WebView: create an order server-side, build the checkout URL, and load it. This guide covers the direct WebView integration for apps that do not use a Crossmint client SDK, including native iOS (Swift) and Android (Kotlin) apps.
The React Native, Flutter, and Kotlin SDKs render and configure this WebView for you. If you build with one of those frameworks, start from the SDK instead and return here only if you need full control over the WebView.

Prerequisites

  • API keys: From the Crossmint Console, under Integrate → API Keys, create a server key (sk_staging_...) with the orders.create and orders.read scopes, and a client key (ck_staging_...) with the orders.read scope.
  • A recipient wallet: purchased assets are delivered to a wallet address that you pass at order creation.
  • A backend: order creation uses the server key, which must never ship inside the app.

Integration

1

Create the order server-side

Create the order from your backend and return the orderId and clientSecret to the app. The order carries the item, the recipient, and optionally the receipt email, so the checkout never needs to ask the user for them:
The example uses a token line item; NFT collection line items work the same way. See the create order API reference for all line item types and options.
2

Build the checkout URL

The checkout page accepts its configuration as URL query parameters:
Every configuration option from payment methods and UI customization works here. The example above renders a wallet-button-only checkout; see the one-tap Apple Pay quickstart for that experience end to end.
3

Render the URL in a WebView

A few WebView settings make the difference between a checkout that shows Apple Pay and Google Pay and one that silently does not. The tabs below contain the tested configuration per platform:
Requires react-native-webview version 13.15.0 or higher.
For Google Pay, the app also needs the Android payment intent declaration from the Google Pay guide.
Keep navigation inside the WebView unrestricted, and keep iframes enabled. To complete an order, the checkout navigates to pages from Crossmint’s payment method and identity partners, and a WebView that blocks those pages interrupts the purchase with no visible error.
If your security policy requires a navigation allowlist, include these domains, grouped by what they render during checkout:Match subdomains as well (for example *.crossmint.com), and revisit the list when you update the SDK or change payment methods.
4

Track the order

The checkout page reports progress with messages. In React Native, listen with onMessage:
On iOS (Swift) and Android (Kotlin), track the order from your backend instead: subscribe to webhooks or poll the get order endpoint with the orderId you already hold.
5

Test on a physical device

Wallet payment methods render on real hardware: test Apple Pay on an iPhone running iOS 17 or higher with a card added to Apple Wallet, and Google Pay on an Android device with Google Play Services. In staging, wallet payments run against a test environment, so the card behind the wallet is never charged.To exercise the full purchase from a simulator or emulator during development, enable the card form (allowedMethods: { card: true, ... }) and pay with the staging test card 4242 4242 4242 4242. More options are listed in testing tips.

Troubleshooting

  • Set a standard mobile browser userAgent on the WebView (step 3). The checkout serves wallet buttons to mobile browsers, and the default WebView userAgent identifies as an app.
  • For Google Pay, enable the Payment Request setting and declare the payment intent in the manifest (step 3), and test on a device with Google Play Services.
  • For Apple Pay, use a physical iPhone on iOS 17 or higher: the iOS Simulator does not render Apple Pay.
  • Confirm the order was created successfully and payment in the URL enables the wallet you expect.
A navigation restriction is usually interrupting the checkout mid-purchase. Remove custom WebViewClient/WKNavigationDelegate rules that cancel navigations, or extend your allowlist with the domains listed under “Restricting navigation” above.
  • Enable JavaScript and DOM storage on the WebView (step 3).
  • Match the base URL to the key environment: ck_staging_/sk_staging_ keys pair with staging.crossmint.com, production keys with www.crossmint.com.
  • Confirm the payment and appearance parameters contain valid JSON after URL encoding.
Pass GlobalMessage: { display: "visible" } inside appearance.rules (step 2). In layouts that hide the checkout inputs, this rule is the surface where payment errors render.

FAQ

Yes. The React Native, Flutter, and Kotlin SDKs apply this WebView configuration automatically and expose the checkout as a component. Use this guide when you need your own WebView, or on platforms without an SDK, such as native iOS (Swift).
No. Apple Pay domain registration applies to websites that embed the checkout. In this integration the checkout page is served from crossmint.com, which is already enabled for Apple Pay.
Restrict the payment methods and hide the checkout inputs through the payment and appearance URL parameters. The one-tap Apple Pay quickstart covers the complete configuration, and every setting in it maps directly onto the URL parameters from step 2.
Yes. The checkout URL also renders in SFSafariViewController, Chrome Custom Tabs, or a regular browser tab. A WebView keeps the checkout inside your own screens; a browser surface takes less configuration and suits flows where opening a sheet over the app is acceptable.
The same ones as the embedded checkout on web: cards, Apple Pay, Google Pay, and crypto, controlled by the payment URL parameter. See payment methods.

Next Steps

One-Tap Apple Pay

Render only the wallet button and build the rest of the experience in your own UI

Google Pay Mobile

Production approval and native Android configuration for Google Pay

UI Customization

Theme the checkout through the appearance parameter