Mobile SDK Integration
Integrate the Tapaya Accept SDK into your mobile application.
The Tapaya Accept SDK for Android provides a robust, secure, and easy-to-use toolkit for embedding payment processing directly into your Android application. Designed with modern Android development practices in mind, it supports Kotlin Coroutines, lifecycle-aware components, and a clean API surface.
Installation
Add the Tapaya Accept SDK dependency to your module-level build.gradle file.
dependencies {
implementation("com.tapaya:accept:1.1.0")
}Initialization
The AcceptSDK singleton is the entry point for all SDK functionality. Initialize it once — typically in
your Application class — then authenticate separately with a merchant token.
Step 1 — Initialize
// Explicit environment
AcceptSDK.initialize(context = this, environment = AcceptEnvironment.SANDBOX)
// Convenience overload
AcceptSDK.initialize(context = this, demo = BuildConfig.DEBUG)Step 2 — Authenticate
Call authenticate() after initialization to log in a merchant. Use a TokenProvider in production so the
SDK can refresh the token automatically.
// TokenProvider (Recommended for Production)
val tokenProvider = object : TokenProvider {
override fun getToken(): String {
return myBackendApi.getMerchantToken()
}
}
AcceptSDK.authenticate(
tokenProvider = tokenProvider,
onSuccess = { /* proceed */ },
onError = { e -> /* handle AcceptSDKException */ }
)
// Static token (testing only)
AcceptSDK.authenticate(
token = AcceptSDK.DEMO_TOKEN,
onSuccess = { /* proceed */ }
)Core Concepts
Payment Interface
The SDK exposes specialized "Terminal" objects for different payment methods. These are lazily initialized and handle the specific logic for each payment type.

| Method | Description | Use Case |
|---|---|---|
cardTerminal | NFC Card Reader | Contactless EMV payments. |
sepaTerminal | SEPA Instant | Bank-to-bank transfers via QR code. |
certisTerminal | Certis Payments | Specialized instant payment network. For more information, see the official CERTIS documentation. |
Onboarding
Before processing payments, you may need to verify the merchant's status or collect additional information
(KYC/KYB).
The AcceptSDK.identity module manages these flows.

