{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-ios/sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":["code-walkthrough","admonition","step"]},"type":"markdown"},"seo":{"title":"Device Setup | iOS Tap to Pay on iPhone SDK Reference","description":"Create a Finix Device for each merchant and iPhone pair before initializing the Tap to Pay on iPhone SDK.","siteUrl":"https://docs.finix.com/","llmstxt":{"hide":false,"sections":[{"title":"Getting Started","includeFiles":["guides/getting-started/**/*.md"],"excludeFiles":[]},{"title":"Online Payments","includeFiles":["guides/online-payments/**/*.md"],"excludeFiles":["guides/online-payments/payment-features/fsa-hsa-non-healthcare-mcc.md"]},{"title":"In-Person Payments","includeFiles":["guides/in-person-payments/**/*.md"],"excludeFiles":[]},{"title":"Subscriptions","includeFiles":["guides/subscriptions/**/*.md"],"excludeFiles":[]},{"title":"After the Payment","includeFiles":["guides/after-the-payment/**/*.md"],"excludeFiles":[]},{"title":"Managing Operations","includeFiles":["guides/managing-operations/**/*.md"],"excludeFiles":[]},{"title":"Platform Payments","includeFiles":["guides/platform-payments/**/*.md"],"excludeFiles":[]},{"title":"Payouts","includeFiles":["guides/payouts/**/*.md"],"excludeFiles":[]},{"title":"Low-Code / No-Code","includeFiles":["low-code-no-code/**/*.md"],"excludeFiles":[]},{"title":"Developers","includeFiles":["additional-resources/developers/**/*.md"],"excludeFiles":[]},{"title":"Plugins","includeFiles":["additional-resources/plugins/**/*.md"],"excludeFiles":[]},{"title":"Industry Considerations","includeFiles":["guides/industry-considerations/**/*.md"],"excludeFiles":[]},{"title":"Regional Considerations","includeFiles":["guides/regional-considerations/**/*.md"],"excludeFiles":[]},{"title":"Release Notes","includeFiles":["release-notes/**/*.md"],"excludeFiles":[]}],"excludeFiles":[]}},"dynamicMarkdocComponents":[],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"CodeWalkthrough","attributes":{"__idx":1,"filters":{},"filesets":[{"files":[{"path":"ios/tap-to-pay/_filesets/device-setup.swift","content":[{"start":0,"condition":{"steps":["get-reader-identifier"]},"children":["import ProximityReader","","func fetchReaderIdentifier() async throws -> String {","    try await PaymentCardReader().readerIdentifier","}"]},"",{"start":8,"condition":{"steps":["cache-device-id"]},"children":["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","}"]},""],"metadata":{"steps":["get-reader-identifier","cache-device-id"]},"basename":"device-setup.swift","language":"swift"},{"path":"ios/tap-to-pay/_filesets/device-setup.sh","content":[{"start":0,"condition":{"steps":["check-existing-device"]},"children":["curl -i \"https://finix.sandbox-payments-api.com/devices?merchant_id={merchant_id}&serial_number={reader_identifier}\" \\","  -u {your_api_key}:{your_api_secret} \\","  -H 'Accept: application/hal+json' \\","  -H 'Finix-Version: 2022-02-01'"]},"",{"start":7,"condition":{"steps":["create-device"]},"children":["curl -i -X POST \\","  -u {your_api_key}:{your_api_secret} \\","  https://finix.sandbox-payments-api.com/merchants/{merchant_id}/devices \\","  -H 'Accept: application/hal+json' \\","  -H 'Content-Type: application/json' \\","  -H 'Finix-Version: 2022-02-01' \\","  -d '{","    \"model\": \"IOS_TAP_TO_PAY\",","    \"name\": \"Tap to Pay on iPhone - Front Counter\",","    \"description\": \"Store 12 front counter iPhone\",","    \"serial_number\": \"{reader_identifier}\",","    \"app_bundle_id\": \"com.example.yourapp\"","  }'"]},"",{"start":23,"condition":{"steps":["activate-device"]},"children":["curl -i -X PUT \\","  -u {your_api_key}:{your_api_secret} \\","  https://finix.sandbox-payments-api.com/devices/{device_id} \\","  -H 'Accept: application/hal+json' \\","  -H 'Content-Type: application/json' \\","  -H 'Finix-Version: 2022-02-01' \\","  -d '{ \"action\": \"ACTIVATE\" }'"]},""],"metadata":{"steps":["check-existing-device","create-device","activate-device"]},"basename":"device-setup.sh","language":"bash"}],"downloadAssociatedFiles":[]}],"steps":[{"id":"get-reader-identifier","heading":"Get the reader identifier"},{"id":"check-existing-device","heading":"Check for an existing Device"},{"id":"create-device","heading":"Create the Device"},{"id":"activate-device","heading":"Activate the Device"},{"id":"cache-device-id","heading":"Cache and reuse the Device ID"}],"inputs":{},"toggles":{}},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"set-up-a-device","__idx":0},"children":["Set up a Device"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["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."]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"warning","name":"Provision before you initialize"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Create the Device first, then pass its ID to ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["TapToPayConfiguration"]},". A missing or un-activated Device doesn't fail at initialization. It shows up later as token and transaction failures."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["A Tap to Pay on iPhone Device is specific to one merchant ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["and"]}," one physical iPhone. The iPhone side of that identity is Apple's ",{"$$mdtype":"Tag","name":"em","attributes":{},"children":["reader identifier"]},", which you store as the Device's ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["serial_number"]},"."]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"info","name":"Run these API calls from your backend"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["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 ",{"$$mdtype":"Tag","name":"a","attributes":{"href":"#cache-and-reuse-the-device-id"},"children":["Cache and reuse the Device ID"]},"). Devices can also be created directly in the Finix Dashboard."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"get-the-reader-identifier","__idx":1},"children":["Get the reader identifier"]},{"$$mdtype":"Tag","name":"CodeStep","attributes":{"id":"get-reader-identifier","heading":"Get the reader identifier"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Apple assigns each iPhone a stable reader identifier. Fetch it on the device and send it to your backend."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"check-for-an-existing-device","__idx":2},"children":["Check for an existing ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Device"]}]},{"$$mdtype":"Tag","name":"CodeStep","attributes":{"id":"check-existing-device","heading":"Check for an existing Device"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Before creating a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Device"]},", check whether one already exists for this ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Merchant"]}," and reader (for example, after the merchant reinstalls your app)."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["If the response contains a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Device"]}," whose ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["serial_number"]}," matches the reader identifier and whose ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["enabled"]}," is ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["true"]},", reuse its ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["id"]}," and skip the rest of this page. Confirm the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["serial_number"]}," matches on your side before reusing a result."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"create-the-device","__idx":3},"children":["Create the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Device"]}]},{"$$mdtype":"Tag","name":"CodeStep","attributes":{"id":"create-device","heading":"Create the Device"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Create the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Device"]}," under the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Merchant"]}," that receives the payments."]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Field"},"children":["Field"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Value"},"children":["Value"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["model"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Always ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["IOS_TAP_TO_PAY"]},"."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["name"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["description"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Free-form labels shown in the Finix Dashboard."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["serial_number"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The Apple reader identifier from the previous step."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["app_bundle_id"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Your app's bundle identifier. Must match the app that takes payments."]}]}]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["A successful response returns the new Device. Note the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["id"]}," and that the Device starts ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["disabled"]},":"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","data-title":"Response","header":{"title":"Response","controls":{"copy":{}}},"source":"{\n  \"id\": \"DVxxxxxxxxxxxxx\",\n  \"enabled\": false,\n  \"model\": \"IOS_TAP_TO_PAY\",\n  \"merchant\": \"MUxxxxxxxxxxxxx\",\n  \"name\": \"Tap to Pay on iPhone - Front Counter\",\n  \"serial_number\": \"{reader_identifier}\",\n  \"created_at\": \"2026-08-04T17:32:11.000Z\"\n}\n","lang":"json"},"children":[]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"activate-the-device","__idx":4},"children":["Activate the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Device"]}]},{"$$mdtype":"Tag","name":"CodeStep","attributes":{"id":"activate-device","heading":"Activate the Device"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["After creating the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Device"]},", activate it before taking payments. A successful response returns the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Device"]}," with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["\"enabled\": true"]},"."]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"warning","name":"Activation is required"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["A Device must be activated (",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["enabled: true"]},") before it can process transfers. If you skip activation, transactions on that Device fail at processing time."]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"cache-and-reuse-the-device-id","__idx":5},"children":["Cache and reuse the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Device"]}," ID"]},{"$$mdtype":"Tag","name":"CodeStep","attributes":{"id":"cache-device-id","heading":"Cache and reuse the Device ID"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Provisioning only needs to happen once per ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Merchant"]}," and iPhone pair, so don't repeat it on every launch:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Persist the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Device"]}," ID keyed by ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["both"]}," the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Merchant"]}," ID and the reader identifier. A new iPhone (new reader identifier) or a different ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Merchant"]}," needs its own ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Device"]},"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["On launch, use the cached ID if present; otherwise run the check-and-create flow above."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["If a transaction fails with an error indicating the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Device"]}," is not activated or not enabled, discard the cached ID and re-provision on the next attempt."]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Next:"]}," ",{"$$mdtype":"Tag","name":"a","attributes":{"href":"/ios/tap-to-pay/installation"},"children":["Installation and initialization"]},"."]}]}]},"headings":[{"value":"Set up a Device","id":"set-up-a-device","depth":1},{"value":"Get the reader identifier","id":"get-the-reader-identifier","depth":2},{"value":"Check for an existing Device","id":"check-for-an-existing-device","depth":2},{"value":"Create the Device","id":"create-the-device","depth":2},{"value":"Activate the Device","id":"activate-the-device","depth":2},{"value":"Cache and reuse the Device ID","id":"cache-and-reuse-the-device-id","depth":2}],"frontmatter":{"seo":{"title":"Device Setup | iOS Tap to Pay on iPhone SDK Reference","description":"Create a Finix Device for each merchant and iPhone pair before initializing the Tap to Pay on iPhone SDK."},"markdown":{"toc":{"hide":true}},"footer":{"hide":true}},"lastModified":"2026-08-11T19:49:07.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/ios/tap-to-pay/device-setup","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}