Skip to content

PAX D135 Android Quickstart

Use the Finix Android SDK to integrate the PAX D135 Bluetooth card reader into your Android app and accept in-person payments. This guide covers SDK installation, initialization, and processing your first transaction.

Prerequisites

Before starting, complete the Integration Prerequisites to configure your environment, credentials, and a Device resource.

1. Installation and initialization

Installation

Add the dependency to your Gradle file. See Maven Central or MVN Repository for the latest version.

implementation("com.finix:pax-mpos-sdk-android:3.7.0")
Upgrading SDK version from v2.x

SDK version 3.0.0 is a major update and is not compatible with earlier versions (2.x.x or below). If you use D135 readers in Production on SDK version 2.0.0 or above, contact Finix before updating. We will help guide the rollout and provide extra devices if needed.

Initialization

Add permissions to the AndroidManifest to interact with the mPOS device via Bluetooth.

<!-- For network communication -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

<!-- For bluetooth communication -->
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /><!-- TargetSdkVersion greater than or equal to 31 -->
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />

To interact with the MPOS device, the SDK first needs to be initialized. This can be done by initializing the mposFinix class.

Initialize
class mposFinix(private val context: Context, private val merchantData: MerchantData)

context: Android application context
merchantData: Specific values which help identify the merchant

class MerchantData (
    // Merchant Id from Finix starting with MUxxxx
    val merchantId: String,

    // Finix mid (GUID representation)
    val mid: String,

    // Device ID - device registers with Finix, starting with DVxxxx
    val deviceId: String,

    val currency: Currency = Currency.USD,

    // Sandbox or Production
    val env: EnvEnum = EnvEnum.SB,

    // ROLE_MERCHANT or ROLE_PARTNER UserId
    val userId : String,

    //  ROLE_MERCHANT or ROLE_PARTNER password
    val password: String
)

Example : val mpos = mposFinix(
    context,
    MerchantData(
        merchantId = "MUxxxxxx",
        mid = "",
        deviceId = "DVxxxxx",
        env = EnvEnum.SB,
        userId = "USxxxxxxxxx",
        password = ""
  )
)

Once initialized, connect to the device. When the device is ready for pairing, it will show an orange light and a green light. Once connected, the orange light will disappear and only the green light will stay on.

First Time Device Configuration

When first pairing a PAX D135 the initial configuration may take a few minutes to complete. We recommend that the user experience you build factors in the configuration time to ensure that the user knows the device configuration is in progress.

Connect
fun connect(deviceName: String, deviceAddress: String, callback: MPOSConnectionCallback)

deviceName : bluetooth name of the device
deviceAddress : bluetooth address of the device
callback: exposes functions which are invoked to propagate success, error, progress

interface MPOSConnectionCallback {
    fun onSuccess() // Called if the connection is successfully established
    fun onError(errorMessage: String) // Called if the connection fails for some reason
    fun onProcessing(currentStepMessage: String) // Provides status messages of what's currently happening
}

2. Creating a Device

Create a Device under the Merchant provisioned to process in-person payments. Include the model of the payment terminal you'll be using to process cards.

curl -i -X POST \
  -u USfdccsr1Z5iVbXDyYt7hjZZ:313636f3-fac2-45a7-bff7-a334b93e7bda \
  https://finix.sandbox-payments-api.com/merchants/MUwfZPNW3r4EqLMzwgr6txw4/devices \
  -H 'Content-Type: application/json' \
  -H 'Finix-Version: 2022-02-01' \
  -d '{
    "configuration": {
      "allow_debit": true,
      "allow_standalone_authorizations": false,
      "allow_standalone_refunds": false,
      "allow_standalone_sales": false,
      "bypass_device_on_capture": true,
      "check_for_duplicate_transactions": true,
      "display_tip_on_receipt": false,
      "prompt_amount_confirmation": true,
      "prompt_manual_entry": false,
      "prompt_receipt_confirmation": true,
      "prompt_tip_on_screen": false,
      "tipping_details": {
        "allow_custom_tip": true,
        "fixed_options": [
          100,
          150,
          200
        ],
        "percent_options": [
          18,
          20,
          22
        ],
        "percent_tipping_threshold": 0
      }
    },
    "description": "Cashier Three",
    "integration_mode": "PAYMENT_APP",
    "model": "PAX_D135",
    "name": "My PAX_D135 Finix Device",
    "serial_number": "1904626094"
  }'