// Check if the merchant is approved for Card payments
val status = AcceptSDK.identity.loadStatus(PaymentMethod.CARD)
if (status == IdentityStatus.VERIFIED) {
// Ready to process payments
} else {
// Launch KYB onboarding UI (optionally prefill known data)
AcceptSDK.identity.presentKyb()
}Permissions
Processing payments, especially contactless card payments, requires specific Android permissions and hardware
capabilities (NFC).
The AcceptSDK.helper simplifies managing these requirements.
Lifecycle Management
To ensure the helper can correctly handle permission results, link it to your Activity's lifecycle.
class PaymentActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Register lifecycle observer
AcceptSDK.helper.onCreate(this)
}
override fun onDestroy() {
AcceptSDK.helper.onDestroy()
super.onDestroy()
}
}Requesting Permissions
Request the necessary permissions before starting a transaction. The SDK handles the complexity of different Android versions.
fun startPayment() {
AcceptSDK.helper.requestLocationPermission(this,
onLocationPermissionGranted = {
// Permission granted, proceed to payment
launchPaymentFlow()
},
onLocationPermissionDenied = {
// Show rationale to user
showPermissionRationale()
}
)
}Error Handling
The SDK uses a unified exception hierarchy rooted at AcceptSDKException. All exceptions are wrapped in
AcceptSDKExceptionWrapper to preserve the original cause while providing a consistent interface.
Exception Hierarchy
| Exception Class | Description |
|---|---|
| Initialization | |
AcceptSDKUninitializedException | Terminal is not initialized, call AcceptSDK.initialize() first. |
AcceptSDKServiceStartingException | Service failed to start. Ensure app is in foreground. |
AcceptSDKServiceInitializationException | Unable to initialize payment service. Payments may not be working properly. |
AcceptSDKTokenInitializationErrorException | Error in your TokenProvider implementation. |
AcceptSDKInitializationException | Accept SDK initialization failed. |
AcceptSDKLoginExpiredException | Session expired or not found. Call AcceptSDK.initialize() first. |
AcceptSDKInitializeWithoutDataException | Device restarted payment service. Waiting for proper start. |
| Permissions & Environment | |
AcceptSDKLocationPermissionException | Missing required location permissions (ACCESS_COARSE_LOCATION / ACCESS_FINE_LOCATION). |
AcceptSDKLocationDisabledException | Android Location services are disabled. |
AcceptNFCDisabledException | NFC is disabled on the device. |
AcceptSDKNotDebuggableException | Production app detected, but SDK registered in DEMO mode. Use AcceptSDK.initialize(..., demo = false). |
AcceptSDKDebuggableNotDemoException | Debug app detected, but SDK registered in PROD mode. Use AcceptSDK.initialize(..., demo = true). |
| Reader & Connection | |
AcceptSDKReaderNotFoundException | No Tap-to-Pay terminal reader found on this device. |
AcceptSDKReaderNotReadyYetException | Merchant KYB data missing or processing for the specific terminal reader. |
AcceptSDKReaderBadConnectionException | Connection issues detected while communicating with the reader. |
AcceptSDKOfflineException | Internet connection not available. |
| Transactions & Operations | |
AcceptSDKInitializeTransactionException | Unable to initialize transaction. |
AcceptSDKFinalizeTransactionException | Transaction finalization failed. Verify status manually via backend. |
AcceptSDKOperationTimeoutException | The operation timed out. |
AcceptSDKPaymentNotFoundException | The requested payment record was not found. |
AcceptSDKServerErrorException | Server error occurred. |
AcceptSDKClientErrorException | Client error occurred. |
AcceptSDKCancellationException | User cancelled the operation manually. |
| Onboarding & Location Metadata | |
AcceptSDKOnboardingException | Error occurred during terminal onboarding. |
AcceptSDKDuplicatedOnboardingException | Duplicated onboarding provided. |
AcceptSDKMissingKYBDetailsException | Onboarding not completed for the specified payment method. |
AcceptSDKLocationNotFoundException | Unable to resolve location coordinates. |
AcceptSDKLocationIdNotFoundException | Stripe/Internal location identifier not found. |
| System | |
AcceptSDKUnknownException | Unknown SDK error. |
AcceptSDKUnknownMessageException | Unknown SDK error with message. |
Handling Exceptions
When using Coroutines, wrap SDK calls in a try-catch block to handle these specific scenarios.
try {
AcceptSDK.cardTerminal.process(...)
} catch (e: AcceptSDKCancellationException) {
// User cancelled, do nothing
} catch (e: AcceptSDKLocationPermissionException) {
// Prompt user for permissions
} catch (e: AcceptSDKException) {
// Handle other SDK-specific errors
Log.e("Payment", "Error: ${e.message}")
}Logging
Enable verbose logging during development to troubleshoot issues.
// Enable debug logs
AcceptSDK.setLogLevel(LogLevel.DEBUG)The Tapaya Accept SDK for iOS provides a secure, easy-to-use toolkit for embedding payment processing directly into your iOS application. Built with Swift 6 and modern concurrency in mind, it offers a clean async/await API and tight integration with the Tapaya Accept companion app.
Requirements
| Requirement | Minimum Version |
|---|---|
| iOS | 26.0 |
| Swift | 6.2 |
| Xcode | 26.0 |
Installation
The SDK is distributed via Swift Package Manager from the public repository.
In Xcode: go to File → Add Package Dependencies, paste the repository URL, and add the AcceptSDK product to your target.
In Package.swift:
dependencies: [
.package(url: "https://github.com/tapayadot/accept-ios.git", from: "1.1.2")
],
targets: [
.target(
name: "MyApp",
dependencies: [
.product(name: "AcceptSDK", package: "accept-ios")
]
)
]App Configuration
The SDK requires two Info.plist entries to function correctly.
1. Companion app detection — allows the SDK to check whether the Tapaya Accept companion app is installed:
<key>LSApplicationQueriesSchemes</key>
<array>
<string>tapaya-accept</string>
</array>2. Callback URL scheme — required for deep link callbacks (e.g. after KYB onboarding). Replace myapp with your app's unique scheme:
<key>AcceptCallbackScheme</key>
<string>myapp</string>Required
If AcceptCallbackScheme is missing or empty, Accept.initialize() will throw .notInitialized.
Deep Link Handling
Forward inbound URLs to the SDK so it can handle callbacks (e.g. returning from the companion app or KYB flows).
// SwiftUI
.onOpenURL { url in
Accept.handle(url: url)
}
// UIKit
func application(_ app: UIApplication, open url: URL, options: [...]) -> Bool {
Accept.handle(url: url)
}Initialization
AcceptSDK is the single entry point for all SDK functionality.
Initialize it once at app launch — for example in your App struct or AppDelegate — before calling any other method.
// Sandbox environment (default — safe for testing)
try await Accept.initialize()
// Explicit environment
try await Accept.initialize(environment: .production)
// Convenience: true → sandbox, false → production
try await Accept.initialize(demo: isTestMode)Authentication
After initialization, authenticate the merchant using a token obtained from your backend.
do {
let merchantToken = try await myBackend.login()
try await Accept.authenticate(merchantToken: merchantToken)
} catch AcceptSDKError.failedToAuthenticateMerchant {
// Invalid credentials or network failure — prompt the user to retry
}Logout
To log out the current merchant and clear the session, call logout().
try await Accept.logout()Companion App
The Tapaya Accept companion app is required for card payment flows. Check whether it is installed and guide the merchant to install it if needed.

