> ## Documentation Index
> Fetch the complete documentation index at: https://eurusys-6c0957fa.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Swift (macOS)

> Integrate the MBKYC SDK into a macOS app using Swift or Objective-C.

The Swift SDK gives macOS apps Emirates ID reading and fingerprint capture through an idiomatic `async/await` API (with callback-style overloads, and full Objective-C support).

<Info>
  **Prerequisites.** To read a card or capture a fingerprint, install the matching macOS **desktop service** first — `mbkyc-pcsc-service` for card readers and the vendor service (e.g. `mbkyc-suprema-service`) for fingerprint. Without them, `listSmartcardReaders()` / `listFingerprintReaders()` return empty. See [Install services on macOS](/distribution/services-macos) and [Supported devices](/distribution/supported-devices). Manual-entry verification needs no services.
</Info>

<Card title="Download the example" icon="download" href="/examples/mbkyc-swift-example.zip" cta="mbkyc-swift-example.zip">
  A self-contained CLI. Drop the XCFramework into `deps/`, fill in the config block, and `swift run`.
</Card>

## Install

The Swift SDK ships as a signed, notarized **XCFramework** — there is no Swift Package Manager or CocoaPods distribution. Download the framework from Nexus and link it into your Xcode project.

<Steps>
  <Step title="Download the XCFramework">
    Fetch it from the raw repository (replace `repo.client.ae` with your [proxied host](/distribution/nexus-overview), and `0.5.0` with the [current version](/reference/versions)):

    ```bash theme={null}
    curl -fsSL -u "$NEXUS_USER:$NEXUS_PASSWORD" \
      https://repo.client.ae/repository/mbkyc-raw/mbkyc/swift-sdk/0.5.0/MBKYCSDK.xcframework.zip \
      -o MBKYCSDK.xcframework.zip
    unzip MBKYCSDK.xcframework.zip
    ```
  </Step>

  <Step title="Add it to your project">
    Drag `MBKYCSDK.xcframework` into your Xcode target's **Frameworks, Libraries, and Embedded Content**, set to **Embed & Sign**. The C library is statically linked inside the framework — there's nothing else to add.
  </Step>
</Steps>

## Initialize

```swift theme={null}
import MBKYCSDK

let mbkyc = try MBKYC.create(
    baseUrl:       "https://api.client.ae",
    apiKeyId:      "key-id",
    tokenSigner:   myTokenSigner,   // signs request inputs via your backend
    logConfig:     LogConfig(logDir: URL(fileURLWithPath: "/var/log/myapp")),
    httpTimeoutMs: 30_000
)
```

The API secret never enters the SDK. You pass a `TokenSignerDelegate` whose `sign(signingInput:completion:)` routes the input to the holder of the secret (your backend), signs it, and returns the signature. See [Authentication](/concepts/authentication).

## Register & validate

Register the device once, then `validate` with the request for your flow:

```swift theme={null}
let readers = try await mbkyc.listSmartcardReaders()

try await mbkyc.registerDevice(name: "lobby-kiosk")   // once per device

let result = try await mbkyc.validate(
    EmiratesIdManual(
        idNumber:       "784-XXXX-XXXXXXX-X",
        documentNumber: "...",
        nationality:    "ARE"
    )
)
print(result.success, result.message)
```

### Validation requests

Each request is a `ValidationRequest` subclass. Pick the one for the document you're verifying — see [Validation methods](/concepts/validation-methods) for when to use each, and [Install services on macOS](/distribution/services-macos) for the hardware prerequisites.

