The Banxa JavaScript Native Payments SDK is the payment execution layer of Banxa Native for web. It's the web counterpart to the React Native SDK: used alongside the Native API to present native card and wallet payments in the browser, the payment methods that can't be handled through the API alone due to PCI requirements.
Bank transfers are handled directly by the Native API and don't involve the SDK. For the end-to-end integration walkthrough, see the Integration Guide.
Which parts are relevant for Banxa Native? In a Banxa Native integration, your backend handles pricing, identity, and eligibility via the Native API. The SDK's role is limited to payment execution: the
<banxa-primer-checkout>web component renders the native payment sheet in your page, gated on the eligibilitypaymentReadyflag.The full API surface is documented below for completeness.
npm install @banxa-official/javascript-native-payments-sdkFor native payment checkout, install the Primer peer dependency:
npm install @primer-io/primer-js@primer-io/primer-js is an optional peer dependency, required only for the native checkout web component.
The SDK ships dual module output (ESM + CJS) with separate server and browser entry points, so backend code never pulls in DOM or web component code.
| Import | Environment | Exports |
|---|---|---|
@banxa-official/javascript-native-payments-sdk | Node / server | BanxaApiClient, BanxaApiError, API types |
@banxa-official/javascript-native-payments-sdk/api | Node / server | Same as above |
@banxa-official/javascript-native-payments-sdk/web | Browser | registerBanxaCheckout, registerBanxaPrimerCheckout, registerBanxaHostedCheckout, runBuyCheckoutFlow, checkout and Primer types |
The web entry does not auto-register custom elements. Call registerBanxaCheckout() (or register components individually) before using them.
The BanxaApiClient is Node-safe and handles all Banxa API requests from your backend.
import { BanxaApiClient } from '@banxa-official/javascript-native-payments-sdk';
const client = new BanxaApiClient({
apiKey: process.env.BANXA_API_KEY,
partner: process.env.BANXA_PARTNER,
environment: 'sandbox', // or 'production'
});| Option | Type | Required | Description |
|---|---|---|---|
apiKey | string | Yes | Your Banxa API key from the Partner Dashboard. |
partner | string | Yes | Your partner identifier. |
environment | 'sandbox' | 'production' | Yes | Selects the environment base URL. |
Requests use x-api-key authentication. Keep the API key server-side, never in browser or client-side code.
Create a buy order from your backend, then return the payment token to your frontend.
const order = await client.createOrder({
externalCustomerId: 'user-123',
fiat: 'AUD',
crypto: 'USDT',
fiatAmount: '100', // or cryptoAmount, at least one is required
walletAddress: '0x1234567890abcdef...',
redirectUrl: 'https://yoursite.com/order-complete',
paymentMethodId: 'debit-credit-card', // optional
blockchain: 'TRON', // optional
});
// Native payments: pass this token to the checkout web component
const nativeToken = order.nativeToken;createOrder maps to POST /v2/buy.
| Field | Required | Description |
|---|---|---|
externalCustomerId | Yes | Your customer reference. Use the same value across identity and eligibility flows. |
fiat | Yes | Fiat currency code (for example AUD, USD). |
crypto | Yes | Crypto currency code (for example USDT, BTC). |
walletAddress | Yes | Customer wallet address. |
redirectUrl | Yes | URL the customer returns to after checkout completes, fails, or is cancelled. |
fiatAmount | One of | Fiat amount to buy. |
cryptoAmount | One of | Crypto amount to buy. |
paymentMethodId | No | Pre-select a payment method (for example debit-credit-card). |
blockchain | No | Blockchain network for the crypto token. |
walletAddressTag | No | Memo or tag for wallets that require it. |
externalOrderId | No | Your order reference. |
discountCode | No | Promotion or discount code. |
email | No | Pre-fill the customer email. |
metadata | No | Opaque string returned on order lookup. |
subPartnerId | No | Channel identifier (exchange, wallet, web, and so on). |
Provide either fiatAmount or cryptoAmount. If both are set, Banxa uses cryptoAmount.
Pricing is indicative. The SDK does not accept a locked quoteId, so re-quote close to order creation to minimise rate drift.
| Field | Description |
|---|---|
id | Banxa order ID. |
nativeToken | Primer client token for <banxa-primer-checkout> (native payments). |
checkoutUrl | Hosted checkout URL, used for the fallback flow when native payments are not available. |
fiat, fiatAmount, crypto, cryptoAmount, blockchain | Order amounts and assets. |
externalCustomerId, externalId | Customer and external references. |
Check whether an order can proceed before presenting the native payment sheet. The response's paymentReady field determines whether to render native Primer checkout or fall back to hosted checkout.
const eligibility = await client.checkOrderEligibility({
externalCustomerId: 'user-123',
fiat: 'AUD',
crypto: 'USDT',
fiatAmount: '100',
walletAddress: '0x1234567890abcdef...',
redirectUrl: 'https://yoursite.com/order-complete',
}, 'buy');
if (eligibility.paymentReady) {
// safe to render native Primer checkout
}checkOrderEligibility maps to POST /eligibility and takes the same body as createOrder plus the order type.
| Field | Description |
|---|---|
eligible | Whether the order context is eligible. |
paymentReady | When true, the customer can use native Primer checkout. |
requirements | Outstanding KYC or compliance requirements when not payment-ready. |
message | Optional human-readable detail. |
Use
paymentReadyto choose between native Primer checkout and the hosted fallback. Do not rely on other fields for gating.
The <banxa-primer-checkout> web component renders the native payment sheet in your page. No redirect, no Banxa-hosted screen.
<script type="module">
import { registerBanxaPrimerCheckout } from '@banxa-official/javascript-native-payments-sdk/web';
registerBanxaPrimerCheckout();
</script>
<banxa-primer-checkout id="checkout" locale="en"></banxa-primer-checkout>
<script type="module">
const response = await fetch('/api/create-order', { method: 'POST' });
const { nativeToken } = await response.json();
const checkout = document.getElementById('checkout');
checkout.clientToken = nativeToken;
checkout.addEventListener('banxa:payment-success', (event) => {
console.log('Payment successful', event.detail);
});
checkout.addEventListener('banxa:payment-failure', (event) => {
console.error('Payment failed', event.detail);
});
</script>Set the token via the clientToken property (or client-token attribute) after your backend returns nativeToken from createOrder.
| Attribute | Description |
|---|---|
client-token | Required. Primer client token (order.nativeToken from createOrder). |
locale | Locale string (for example en). |
layout-mode | preset (default), auto, or custom. |
payment-methods | Comma-separated Primer types for preset mode (for example PAYMENT_CARD,APPLE_PAY). |
loader-disabled | Disable the loading placeholder. |
custom-styles | CSS string injected into the component shadow root. |
| Property | Description |
|---|---|
clientToken | Get or set the client-token attribute. |
locale | Get or set the locale. |
layoutMode | Get or set the layout mode. |
paymentMethods | Get or set the preset payment methods. |
checkoutLayout | Programmatic CheckoutLayoutConfig, merged with attributes. |
checkoutTemplate | Raw HTML for custom layout mode. |
loaderDisabled | Get or set the loading placeholder. |
customStyles | Get or set custom CSS. |
| Method | Description |
|---|---|
refreshSession() | Delegates to the Primer refreshSession() when available. |
Primer events are re-emitted on the host element with a banxa: prefix. Use native addEventListener.
| Event | Description |
|---|---|
banxa:ready | Checkout ready. |
banxa:payment-start | Payment started. |
banxa:payment-success | Payment succeeded. |
banxa:payment-failure | Payment failed. |
banxa:payment-cancel | Payment cancelled. |
banxa:state-change | Primer SDK state changed. |
banxa:methods-update | Available payment methods updated. |
banxa:card-success, banxa:card-error | Card validation events. |
banxa:bin-data-available, banxa:bin-data-loading-change | Card BIN lookup events. |
checkout-error | The SDK failed to load or initialise (not prefixed). |
Event detail objects are sanitised for JSON serialisation: DOM nodes and circular references are replaced with string placeholders.
| Mode | Behaviour |
|---|---|
preset (default) | Builds markup from paymentMethods (default: card plus Apple Pay). Card payments use a standalone Primer card form with slotted fields. |
auto | Omits the payments slot so Primer renders all session payment methods. |
custom | Uses checkoutTemplate, checkoutLayout.mainHtml, or a <template slot="checkout-layout"> child for full control. |
Custom card forms must use Primer hosted input components only. Raw HTML inputs cannot host PCI card data. In preset mode a custom cardFormHtml is ignored with a console warning; use custom layout mode or the checkout-layout slot instead.
import { registerBanxaPrimerCheckout, PrimerPaymentMethodTypes } from '@banxa-official/javascript-native-payments-sdk/web';
registerBanxaPrimerCheckout();
const checkout = document.querySelector('banxa-primer-checkout');
checkout.checkoutLayout = {
mode: 'preset',
paymentMethods: [
{ type: PrimerPaymentMethodTypes.PAYMENT_CARD },
{ type: PrimerPaymentMethodTypes.APPLE_PAY },
],
};runBuyCheckoutFlow checks eligibility, creates the order, and selects the right UI automatically: native Primer checkout when paymentReady is true, or the hosted fallback when it isn't.
import { BanxaApiClient } from '@banxa-official/javascript-native-payments-sdk';
import { runBuyCheckoutFlow } from '@banxa-official/javascript-native-payments-sdk/web';
const client = new BanxaApiClient({ apiKey, partner, environment: 'sandbox' });
const container = document.getElementById('checkout');
const { mode, order, element } = await runBuyCheckoutFlow({
client,
request: {
externalCustomerId: 'user-123',
fiat: 'AUD',
crypto: 'USDT',
fiatAmount: '100',
walletAddress: '0xabc',
redirectUrl: `${window.location.origin}/checkout/return`,
paymentMethodId: 'debit-credit-card',
},
container,
});
if (mode === 'primer') {
element.addEventListener('banxa:payment-success', () => { /* ... */ });
} else {
element.addEventListener('banxa:checkout-success', () => { /* hosted fallback completed */ });
}paymentReady | nativeToken | Result |
|---|---|---|
true | present | <banxa-primer-checkout> (native payment sheet) |
false or no token | checkoutUrl present | <banxa-hosted-checkout> (hosted fallback iframe) |
| Option | Description |
|---|---|
skipEligibilityCheck | Skip the eligibility call and assume payment-ready. |
primerCheckoutOptions | Pass-through for locale, layoutMode, checkoutLayout, checkoutTemplate, loaderDisabled, customStyles. |
Use the same redirectUrl on your checkout page origin so the fallback iframe can detect return navigation after payment.
Retrieve indicative pricing.
const quote = await client.getQuote({
fiat: 'AUD',
crypto: 'USDT',
blockchain: 'TRON',
paymentMethodId: 'debit-credit-card',
fiatAmount: '100',
}, 'buy');getQuote maps to GET /quotes/{orderType}. Either fiatAmount or cryptoAmount is required, along with fiat, crypto, blockchain, and paymentMethodId.
// Payment methods, optionally filtered by source, target, and country
const paymentMethods = await client.getPaymentMethods('AUD', 'USDT', 'AU');
// Currencies (default order type is 'buy')
const currencies = await client.getCurrencies('buy');
const fiats = await client.getFiatCurrencies('buy');
const crypto = await client.getCryptoCurrencies('buy');
// Countries
const countries = await client.getCountries();const orderDetails = await client.getOrder(order.id);getOrder maps to GET /orders/{orderId}.
API failures throw BanxaApiError.
import { BanxaApiClient, BanxaApiError } from '@banxa-official/javascript-native-payments-sdk';
try {
const order = await client.createOrder({ /* ... */ });
} catch (error) {
if (error instanceof BanxaApiError) {
console.error('Status code:', error.statusCode);
console.error('Response body:', error.responseBody);
console.error('Errors:', error.errors);
} else {
console.error('Unknown error:', error);
}
}| Property | Description |
|---|---|
statusCode | HTTP status code from the API response. |
responseBody | Optional raw response body. |
errors | Optional array of BanxaApiErrorItem with per-field detail. |
Show user-facing messages only from validated error fields. Do not expose raw error strings that may include internal detail.
The SDK is written in TypeScript and ships with type definitions for both entry points.
import { BanxaApiClient } from '@banxa-official/javascript-native-payments-sdk';
import type { CreateOrderRequest, Order, Quote } from '@banxa-official/javascript-native-payments-sdk';| Environment | Base URL |
|---|---|
| Sandbox | https://api.banxa-sandbox.com/{partner}/v2 |
| Production | https://api.banxa.com/{partner}/v2 |