A successful response returns the Device resource you will use to initialize the SDK.

Model PAX_D135 Device
{
  "id": "DV4qtWCsxMqZs6gUWPhJu6uQ",
  "created_at": "2026-09-17T21:09:25.453155Z",
  "updated_at": "2026-09-17T21:09:25.453155Z",
  "configuration_details": { 
    "allow_debit": true,
    "allow_standalone_authorizations": false,
    "allow_standalone_refunds": false,
    "allow_standalone_sales": false,
    "automatic_receipt_delivery_methods": null,
    "available_receipt_methods": null,
    "bypass_device_on_capture": true,
    "check_for_duplicate_transactions": true,
    "display_tip_on_receipt": false,
    "idle_image_file_id": null,
    "idle_message": null,
    "prompt_amount_confirmation": true,
    "prompt_for_signature": "NEVER",
    "prompt_manual_entry": false,
    "prompt_receipt_confirmation": true,
    "prompt_tip_on_screen": false,
    "signature_threshold_amount": 10000,
    "surcharge_basis_points": null,
    "tipping_details": {
      "fixed_options": [
        100,
        150,
        200
      ],
      "percent_options": [
        18,
        20,
        22
      ],
      "percent_tipping_threshold": 0
    }
  },
  "description": "Cashier Three",
  "enabled": true,
  "idle_message": null,
  "integration_mode": "PAYMENT_APP",
  "merchant": "MUiV7ntxfY4eyJxp6E7cZvym",
  "model": "PAX_D135",
  "name": "My PAX_D135 Finix Device",
  "serial_number": "1904626094",
  "tags": {},
  "_links": {
    "self": {
      "href": "https://finix.sandbox-payments-api.com/devices/DV4qtWCsxMqZs6gUWPhJu6uQ"
    },
    "merchant": {
      "href": "https://finix.sandbox-payments-api.com/merchants/MUiV7ntxfY4eyJxp6E7cZvym"
    },
    "transfers": {
      "href": "https://finix.sandbox-payments-api.com/transfers"
    },
    "authorizations": {
      "href": "https://finix.sandbox-payments-api.com/authorizations"
    }
  }
}

3. Starting a transaction

To start a transaction, call the startTransaction() function. This will prep the mPOS device to accept card input (swipe, tap, insert). A blue status light displays. Once any action is performed with the card, the device will show a red light to indicate the card has been read. Remove the card at this point.

Start Transaction
fun startTransaction(
    amount: Long,
    idempotencyId: String? = null,
    transactionType: TransactionType,
    transactionCallback: MPOSTransactionCallback,
    splitTransfers: List<SplitTransfer>? = null,
    tags: Map<String, String>? = null,
    buyerIdentityId: String? = null,
    surcharge: Long? = null,
    tipAmount: Long? = null,
    promptForSignature: PromptForSignature = PromptForSignature.Never
)
FieldTypeDescription
amountLong, requiredAmount in cents. e.g. for $10.10, this value would be 1010.
idempotencyIdString?, optionalA randomly generated or internal ID to idempotently identify Transfers, Authorizations, or refund requests.
transactionTypeTransactionType, requiredTransactionType enum - Sale, Refund, or Authorization.
transactionCallbackMPOSTransactionCallback, requiredCallback invoked with the status of the transaction or the Transaction Result.
splitTransfersList<SplitTransfer>?, optionalOptional list of split transfer request data.
tagsMap<String, String>?, optionalOptional map of key/value strings to be provided in the request.
buyerIdentityIdString?, optionalOptional buyer identity associated with this transaction.
surchargeLong?, optionalOptional surcharge amount in cents.
tipAmountLong?, optionalOptional tip amount in cents.
promptForSignaturePromptForSignature, optionalSetting that determines whether a signature should be collected.
MPOSTransactionCallback
interface MPOSTransactionCallback {
    // Called if the transaction is successfully processed
    fun onSuccess(result: TransactionResult?)
    // Called if the transaction fails for any reason
    fun onError(errorMessage: String)
    // Provides status messages of what's currently happening
    fun onProcessing(currentStepMessage: String)
}
PromptForSignature
sealed interface PromptForSignature {
    // A signature should always be collected
    object Always : PromptForSignature
    // A signature should never be collected
    object Never : PromptForSignature
    // A signature is collected if the amount is greater than or equal to the [thresholdAmount]
    class ThresholdAmount(
        val thresholdAmount: Long,
    ) : PromptForSignature
    // A signature is collected based on the response from the card network
    object OnNetworkRecommendation : PromptForSignature
}