<Tabs>
  <Tab title="Emirates ID">
    **Manual entry** — no hardware required.

    ```swift theme={null}
    EmiratesIdManual(idNumber: "784-XXXX-XXXXXXX-X", documentNumber: "...", nationality: "ARE")
    ```

    **Card read** — needs a smart card reader + `mbkyc-pcsc-service`.

    ```swift theme={null}
    EmiratesIdCard(readerId: reader.id)
    ```

    **+ Fingerprint** — pass a `fingerprint:` to either request above to add a biometric match (needs a fingerprint sensor + its service — see [Biometrics](#biometrics)).

    ```swift theme={null}
    EmiratesIdCard(readerId: reader.id, fingerprint: fingerprint)
    ```
  </Tab>

  <Tab title="Passport">
    **Manual entry** — no hardware required. No biometric variant.

    ```swift theme={null}
    PassportManual(passportNumber: "...", passportType: "P", nationality: "IND")
    ```
  </Tab>
</Tabs>

<Info>
  **Full initializers** (optional params: `dateOfBirth`, `issueDate`, `expiryDate`, `fingerprint`, `clientReferenceId`):

  * `EmiratesIdManual(idNumber:documentNumber:nationality:dateOfBirth:issueDate:expiryDate:fingerprint:clientReferenceId:)`
  * `EmiratesIdCard(readerId:cardDipTimeoutMs:fingerprint:clientReferenceId:)`
  * `PassportManual(passportNumber:passportType:nationality:dateOfBirth:issueDate:expiryDate:clientReferenceId:)`

  Each async method also has a completion-handler overload — `(VerificationResult?, MBKYCError?) -> Void` — for codebases that haven't adopted `async/await`.
</Info>

## Biometrics

Attach a `Fingerprint` to an Emirates ID request (`EmiratesIdCard` or `EmiratesIdManual`) to also match a fingerprint. You supply a `FingerRecommendationDelegate` that picks which finger to capture when the SDK asks:

```swift theme={null}
final class MyFingerDelegate: NSObject, FingerRecommendationDelegate {
    func onFingerRecommendation(
        recommendedFingers: [NSNumber],
        completion: @escaping (FingerSelection) -> Void
    ) {
        let finger = recommendedFingers.first
            .flatMap { Finger(rawValue: $0.uint32Value) } ?? .rightIndex
        completion(.recommended(finger))   // or .custom(.leftMiddle) / .cancel()
    }
}

let fingerprint = Fingerprint(
    readerId: scanner.id,
    recommendationDelegate: MyFingerDelegate())

let result = try await mbkyc.validate(
    EmiratesIdCard(readerId: reader.id, fingerprint: fingerprint))
```

<Info>
  Requires a fingerprint sensor and its [desktop service](/distribution/services-macos) (e.g. `mbkyc-suprema-service`). Get `scanner.id` from `listFingerprintReaders()`.
</Info>

## Error handling

All errors are `MBKYCError: Error` with a typed `ErrorCode` enum:

```swift theme={null}
do {
    _ = try await mbkyc.validate(request)
} catch let err as MBKYCError {
    print("code=\(err.error.rawValue) message=\(err.localizedDescription)")
    if let detail = err.detail { print("detail:", detail) }
}
```

## Objective-C

```objc theme={null}
NSError *error;
MBKYC *mbkyc = [MBKYC createWithBaseUrl:@"https://api.client.ae"
                              apiKeyId:@"key-id"
                           tokenSigner:myTokenSigner
                             logConfig:logConfig
                         httpTimeoutMs:30000
                          extraHeaders:nil
                                 error:&error];
```

<Info>
  `MBKYC` can be used from any queue; hold it for the lifetime of your SDK use.
</Info>

## Full API reference

`async/await` signatures below; each has a completion-handler overload of the form `completion: @escaping (Value?, MBKYCError?) -> Void`. Shared types are in [Data types](/reference/data-types).

| Method                   | Signature                                                                                                 |
| ------------------------ | --------------------------------------------------------------------------------------------------------- |
| Create                   | `static MBKYC.create(baseUrl:apiKeyId:tokenSigner:logConfig:httpTimeoutMs:extraHeaders:) throws -> MBKYC` |
| List smart card readers  | `listSmartcardReaders() async throws -> [ReaderInfo]`                                                     |
| List fingerprint readers | `listFingerprintReaders() async throws -> [ReaderInfo]`                                                   |
| Register device          | `registerDevice(name: String) async throws`                                                               |
| Check registration       | `checkRegistration() async throws -> RegistrationStatus`                                                  |
| Validate                 | `validate(_ request: ValidationRequest) async throws -> VerificationResult`                               |
| Export logs              | `exportLogs(to url: URL) async throws`                                                                    |

**Validation requests** (`ValidationRequest` subclasses — see [Validation requests](#validation-requests) above):

```swift theme={null}
EmiratesIdCard(readerId: String, cardDipTimeoutMs: UInt32 = 5_000,
               fingerprint: Fingerprint? = nil, clientReferenceId: String? = nil)
EmiratesIdManual(idNumber: String, documentNumber: String, nationality: String,
                 dateOfBirth: String? = nil, issueDate: String? = nil, expiryDate: String? = nil,
                 fingerprint: Fingerprint? = nil, clientReferenceId: String? = nil)
PassportManual(passportNumber: String, passportType: String, nationality: String,
               dateOfBirth: String? = nil, issueDate: String? = nil, expiryDate: String? = nil,
               clientReferenceId: String? = nil)

Fingerprint(readerId: String, recommendationDelegate: FingerRecommendationDelegate,
            captureTimeoutMs: UInt32 = 10_000)
```

Cancel by cancelling the enclosing `Task`. Errors are thrown as [`MBKYCError`](/reference/error-codes).
