iOS SDK
Overview
The VerifEye iOS SDK (Verifeye) is a SwiftUI library for embedding the VerifEye verification flow directly into your iOS application. Its single entry point is the VerifyVerifier
The SDK handles the on-device capture and the calls to the VerifEye Service. It does not create sessions or expose results on its own:
- Your backend creates a verification session (using your API key) and returns its
sessionIdandaccessTokento the app. - The
VerifyVerifierview runs the verification using those credentials and invokesonVerificationCompletedwhen the flow finishes. - Your backend fetches the outcome from the VerifEye Service API once the flow completes.
Session creation requires your API key and must happen server-side only. Never ship your API key inside the app — the SDK only ever receives a short-lived session accessToken.
Prerequisites
- iOS 16 or higher, and SwiftUI.
- A VerifEye account and API key from the VerifEye Developer Console.
- A server-side endpoint that creates a verification session and returns its
sessionIdandaccessToken(seeQuick Start ). - An
NSCameraUsageDescriptionentry in your app'sInfo.plist— iOS requires it before any camera access. The SDK requests the runtime camera permission itself, but the usage-description string must be provided by the host app.
<key>NSCameraUsageDescription</key>
<string>We use the camera to verify your identity.</string>
Installation
Add the package with Swift Package Manager. In Xcode: File → Add Package Dependencies…, or in Package.swift:
dependencies: [
.package(url: "https://github.com/Realeyes/Verify-Service-iOS", from: "1.0.2")
]
Then add Verifeye to your target's dependencies and import Verifeye.
Distribution
The SDK ships as a binary XCFramework hosted in a public repository and consumed over SPM. Its third-party native dependencies are embedded inside the framework and hidden from its public interface — so you import Verifeye without adding, resolving, or version-managing any additional packages yourself.
Quick Start
1. Create a session on your server
Call the VerifEye Service to create a verification session, authenticating with your API key. The response contains the session ID and a short-lived session token, which you return to the app.
// Server-side — never expose your API key to the app
// POST https://verifeye-service-api-eu.realeyes.ai/v1/verification/create-session
// Header: Authorization: ApiKey <YOUR_API_KEY>
// Body:
// {
// "verifierConfigs": {
// "liveness": { "type": "Verification", "challengeType": "Balanced" },
// "age": { "type": "CalculationOnly" },
// "gender": { "type": "CalculationOnly" }
// }
// }
// Response: { "verificationSessionId": "...", "sessionToken": "..." }
// Return verificationSessionId -> sessionId and sessionToken -> accessToken to the app.
2. Present the view in your app
Show VerifyVerifier once the session credentials are available, and react to completion.
import SwiftUI
import Verifeye
struct Verification: View {
let sessionId: String
let accessToken: String
var body: some View {
VerifyVerifier(
sessionId: sessionId,
accessToken: accessToken,
onVerificationCompleted: { completedSessionId in
// The flow has finished. Fetch the outcome from your backend, which
// calls the VerifEye Service "Get Session Result" endpoint.
},
region: .eu
)
}
}
onVerificationCompleted fires when the flow finishes — it does not tell you whether verification passed or failed. Retrieve the result server-side via Get Session Result using the sessionId.
3. Read the result on your server
When onVerificationCompleted fires, have the app notify your backend, then fetch the outcome from the VerifEye Service Get Session Result endpoint — again authenticating with your API key, never from the app.
The result stays available for 7 days after the session was created, and returns all captured fields; fields for verifiers you did not enable are null. See Get Session Result for the full response schema.
API Reference
VerifyVerifier
public struct VerifyVerifier: View {
public init(
sessionId: String,
accessToken: String,
onVerificationCompleted: @escaping (String) -> Void,
region: Region = .eu,
onServiceError: ((VerifyServiceOperation) -> Void)? = nil,
consentSkipMode: ConsentSkipMode? = nil,
headless: Bool = false,
headlessCallbacks: HeadlessCallbacks? = nil,
showVerificationSessionId: Bool = false,
apiBaseUrlOverride: String? = nil
)
}
The main SwiftUI view. Present it to run a single verification session. Each session is single-use — to run another verification, create a new session and present a fresh VerifyVerifier.
Forcing a new verification
The view holds its verification state in a @StateObject, so changing only sessionId on an existing view instance does not restart the flow. To run another verification, give the view a new identity with .id(sessionId) so SwiftUI recreates it:
VerifyVerifier(
sessionId: sessionId,
accessToken: accessToken,
onVerificationCompleted: { handleCompleted($0) },
region: .eu
)
.id(sessionId)
(The UIKit VerifeyePresenterpresent(...), so this only applies to the embedded SwiftUI view.)
Parameters
Supporting types
Region
public enum Region { case eu, us }
The supported VerifEye regions.
ConsentSkipMode
Controls whether the camera-consent screen is shown before capture.
When the consentSkipMode parameter is nil, the consent screen is always shown. See
VerifyServiceOperation
public enum VerifyServiceOperation: String {
case initSession = "init-session"
case captureImage = "capture-image"
case verify = "verify"
case unknown = "unknown"
}
Identifies which backend operation was in progress when onServiceError was invoked.
HeadlessCallbacks
Lifecycle hooks used in
public struct HeadlessCallbacks {
public var onVerificationStarting: (() -> Void)?
public var onBeforeCameraAccess: (() -> Void)?
public var onAfterCameraAccess: (() -> Void)?
}
UIKit presenter
If you integrate from UIKit (rather than embedding the SwiftUI view), present verification as a full-screen flow and receive a typed result via completion.
import Verifeye
VerifeyePresenter.present(
from: presentingViewController,
request: VerifeyeRequest(sessionId: sessionId, accessToken: accessToken, region: .eu),
completion: { result in
switch result {
case .completed(let sessionId): handleCompleted(sessionId)
case .serviceError(let operation): handleError(operation)
case .canceled: handleCanceled()
}
}
)
VerifeyeRequest mirrors the view's inputs:
public struct VerifeyeRequest {
public init(
sessionId: String,
accessToken: String,
region: Region = .eu,
consentSkipMode: ConsentSkipMode? = nil,
headless: Bool = false,
showVerificationSessionId: Bool = false
)
}
VerifeyeResult is an enum:
Consent handling
The VerifyVerifier flow accesses the user's camera and processes facial (biometric) data to perform liveness and identity verification. Captured images are used solely to carry out the verification — the SDK does not store them or expose raw biometric data to your application.
Obtaining consent is your responsibility
The hosting application is responsible for obtaining valid, informed user consent for camera access and biometric processing before a verification runs, and for meeting the requirements of the privacy and biometric-data regulations that apply to your users (e.g. GDPR, BIPA, CCPA). See the Realeyes Privacy Policy.
Built-in consent screen
By default, the SDK shows its own consent screen before it requests camera access. This behaviour is controlled by the consentSkipMode
Only disable the built-in consent screen (skipIfCameraGranted or alwaysSkip) when your application already obtains equivalent, legally valid consent for camera access and biometric processing before showing VerifyVerifier. If your application does not handle consent itself, leave the built-in consent screen enabled.
Usage examples
Standard verification
The default, interactive flow — the SDK renders its own full-screen UI and drives the user through consent, liveness, and capture.
VerifyVerifier(
sessionId: sessionId,
accessToken: accessToken,
onVerificationCompleted: { handleCompleted($0) },
region: .eu
)
Headless verification
Set headless to run a verification without the built-in UI — for example, to silently re-verify a user while they keep using your application. Provide headlessCallbacks to hook into the lifecycle, and present a fresh VerifyVerifier with a new session for each verification cycle.
VerifyVerifier(
sessionId: sessionId,
accessToken: accessToken,
onVerificationCompleted: { handleCompleted($0) },
region: .eu,
onServiceError: { handleError($0) },
headless: true,
headlessCallbacks: HeadlessCallbacks(
onVerificationStarting: { /* ... */ },
onBeforeCameraAccess: { /* ... */ },
onAfterCameraAccess: { /* ... */ }
)
)
Handling service errors
Use onServiceError to react to backend failures and inspect which operation failed.
VerifyVerifier(
sessionId: sessionId,
accessToken: accessToken,
onVerificationCompleted: { handleCompleted($0) },
region: .eu,
onServiceError: { operation in
// operation: .initSession | .captureImage | .verify | .unknown
print("Verification failed during: \(operation.rawValue)")
}
)
Targeting an environment
In production, leave apiBaseUrlOverride unset — the SDK targets the production VerifEye Service for the selected region (https://verifeye-service-eu.realeyes.ai or https://verifeye-service-us.realeyes.ai).
apiBaseUrlOverride is an advanced escape hatch for pointing the SDK at a non-production VerifEye environment while integrating; it must not be set for client applications shipping to production.
Next Steps
- Web SDK — the equivalent React library for web applications.
- Android SDK — the equivalent library for Android applications.
- VerifEye Service API — manage verification configurations and retrieve session results server-side.
- Authentication — API key and bearer token authentication for server-side calls.
Last updated: 2026-08-04