Use this file to discover all available pages before exploring further.
The Busha Pay mobile SDKs let you embed a crypto checkout experience directly into your mobile app. Users can pay with their Busha wallet or externally without leaving your app. Three SDKs are available; React Native, iOS (Swift), and Flutter.
A React Native, iOS, or Flutter mobile application.
Important Note: The mobile SDKs use your Public API Key, not your Secret
API Key. Your Public API Key is automatically generated for your account — you
do not need to create a new token to access it. You can find it in Settings
→ Developer Tools → API Tokens.
Installing from GitHub releasesEach release ships an npm-installable tarball on GitHub under tags shaped react-native/v<version>. You can install directly without going through the npm registry:
npm install https://github.com/bushaHQ/pay/releases/download/react-native/v0.0.1/busha_pay_react_native-0.0.1.tgz# or with yarn:yarn add https://github.com/bushaHQ/pay/releases/download/react-native/v0.0.1/busha_pay_react_native-0.0.1.tgz
Then install the peer dependencies separately:
npm install react-native-webview expo-application
Bare React Native setupIf your app is bare React Native (not Expo), run this once to enable Expo modules:
npx install-expo-modules@latest
Expo managed, Expo dev client, and Expo Go users can skip this step.
BushaPay iOS SDK
View the full iOS SDK source, releases, and Swift Package Manager setup on
GitHub.
Requirements: iOS 14+, Swift 5.9+, Xcode 15+Installing via Swift Package Manager (recommended)In Xcode, go to File → Add Package Dependencies… and enter:
https://github.com/bushaHQ/pay-iosSelect your version, choose the BushaPay library, and add it to your app target.For Package.swift:
The SDK is authored in the bushaHQ/pay
monorepo under ios/. Each release is mirrored to the standalone
bushaHQ/pay-ios repository so Swift
Package Manager can resolve it correctly. Issues, PRs, and source code live in
the monorepo.
busha_pay on pub.dev
View the full Flutter SDK package, documentation, and changelog on pub.dev.
Requirements: Flutter 3.0+, Dart 3.0+Installing from pub.dev (recommended)Add busha_pay to your pubspec.yaml:
dependencies: busha_pay: ^0.0.1
Then run:
flutter pub get
Installing from GitHubEach release ships as a zipped artifact on GitHub under tags shaped flutter/v<version>. To install directly from the monorepo without going through pub.dev:
Both iOS and Android require two things: registering your app’s callback URL scheme so the Busha app can return the payment result to you, and declaring the Busha app’s URL scheme as launchable so the SDK can deep-link into it when installed.
The SDK does not subscribe to incoming URLs itself to avoid conflicts with your existing deep-link setup. Forward Busha callbacks with a single call — BushaPay.handleDeepLink(url) returns true if the URL was a Busha callback.
React Native
iOS (Swift)
Flutter
Pick whichever matches the deep-link approach your app already uses.Option A — React Native Linking:
import { useEffect } from 'react'import { Linking } from 'react-native'import { BushaPay } from '@busha/pay-react-native'useEffect(() => { const sub = Linking.addEventListener('url', ({ url }) => { BushaPay.handleDeepLink(url) }) Linking.getInitialURL().then((url) => { if (url) BushaPay.handleDeepLink(url) }) return () => sub.remove()}, [])
Option B — expo-linking:
import { useEffect } from 'react'import * as Linking from 'expo-linking'import { BushaPay } from '@busha/pay-react-native'useEffect(() => { const sub = Linking.addEventListener('url', ({ url }) => { BushaPay.handleDeepLink(url) }) Linking.getInitialURL().then((url) => { if (url) BushaPay.handleDeepLink(url) }) return () => sub.remove()}, [])
Option C — React Navigation:
import { NavigationContainer } from '@react-navigation/native'import { Linking } from 'react-native'import { BushaPay } from '@busha/pay-react-native'const linking = { prefixes: ['com.example.myapp.busha-pay://', 'https://yourapp.com'], config: { /* your screens */ }, subscribe(listener) { const sub = Linking.addEventListener('url', ({ url }) => { if (BushaPay.handleDeepLink(url)) return listener(url) }) return () => sub.remove() },}<NavigationContainer linking={linking}> {/* ... */}</NavigationContainer>
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) { for context in URLContexts { if BushaPay.handleDeepLink(context.url) { continue } // your own URL handling }}
SwiftUI:
@mainstruct MyApp: App { var body: some Scene { WindowGroup { ContentView() .onOpenURL { url in if BushaPay.handleDeepLink(url) { return } // your own URL handling } } }}
Flutter has a built-in deep-link handler that, when enabled, routes incoming URLs through your app’s Router/Navigator. Whether you enable it depends on your wiring approach:
import 'package:uni_links/uni_links.dart';uriLinkStream.listen((uri) { if (uri != null) BushaPay.handleDeepLink(uri);});
You can verify your deep link setup without making a real payment. Run the following in your terminal and confirm your app comes to the foreground and checkout() resolves with a success result.iOS simulator:
When checkout() is called, the SDK opens a chooser with two options:
Pay with Busha app — if the Busha app is installed on the device, the SDK deep-links directly into it. The user completes the payment inside the Busha app and is returned to your app via the callback URL scheme. If the Busha app is not installed, the SDK falls back to the web checkout automatically.
Pay with Stablecoins — opens the Busha web checkout in an in-app WebView (WKWebView on iOS, WebView on Android). The user completes the payment inside your app without switching to another application.
Either way, the result is delivered to the promise or callback returned by checkout().When payment completes via the web checkout, the result includes full payment data — amounts, currencies, exchange rate, and timeline. When payment completes via the Busha app, only paymentId and status are available. Use result.hasFullData to check before accessing the additional fields.
A cancelled result carries a reason so you can tell exactly how the checkout ended:
Reason
Meaning
dismissed
The user closed the in-app chooser or web checkout sheet.
rejected
The Busha app reported the user explicitly rejected the payment. paymentId is populated so you can reconcile the request server-side.
abandoned
The user returned from the Busha app without a callback. The outcome is unverified — the payment may still have succeeded. Always reconcile server-side via webhooks or the status API before showing the user a final state.
When payment completes via the Busha app, only paymentId and status are
available. Full payment data (amounts, currencies, rate, timeline) is only
returned when payment completes via the web checkout. Use result.hasFullData
to check. Always verify payments server-side via webhooks — the client result
is a UX hint, not the source of truth.
By default, checkout shows a chooser with two options: Pay with Busha app and Pay with Stablecoins. Pass allowedPaymentMethods to skip the chooser or restrict options:
Value
Behaviour
undefined or []
Show the full chooser
['bushaApp']
Skip chooser; deep-link into the Busha app, with web fallback if not installed
CHECKOUT_IN_PROGRESS — A previous checkout() call hasn’t resolved yet. Wait for it to complete before calling again.
WEBVIEW_LOAD_ERROR — Network failure or DNS error. Check the device’s internet connection.
WEBVIEW_HTTP_ERROR — The checkout endpoint returned a non-2xx HTTP response. Check your public key and environment configuration.
WEBVIEW_TIMEOUT — Checkout page didn’t load within 30 seconds. Retry on a stable connection.
HTML_LOAD_ERROR (iOS and Flutter only) — The bundled checkout HTML asset failed to load. Try reinstalling the SDK.
BUSHA_APP_LAUNCH_FAILED (iOS only) — The SDK could not deep-link into the Busha app. Verify LSApplicationQueriesSchemes is configured correctly in your Info.plist.
401 Unauthorized — Double-check that your public API key is correct and matches your environment (sandbox vs live).
Callback not received after Busha app payment — Your deep link setup is incomplete. Test it manually using the xcrun simctl or adb commands in the note above.