if await Accept.isCompanionAppInstalled() {
// Pair the device — launches the companion app to complete authentication
try await Accept.pairWithCompanionApp()
} else {
// Show the App Store product page as an in-app sheet
try await Accept.presentCompanionAppSheet()
}Permissions
Card payments require location access. Request the permission before starting a payment flow.
do {
try await Accept.requestLocationPermission()
// Permission granted — safe to initiate a payment
} catch AcceptSDKError.locationPermissionsNotGranted {
// Prompt the user to enable Location in Settings
}Onboarding
Before processing payments, the merchant must complete KYB (Know Your Business) onboarding. Check the verification status and launch the onboarding UI if needed.

let result = try await Accept.presentKyb()
switch result {
case .submitted:
// KYB form submitted — await processor approval
case .cancelled:
// Merchant dismissed without submitting
case .failed:
// Submission failed
}You can optionally prefill known fields to reduce friction:
let prefill = KybPrefillData(
businessType: .company,
countryCode: "CZ",
legalName: "My Company s.r.o.",
registrationNumber: "12345678",
businessEmail: "jan@example.com"
)
let result = try await Accept.presentKyb(prefilling: prefill)Core Concepts
Payment Interface
Companion App Required
Card payments require the Tapaya Accept companion app to be installed on the device.
Use Accept.isCompanionAppInstalled() to check, and Accept.presentCompanionAppSheet() to prompt installation if needed.
See the Companion App section above.
Each payment method has a dedicated intent type. Create an intent and pass it to Accept.pay(_:).

