Skip to content
Last updated

This guide walks through a complete Banxa Hosted Checkout integration using the React Native SDK. By the end, you'll have a working buy flow: fetch a live quote, create an order, present the checkout in a WebView, and retrieve the final order status.


Before you start

Prerequisites

  • A React Native mobile app (iOS, Android, or both).
  • Your Banxa partner reference and API key (sandbox for development, production after approval).
  • A configured webhook endpoint (optional but recommended for order status tracking).

Install the SDK

npm install @banxa-official/react-native-sdk react-native-webview

For iOS, install the pods:

cd ios && pod install

react-native-webview is a peer dependency.


Step 1 — Initialise the SDK

Create a single Banxa client instance at app startup. Keep it in a shared service or context so it can be reused across screens.

import { Banxa } from '@banxa-official/react-native-sdk';

const banxa = new Banxa({
  apiKey: 'YOUR_API_KEY',
  partner: 'your-partner-id',
  environment: 'sandbox', // or 'production'
});
FieldDescription
apiKeyYour Banxa API key.
partnerYour partner identifier (e.g., binance, metamask).
environment'sandbox' or 'production'. Defaults to 'production'.
baseUrlOptional. Overrides the environment-derived base URL.

Step 2 — Get a quote

Call the Quote API to retrieve live pricing before presenting an amount to the customer. Call this close to when you show the price — crypto rates move quickly, and stale quotes can differ from the final checkout price.

const quote = await banxa.prices.getBuyQuote({
  fiat: 'USD',
  crypto: 'BTC',
  fiatAmount: '100',
  paymentMethodId: '1',
  blockchain: 'bitcoin',
});

console.log('Crypto amount:', quote.cryptoAmount);
console.log('Processing fee:', quote.processingFee);
console.log('Network fee:', quote.networkFee);

Either fiatAmount or cryptoAmount must be provided. For sell quotes, use banxa.prices.getQuote('sell', { ... }).


Step 3 — Create an order

Create a buy order once the customer confirms.

const order = await banxa.buy.createOrder({
  externalCustomerId: 'user-123',
  fiat: 'USD',
  crypto: 'BTC',
  fiatAmount: '100',
  paymentMethodId: '1',
  walletAddress: '1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa',
  redirectUrl: 'https://yourapp.com/success',
});

Required fields

  • externalCustomerId — your stable customer identifier, used by Banxa to recognise returning customers.
  • fiat, crypto, and either fiatAmount or cryptoAmount.
  • paymentMethodId — pre-selects the payment method.
  • walletAddress — the customer's receiving wallet address.
  • redirectUrl — where the customer is returned after checkout.

Response

{
  "checkoutUrl": "https://partner.banxa.com/portal?expires=xxx&oid=xxx&signature=xxx",
  "id": "191fa5b4b1f45e1cf784422e09317d56",
  "externalOrderId": "a4b427ccb872a1744b317456bd0d165f",
  "externalCustomerId": "user-123",
  "fiat": "CAD",
  "fiatAmount": "1000.00",
  "crypto": "USDC",
  "cryptoAmount": null,
  "blockchain": "TRON"
}
FieldDescription
checkoutUrlBanxa-hosted checkout URL to present to the customer.
idBanxa order ID. Store this — you'll use it for order lookup.
externalOrderIdYour internal order reference, if provided at creation. null if not.
externalCustomerIdYour customer identifier as supplied.
fiat, fiatAmount, crypto, cryptoAmount, blockchainOrder parameters as supplied. If cryptoAmount or fiatAmount wasn't provided, it will be null.

Step 4 — Present the checkout

Use initializeCheckoutWebView to configure the props for the CheckoutWebView component, then render it.

import { CheckoutWebView } from '@banxa-official/react-native-sdk';
import { useState } from 'react';

function BuyCryptoScreen() {
  const [webViewProps, setWebViewProps] = useState(null);

  const handleBuyPress = async () => {
    const order = await banxa.buy.createOrder({
      externalCustomerId: 'user-123',
      fiat: 'USD',
      crypto: 'BTC',
      fiatAmount: '100',
      paymentMethodId: '1',
      walletAddress: '1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa',
      redirectUrl: 'https://yourapp.com/success',
    });

    const props = banxa.buy.initializeCheckoutWebView(order, {
      onClose: () => setWebViewProps(null),
      onSuccess: (url) => { /* payment succeeded */ setWebViewProps(null); },
      onFailure: (url) => { /* payment failed */ setWebViewProps(null); },
      returnUrlOnSuccess: 'https://yourapp.com/success',
      returnUrlOnFailure: 'https://yourapp.com/failure',
    });

    setWebViewProps(props);
  };

  return (
    <>
      <Button onPress={handleBuyPress} title="Buy BTC" />
      {webViewProps && <CheckoutWebView {...webViewProps} />}
    </>
  );
}

The WebView detects navigation to your return URLs automatically and triggers the corresponding callback.

Payment methods that can't run in a WebView

Some payment methods — iDEAL, Klarna, and PayPal — cannot complete inside a WebView. These methods require the customer to be redirected outside your app to the provider (bank, Klarna, or PayPal). There is no automatic return, so partners should design a post-payment UX — for example, a confirmation screen with a link back to the app.

Native payment sheet (Primer)

The SDK also supports a native payment sheet via Primer for card, Apple Pay, and Google Pay payments. This is a more advanced integration designed for partners who verify their own users and run their own KYC — see Banxa Native. Talk to Banxa if you'd like to discuss whether this is relevant for your integration.


Step 5 — Look up order status

After the customer completes checkout, retrieve the final order status via the SDK.

const orderDetails = await banxa.buy.getOrder(order.id);

if (orderDetails.status === 'complete') {
  // Notify the user, update your database, etc.
}

For the full list of order statuses and their meanings, see Order Statuses.

Retrieving orders by customer

To list buy orders for a specific customer:

const userOrders = await banxa.buy.getOrdersByAccount('user-123');

This returns orders tied to that externalCustomerId. For a full list of all orders across all customers (reconciliation, reporting), use the Banxa API directly — this isn't exposed through the SDK.


The SDK's onSuccess callback fires when the customer completes checkout, but for reliable order status tracking you should configure webhooks on your backend.

Webhooks fire for every order status change. Configure your webhook URL in the Partner Dashboard.

→ See Webhooks for payload structure and security.

The typical pattern:

  • SDK onSuccess callback → optimistic UI update ("your order is processing").
  • Webhook to your backend → authoritative order state.
  • Backend pushes update to the app (or app re-fetches order on resume).

Error handling

Wrap SDK calls in try/catch. The SDK throws BanxaSDKError objects for API and network failures.

import { Banxa, BanxaSDKError } from '@banxa-official/react-native-sdk';

try {
  const order = await banxa.buy.createOrder({ /* ... */ });
} catch (error) {
  if (error instanceof BanxaSDKError) {
    console.error('Banxa API error:', error.message);
    console.error('Error code:', error.code);
    console.error('Status code:', error.statusCode);
  } else {
    console.error('Unknown error:', error);
  }
}

Show user-facing messages only from validated error fields — don't expose raw error strings that may include internal detail.


Testing

Use the sandbox environment for all development and testing:

const banxa = new Banxa({
  apiKey: 'YOUR_SANDBOX_API_KEY',
  partner: 'your-partner-id',
  environment: 'sandbox',
});

For test credentials (mobile numbers, card numbers, PIN codes, KYC data), see Sandbox Test Data.


Next steps