Skip to main content

iOS SDK

Release: AssayraSDK 1.0.0
Minimum deployment: iOS 15
Distribution: versioned local Swift Package for the current trial

1. Download and verify

  1. Download assayra-ios-sdk-1.0.0.tar.gz.
  2. Verify it against SHA256SUMS.
  3. Extract it into a stable location inside your repository:
mkdir -p Vendor/AssayraSDK
tar -xzf assayra-ios-sdk-1.0.0.tar.gz -C Vendor/AssayraSDK

Keep the archive or extracted package under source/dependency control so local and CI builds use the same version.

2. Add the local Swift Package

In Xcode:

  1. Open the application project or workspace.
  2. Choose File → Add Package Dependencies….
  3. Choose Add Local….
  4. Select Vendor/AssayraSDK, the folder containing Package.swift.
  5. Add the AssayraSDK product to the app target that owns verification UI.
  6. In Target → General → Frameworks, Libraries, and Embedded Content, confirm AssayraSDK is listed.

For a Swift package application, add the local dependency and product:

dependencies: [
.package(path: "../Vendor/AssayraSDK")
],
targets: [
.target(
name: "YourApp",
dependencies: [.product(name: "AssayraSDK", package: "AssayraSDK")]
)
]

The package resolves its exact NFC reader dependency from Package.swift; allow that dependency in your organisation’s package policy or mirror it internally.

3. Add iOS permissions

Add clear purpose strings to the app target’s Info.plist:

<key>NSCameraUsageDescription</key>
<string>We use the camera to capture your identity document and verify that you are present.</string>
<key>NFCReaderUsageDescription</key>
<string>We use NFC to read the security chip in supported identity documents.</string>

In Signing & Capabilities:

  1. Add Near Field Communication Tag Reading when your workflow uses NFC.
  2. Add the App Attest/DeviceCheck capability required by your signed application profile.
  3. Test NFC and App Attest on a physical device; the simulator cannot validate the production path.

4. Receive a scoped token

Your backend creates the Assayra application and passes the opaque token from the issued applicant URL to the signed-in app. Never embed a tenant API key in the application bundle.

Create the SDK configuration:

import AssayraSDK

let configuration = AssayraConfiguration(
baseURL: URL(string: "https://your-assayra-origin.example")!,
verificationToken: invitationToken
)

Use HTTPS. allowsLocalSandbox is only for explicit localhost development, never a shipped build.

Option A — hosted SwiftUI view

import AssayraSDK
import SwiftUI

struct IdentityVerificationScreen: View {
let token: String

@StateObject private var verification = AssayraVerificationSession { event in
switch event {
case .complete(_, _, let reference):
NotificationCenter.default.post(
name: .verificationSubmitted,
object: reference
)
case .error(let code, _):
reportSafeVerificationCode(code)
default:
break
}
}

var body: some View {
AssayraVerificationView(
configuration: AssayraConfiguration(
baseURL: URL(string: "https://your-assayra-origin.example")!,
verificationToken: token
),
session: verification
)
}
}

The view uses a non-persistent WebKit data store, constrains navigation and bridge messages to the configured origin, and grants camera capture only to that origin. Treat .complete as navigation to a pending screen; reconcile final state on your backend.

Option B — headless async client

let client = try AssayraClient(configuration: configuration)
let session = try await client.sessionStatus()

let identity = AssayraIdentity(
givenName: "Amara",
familyName: "Vale",
dateOfBirth: "1992-06-14",
nationality: "SG",
email: "person@example.com",
address: "Applicant supplied address"
)

_ = try await client.submitIdentity(identity)

Headless methods cover session state, individual/business data, document upload, guided liveness, ECDD, wallet/attended handoff, NFC and final submission. Re-read sessionStatus() after interruption and render only the returned step.

5. Automatic face capture

The provided native capture view/controller owns the front-camera preview and state sequence. If you build your own camera UI:

  1. Request a fresh livenessChallenge().
  2. Send reduced preview JPEGs to observeLiveness(challenge:jpeg:).
  3. Show the returned guidance.
  4. Auto-capture full-quality frames only after stable, challenge-correct observations.
  5. Submit exactly three fresh frames and timestamps with submitLiveness.
  6. Stop the capture session when the view disappears or the app backgrounds.
let challenge = try await client.livenessChallenge()
let observation = try await client.observeLiveness(
challenge: challenge,
jpeg: reducedPreviewJPEG
)

guidance = observation.guidance
if observation.ready {
// Confirm the challenge-specific pose and retain a fresh evidence frame.
}

An observation is positioning guidance, not an Assayra biometric result. The server performs final liveness/likeness evaluation.

6. Passport NFC

  1. Call startNFC(documentNumber:countryCode:) immediately before reading.
  2. Derive the MRZ access key in protected memory.
  3. Read DG1, DG2, SOD and document-signer evidence with the SDK reader.
  4. Create the device-bound reader statement/App Attest assertion.
  5. Call completeNFC before the server challenge expires.
  6. Clear raw chip/document data from app memory after upload.

Assayra independently validates SOD, data-group hashes and configured CSCA trust. On-device diagnostic booleans are not authoritative.

7. Build and test

From the extracted package folder:

swift test

Then test a signed application on a physical supported device for camera permission denial, interruption/backgrounding, no NFC, failed chip read, expired invitation and completion webhook reconciliation.

Upgrade or remove

To upgrade, verify and extract the new archive over a new versioned folder, update the local package reference, resolve packages, test in Sandbox and commit Package.resolved where your project policy requires it.

To remove, delete the package product from the app target, remove the local package dependency, remove unused permissions/capabilities and delete the versioned vendor folder only after confirming no target references it.