| Intent Type | Description | Use Case |
|---|---|---|
AcceptCardPaymentIntent | NFC Card Reader | Contactless EMV payments. |
AcceptSepaPaymentIntent | SEPA Instant | Bank-to-bank transfers via QR code. |
AcceptCertisPaymentIntent | Certis Payments | Specialized instant payment network. For more information, see the official CERTIS documentation. |
Supported Currencies
| Case | ISO Code |
|---|---|
.czk | CZK |
.eur | EUR |
.gbp | GBP |
Transaction Status
The .status field on a completed payment is an AcceptTransactionStatus:
| Case | Description |
|---|---|
.pending | Payment is pending. |
.success | Payment completed successfully. |
.cancelled | Payment was cancelled. |
.refunded | Payment was refunded. |
.failed | Payment failed. |
.actionNeeded | Payment requires further action. |
Payment Outcome
Accept.pay(_:) returns an AcceptPaymentOutcome — either .completed(status) or .canceled.
Making a Payment
try await Accept.requestLocationPermission()
let intent = AcceptCardPaymentIntent(
amount: 1000, // smallest currency unit — 10.00 CZK
requestedCurrency: .czk,
settlementCurrency: .czk
)
do {
let outcome = try await Accept.pay(intent)
switch outcome {
case .completed(let status):
print("Payment succeeded: \(status.paymentToken)")
print("Status: \(status.status)")
case .canceled:
print("User dismissed the payment flow")
}
} catch AcceptSDKError.paymentAlreadyInProgress {
// A payment flow is already on screen — wait for it to finish
} catch {
// Handle other AcceptSDKError cases
}Checking Payment Status
Retrieve the status of a previously initiated payment by its token — useful after an app restart or when verifying a payment initiated on another session.
let status = try await Accept.getPaymentStatus(for: paymentToken)Error Handling
All SDK methods throw AcceptSDKError. The error conforms to LocalizedError, so error.localizedDescription
always returns a human-readable message.
| Case | Description |
|---|---|
.notInitialized | Accept.initialize() has not been called, or AcceptCallbackScheme is missing from Info.plist. |
.merchantNotAuthenticated | Accept.authenticate(merchantToken:) has not been called. |
.failedToAuthenticateMerchant | Authentication failed — invalid token or network error. |
.locationPermissionsNotGranted | Location permission was denied or restricted. |
.companionAppNotInstalled | The Tapaya Accept companion app is not installed. |
.paymentAlreadyInProgress | A payment flow is already being presented. |
.kybAlreadyInProgress | A KYB onboarding flow is already being presented. |
.failedToPresent | No visible view controller found to present from. |
.paymentNotFound | No payment matched the provided token. |
.unexpectedPaymentResult | Internal SDK invariant violated — report as a bug. |
do {
let outcome = try await Accept.pay(intent)
} catch AcceptSDKError.merchantNotAuthenticated {
// Re-authenticate before retrying
} catch AcceptSDKError.locationPermissionsNotGranted {
// Prompt the user to allow location access
} catch AcceptSDKError.companionAppNotInstalled {
try await Accept.presentCompanionAppSheet()
} catch {
// Catch-all for other AcceptSDKError cases
print("Payment failed: \(error.localizedDescription)")
}The Tapaya Accept SDK for React Native is a robust, secure, and easy-to-use toolkit that lets you embed payment processing directly into your React Native application. Built to integrate seamlessly with the React Native ecosystem, it offers a clean API, reliable performance, and a developer-friendly experience across platforms.
Installation
Install NPM Package
Add the dependency to your project.
npm i @tapayadot/accept-react-nativeRegister the plugin in your app.json.
"plugins": [
[
"@tapayadot/accept-react-native"
]
]Before first Expo run
Run npx expo prebuild --clean to generate the native bindings before building your app.
Initialization
The AcceptSDK object is the entry point for all SDK functionality. Call initialize() once at app launch.
import AcceptSDK from '@tapayadot/accept-react-native';
// set true for testing environment
await AcceptSDK.initialize(true);Authentication
After initialization, authenticate the merchant using a token obtained from your backend.
const merchantToken = await myBackend.login();
await AcceptSDK.authenticate(merchantToken);Core Concepts
Payment Interface
Companion App Required (iOS)
On iOS, card payments require the Tapaya Accept companion app to be installed.
Use AcceptSDK.isCompanionAppInstalled() to check, and AcceptSDK.presentCompanionAppSheet() to prompt installation if needed.
The SDK exposes payment methods through the AcceptSDK.payments object.
| Method | Description | Use Case |
|---|---|---|
startCardPayment | NFC Card Reader | Contactless EMV payments. |
startSepaPayment | SEPA Instant | Bank-to-bank transfers via QR code. |
startCertisPayment | Certis Payments | Specialized instant payment network. For more information, see the official CERTIS documentation. |
Example of starting a card payment:
import AcceptSDK, { Currency, CardPaymentIntent } from '@tapayadot/accept-react-native';
const paymentIntent: CardPaymentIntent = {
paymentIntentId: Crypto.randomUUID(),
amount: 10000, // 100.00 CZK
requestedCurrency: Currency.CZK,
};
try {
const result = await AcceptSDK.payments.startCardPayment(
paymentIntent,
(status) => {
console.log("Payment Status Update:", status);
},
(message, exception) => {
console.error("Payment Error:", message, exception);
}
);
console.log("Payment Successful:", result);
} catch (error) {
console.error("Payment Failed:", error);
}Onboarding
Before processing payments, you may need to verify the merchant's status or collect additional information
(KYC/KYB). The AcceptSDK.identity module manages these flows.