Signature upload

When a transaction succeeds, a signature upload can be performed if TransactionResult.signaturePending in MPOSTransactionCallback.onSuccess is true. signaturePending is determined by the promptForSignature value passed with the transaction.

For example, if a transaction was made with amount=500 and promptForSignature=PromptForSignature.ThresholdAmount(400), signaturePending will be true.

In this case your app should capture a signature from the user and call uploadSignature.

Signature Upload
fun uploadSignature(
    // Base64 encoded png of the signature
    pngEncodedBase64: String,
    // traceId of the successful transaction, found in TransactionResult
    traceId: String,
)

Referenced refund

A referenced refund refunds the amount specified (refund amount) of a particular transaction (transaction id) to the card on file.

Referenced Refund
fun startRefund(
    idempotencyId: String? = null,
    transactionId: String,
    refundAmount: Long,
    refundCallback: MPOSRefundCallback
)
FieldTypeDescription
idempotencyIdString?, optionalA randomly generated or internal ID to idempotently identify Transfers, Authorizations, or refund requests.
transactionIdString, requiredThe transaction ID correlating to a previous transaction. Returned as part of the TransactionResult.
refundAmountLong, requiredAmount in cents. e.g. for $10.10, this value would be 1010.
refundCallbackMPOSRefundCallback, requiredCallback invoked with the status of the refund or the Refund Result.

Proguard rules

If you are using ProGuard, please add the following to your ProGuard rules.

#Retrofit
 -dontwarn retrofit.**
 -keep class retrofit.** { *; }
 -keepattributes Signature
 -keepattributes Exceptions
 -keepattributes RuntimeVisibleAnnotations
 -keepattributes RuntimeInvisibleAnnotations
 -keepattributes RuntimeVisibleParameterAnnotations
 -keepattributes RuntimeInvisibleParameterAnnotations

#OkHttp3
 -keepattributes Signature
 -keepattributes *Annotation*
 -keep class okhttp3.** { *; }
 -keep interface okhttp3.** { *; }
 -dontwarn okhttp3.**
 -dontwarn java.nio.file.*
 -dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement

#Gson
  -keep class com.google.gson.stream.** { *; }

#Finix
 -dontwarn com.finix.mpos.sdk.**
 -keep class com.finix.mpos.sdk.** { *; }
 -keep class com.finix.mpos.models.** { *; }
 -keep class com.finix.common.networking.models.** { *; }
 -dontwarn java.lang.invoke.StringConcatFactory

Troubleshooting

If you encounter issues, use sendDebugReport to collect diagnostic information from the Device and send the logs to Finix Support to help troubleshoot the issue.

Send Report - Android
fun sendDebugReport(sendReportCallback: MPOSSendReportCallback)

interface MPOSSendReportCallback {
    fun onError(errorMessage: String?)
    fun onSuccess(result: LogsResponse?)
}
Note

Alternatively, you can send debug logs using the Sample App.