Inter-App Integration
Integrate your POS app with CheckoutX using native app switch. Register terminals, process payments, and scan NFC tags through a bi-directional deep link flow.
Overview
Surfboard’s CheckoutX app handles payment acceptance on Android payment terminals and as a SoftPOS solution. If you have your own POS or business app, you can integrate with CheckoutX through native app switch — your app opens CheckoutX to process a payment, and CheckoutX returns control to your app when done.
This guide covers terminal registration, the payment flow, and NFC tag scanning — all through deep links.
Important: Surfboard terminals operate in full online mode. All data exchange happens through APIs and deep link parameters — no offline data passing is supported.
How It Works
The inter-app flow is a bi-directional app switch:
- Your app -> CheckoutX — initiate a task (registration, payment, or tag scan)
- CheckoutX -> Your app — return the result via your redirect URL
There are three flows:
| Flow | Purpose | Frequency |
|---|---|---|
| Terminal Registration | Link CheckoutX to a terminal | Once per device |
| Payment | Process a payment via CheckoutX | Every transaction |
| Tag Scanning | Read NFC product tags | As needed |
Setting Up Your App for App Switch
Configure your app to receive the callback from CheckoutX after a task completes.
Android
Register a deep link intent filter in your AndroidManifest.xml:
<activity android:name=".YourActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="posapp" android:host="hello" />
</intent-filter>
</activity>
iOS
Register a custom URL scheme in your Info.plist or Xcode project settings. Add your scheme (e.g., posapp) under URL Types.
Configure Terminal Before Payment
Before the first payment (especially after a device reboot), call the configuration route to prepare CheckoutX:
checkoutx://com.surfboard.checkoutx/configure?redirectUrl=REDIRECT_URL
Replace REDIRECT_URL with your base64-encoded app URL. CheckoutX will open, configure itself, and return with isConfigured: true when ready.
Use this step before starting the payment flow for optimal performance on the first transaction.
Terminal Registration (One-Time Setup)
Register a terminal with CheckoutX once per device. This links your Surfboard terminal to the CheckoutX app.
Step 1: Get an Interapp Code
Call the API to generate a registration code:
GET /merchants/:merchantId/stores/:storeId/terminals/interapp
// Response
{
"status": "SUCCESS",
"data": {
"registrationCode": "abc123..."
},
"message": "Interapp code generated successfully"
}
The registration code is valid for 120 seconds. Complete the app switch before it expires.
Step 2: App Switch to Register
Build the registration deep link with the code:
checkoutx://com.surfboard.checkoutx/register?redirectUrl=REDIRECT_URL&data=REGISTRATION_CODE
REDIRECT_URL— your base64-encoded app callback URLREGISTRATION_CODE— base64-encoded JSON:{"registrationCode": "GENERATED_CODE"}
Step 3: Handle the Callback
After registration, CheckoutX calls your redirect URL with a data query parameter containing the terminalId:
posapp://hello/order?orderRef=...&data=<base64_encoded_data>
Decode the base64 data parameter to get the terminal ID:
// Kotlin
val data = String(Base64.getUrlDecoder().decode(uri.getQueryParameter("data")))
val jsonObject = serializer.fromJson(data, JsonObject::class.java)
val terminalId = jsonObject["terminalId"].asString
// Swift
guard let base64String = URLComponents(url: url, resolvingAgainstBaseURL: false)?
.queryItems?.first(where: { $0.name == "data" })?.value,
let jsonData = Data(base64Encoded: base64String),
let json = try? JSONSerialization.jsonObject(with: jsonData) as? [String: Any],
let terminalId = json["terminalId"] as? String
else { return }
Store the terminalId — you need it for all future payments on this device.
Step 4: Verify Registration
Confirm the registration status via API:
GET /merchants/:merchantId/stores/:storeId/terminals/interapp/:interappCode
// Response
{
"status": "SUCCESS",
"data": {
"registrationStatus": "REGISTERED",
"terminalId": "83abab731f6fb00704"
}
}
Possible registrationStatus values: REGISTERED | NOT_REGISTERED
Payment Flow
Once the terminal is registered, process payments through app switch.
Step 1: Create an Order via API
Create an order using the Create Order API with the terminalId from registration. The response includes a paymentId and an interAppJWT:
POST /merchants/:merchantId/orders
{
"terminal$id": "YOUR_TERMINAL_ID",
"orderLines": [
{
"id": "ITEM-001",
"name": "Running Shoes",
"quantity": 1,
"amount": { "regular": 50000, "total": 50000, "currency": "752" }
}
],
"totalOrderAmount": { "regular": 50000, "total": 50000, "currency": "752" },
"controlFunctions": {
"initiatePaymentsOptions": { "paymentMethod": "CARD" }
}
}
// Response
{
"status": "SUCCESS",
"data": {
"orderId": "83a1ba32774149710b",
"paymentId": "83a1ba3264bd500106",
"interAppJWT": "eyJhbGciOiJIUzI1NiIs..."
}
}
Step 2: App Switch to CheckoutX
Build the transaction deep link:
checkoutx://com.surfboard.checkoutx/transaction?redirectUrl=REDIRECT_URL&data=REQUIRED_DATA
REDIRECT_URL— your base64-encoded callback URLREQUIRED_DATA— base64-encoded JSON containing the terminal ID:
{ "terminalId": "YOUR_TERMINAL_ID" }
iOS Performance Optimization
On iOS, include the interAppJWT from the order response in the data parameter for faster payment initiation:
{ "interAppJWToken": "eyJhbGciOiJIUzI1NiIs..." }
Step 3: Perform the App Switch
// Kotlin
val url = "checkoutx://com.surfboard.checkoutx/transaction?redirectUrl=$encodedRedirectUrl&data=$encodedData"
val intent = Intent(Intent.ACTION_VIEW)
intent.data = Uri.parse(url)
startActivity(intent)
// Swift
let url = "checkoutx://com.surfboard.checkoutx/transaction?redirectUrl=\(encodedRedirectUrl)&data=\(encodedData)"
if let deepLink = URL(string: url) {
UIApplication.shared.open(deepLink)
}
// Flutter
String url = "checkoutx://com.surfboard.checkoutx/transaction?redirectUrl=$encodedRedirectUrl&data=$encodedData";
Uri uri = Uri.parse(url);
if (await canLaunchUrl(uri)) {
await launchUrl(uri);
}
Step 4: Handle the Result
CheckoutX calls your redirect URL with the result. Check the order status via API to confirm payment completion:
GET /merchants/:merchantId/orders/:orderId/status
Framing the Redirect URL
The redirect URL follows the format:
<YOUR_SCHEME>://<YOUR_HOST>/<ROUTES>?<QUERY_PARAMS>
For example, if your scheme is posapp and host is hello:
posapp://hello/order?orderRef=6ba7b7db-519f-4ed9-9f6b-a834140466f7
This URL must be base64-encoded before passing it as the redirectUrl parameter:
// Kotlin
val url = "posapp://hello/order?orderRef=6ba7b7db-519f-4ed9-9f6b-a834140466f7"
val encoded = Base64.getUrlEncoder().encodeToString(url.toByteArray())
// Swift
let url = "posapp://hello/order?orderRef=6ba7b7db-519f-4ed9-9f6b-a834140466f7"
let encoded = Data(url.utf8).base64EncodedString()
NFC Tag Scanning
Scan product NFC tags through CheckoutX before or during a sale:
checkoutx://com.surfboard.checkoutx/scanProducts?redirectUrl=REDIRECT_URL&data=REQUIRED_DATA
The REQUIRED_DATA is a base64-encoded JSON specifying the read mode:
{ "readMode": "SINGLE" }
| Read Mode | Description |
|---|---|
SINGLE | Scan one product tag |
MULTIPLE_EDITABLE | Scan multiple tags, allow editing scanned data |
MULTIPLE_NONEDITABLE | Scan multiple tags, no editing allowed |
The redirect URL and app switch mechanics are identical to the payment flow.
Example Repositories
Reference
Other Guides
Tap to Pay on iPhone SDK
Accept contactless payments directly on iPhone. Complete integration guide for Surfboard's iOS SoftPOS SDK -- from setup to production.
Android SoftPOS SDK
Turn Android devices into payment terminals with the Surfboard Android SoftPOS SDK. Complete integration guide from setup to production.
EMV Terminal Integration
Integrate traditional card-present terminals through Surfboard's unified API. From account setup to live payments in one guide.
Payment Page
Redirect customers to a Surfboard-hosted checkout page. The fastest way to accept online payments with minimal integration effort.
Self-Hosted Checkout
Embed a payment form directly in your web app with the Surfboard Online SDK. Full UI control with Surfboard handling PCI compliance.
Server-to-Server API
Process online payments entirely from your backend with Merchant Initiated Transactions. Full control over recurring payments, subscriptions, and tokenized card flows.
Create an Order
Learn how to create orders with line items, tax, customer details, and control functions. The starting point for accepting payments with the Surfboard API.
Merchant Onboarding
Set up merchants and stores on the Surfboard platform. Walk through the full onboarding flow from merchant creation to KYB completion and store setup.
Payment Lifecycle
Manage the full payment lifecycle from order creation through capture, void, cancel, and refund operations using the Surfboard Payments API.
Capture a Payment
Finalize a previously authorized payment by capturing funds. Covers delay capture and pre-authorization flows with step-by-step API examples.
Terminal & Device Management
Manage payment terminals and devices via the Surfboard API. Register in-store and online terminals, configure settings, and handle device operations.
Cancel a Payment
Stop an in-progress payment before it completes. Use cancellation when a customer abandons checkout or a payment needs to be halted mid-process.
Webhooks & Notifications
Receive real-time event notifications via webhooks, email, Slack, and SFTP. Subscribe to payment events and settlement reports for merchants and partners.
Recurring Payments
Implement subscription billing and recurring charges using tokenization, recurring payment configuration, and Merchant Initiated Transactions.
Void a Payment
Reverse a completed payment before settlement. Voiding stops funds from transferring to the merchant's account, avoiding incorrect transactions.
Receipts
Generate, email, print, and customise receipts for in-store transactions using the Surfboard Receipts API.
Refund an Order
Process a full refund by creating a return order with negative quantities. Covers the complete refund flow with API examples and payment method requirements.
Partial Refund
Refund specific items or a reduced amount from a completed order. Process partial returns by creating a return order with only the items to be refunded.
Tips Configuration
Configure tipping on Surfboard payment terminals at the merchant, store, or terminal level using a hierarchical override model.
NFC Tag Reading
Use the NFC Reading API to create tag-reading sessions on payment terminals, scan NFC/RFID-tagged products, and retrieve scanned tag data.
Partial Payments
Split an order across multiple payment methods or transactions. Accept card, cash, and Swish in any combination to settle a single order.
Multi-Merchant Terminals
Set up shared payment terminals for multiple merchants using the Multi-Merchant Group API. Ideal for food courts, events, and co-located businesses.
Store Management
Create, update, verify, and manage in-store and online stores using the Surfboard Payments Store APIs.
Gift Cards & Promotions
Issue and manage gift cards, track transactions, and create marketing promotions using the Surfboard Payments APIs.
Product Catalog
Create and manage product catalogs, products, variants, inventory levels, and analytics through the Catalog API.
Settlements & Reporting
Retrieve settlement reports, view adjustments, manage merchant charges, and register customer profiles for reconciliation and billing.
Account & Service Provider Management
Create merchant and partner accounts, manage user roles, register service providers, and configure external notifications via the Surfboard API.
Payment Methods
Activate, deactivate, and list payment methods for a merchant. Manage card, Swish, Klarna, AMEX, Vipps, MobilePay, and more via the API or Partner Portal.
Client Auth Tokens
Generate client-side authentication tokens for secure API access from browsers and mobile apps without exposing your API key or secret.
Partner Branding
Configure white-label branding for terminals and payment pages. Set colors, fonts, logos, and cover images at the partner level via API or Partner Portal.
Ready to get started?
Create a sandbox account and start building your integration today.