import AcceptSDK, { KybPrefillData } from '@tapayadot/accept-react-native';
// Launch onboarding UI
await AcceptSDK.identity.presentKyb();
// Optionally prefill known fields
const prefill: KybPrefillData = {
businessType: 'company',
countryCode: 'CZ',
legalName: 'My Company s.r.o.',
registrationNumber: '12345678',
};
await AcceptSDK.identity.presentKyb(prefill);Permissions
Processing payments, especially contactless card payments, requires specific permissions (like Location).
const granted = await AcceptSDK.requestLocationPermission();
if (granted) {
// Proceed with payment
} else {
// Show rationale
}Error Handling
The SDK returns errors through the error callback in payment methods. The error code is an enum AcceptSDKError.
| Error Code | Name | Description |
|---|---|---|
| 1 | Uninitialized | SDK is not initialized. |
| 2 | ServiceStarting | Service is starting. |
| 3 | ServiceInitialization | Service initialization failed. |
| 4 | TokenInitializationError | Error initializing token. |
| 5 | Initialization | General initialization error. |
| 6 | LoginExpired | Login session expired. |
| 7 | InitializeWithoutData | Initialized without necessary data. |
| 8 | LocationPermission | Location permission missing. |
| 9 | LocationDisabled | Location services disabled. |
| 10 | NFCDisabled | NFC is disabled. |
| 11 | NotDebuggable | App is not debuggable. |
| 12 | DebuggableNotDemo | Debuggable app in non-demo mode. |
| 13 | ReaderNotFound | Card reader not found. |
| 14 | ReaderNotReadyYet | Reader is not ready. |
| 15 | ReaderBadConnection | Bad connection to reader. |
| 16 | Offline | Device is offline. |
| 17 | InitializeTransaction | Transaction initialization failed. |
| 18 | FinalizeTransaction | Transaction finalization failed. |
| 19 | OperationTimeout | Operation timed out. |
| 20 | PaymentNotFound | Payment not found. |
| 21 | ServerError | Server error occurred. |
| 22 | ClientError | Client error occurred. |
| 23 | Onboarding | Onboarding error. |
| 24 | DuplicatedOnboarding | Onboarding duplicated. |
| 25 | MissingKYBDetails | Missing KYB details. |
| 26 | LocationNotFound | Location not found. |
| 27 | LocationIdNotFound | Location ID not found. |
| 28 | Unknown | Unknown error. |
| 29 | UnknownMessage | Unknown error message. |
| 30 | Cancellation | Operation cancelled. |
Other Operations
Get Status
Check the current status of the SDK.
const status = await AcceptSDK.getStatus();Get Transaction Info
Retrieve information about a specific payment intent.
const result = await AcceptSDK.getPaymentStatus("payment_intent_id");Log Out
Clear the current session.
await AcceptSDK.logOut();