Every iPhone that will be used to accept payments is represented in Finix by a Device, the same way a physical terminal is. The SDK requires the Device's ID at initialization.
Create the Device first, then pass its ID to TapToPayConfiguration. A missing or un-activated Device doesn't fail at initialization. It shows up later as token and transaction failures.
A Tap to Pay on iPhone Device is specific to one merchant and one physical iPhone. The iPhone side of that identity is Apple's reader identifier, which you store as the Device's serial_number.
These API calls use your Finix API credentials. The recommended pattern is a single "provision Tap to Pay on iPhone device" endpoint in your API that the app calls with the reader identifier (see Cache and reuse the Device ID). Devices can also be created directly in the Finix Dashboard.
Get the reader identifier
Apple assigns each iPhone a stable reader identifier. Fetch it on the device and send it to your backend.
Check for an existing Device
Before creating a Device, check whether one already exists for this Merchant and reader (for example, after the merchant reinstalls your app).
If the response contains a Device whose serial_number matches the reader identifier and whose enabled is true, reuse its id and skip the rest of this page. Confirm the serial_number matches on your side before reusing a result.
Create the Device
Create the Device under the Merchant that receives the payments.
| Field | Value |
|---|---|
model | Always IOS_TAP_TO_PAY. |
name, description | Free-form labels shown in the Finix Dashboard. |
serial_number | The Apple reader identifier from the previous step. |
app_bundle_id | Your app's bundle identifier. Must match the app that takes payments. |
A successful response returns the new Device. Note the id and that the Device starts disabled:
{
"id": "DVxxxxxxxxxxxxx",
"enabled": false,
"model": "IOS_TAP_TO_PAY",
"merchant": "MUxxxxxxxxxxxxx",
"name": "Tap to Pay on iPhone - Front Counter",
"serial_number": "{reader_identifier}",
"created_at": "2026-08-04T17:32:11.000Z"
}Activate the Device
After creating the Device, activate it before taking payments. A successful response returns the Device with "enabled": true.
A Device must be activated (enabled: true) before it can process transfers. If you skip activation, transactions on that Device fail at processing time.
Cache and reuse the Device ID
Provisioning only needs to happen once per Merchant and iPhone pair, so don't repeat it on every launch:
- Persist the
DeviceID keyed by both theMerchantID and the reader identifier. A new iPhone (new reader identifier) or a differentMerchantneeds its ownDevice. - On launch, use the cached ID if present; otherwise run the check-and-create flow above.
- If a transaction fails with an error indicating the
Deviceis not activated or not enabled, discard the cached ID and re-provision on the next attempt.
import ProximityReader
func fetchReaderIdentifier() async throws -> String {
try await PaymentCardReader().readerIdentifier
}
func tapToPayDeviceId(merchantId: String, readerIdentifier: String) async throws -> String {
let cacheKey = "finix_ttp_device_\(merchantId)_\(readerIdentifier)"
if let cached = UserDefaults.standard.string(forKey: cacheKey) {
return cached
}
// Your backend looks up or creates + activates the Device for
// (merchantId, readerIdentifier) and returns its ID.
let deviceId = try await backend.provisionTapToPayDevice(
merchantId: merchantId,
readerIdentifier: readerIdentifier
)
UserDefaults.standard.set(deviceId, forKey: cacheKey)
return deviceId
}