Palm Verification SDK Guides /

iOS Integration

iOS Integration

1. Install the SDK#

CocoaPods#

pod 'VerySDK', '~> 1.0.64'

Then run pod install.

Swift Package Manager#

dependencies: [
    .package(url: "https://github.com/veroslabs/very-sdk-ios.git", from: "1.0.64")
]

2. Configure your app#

Add camera permission to Info.plist:

<key>NSCameraUsageDescription</key>
<string>Camera access is needed for palm biometric verification.</string>

3. Enroll a new user#

Pass nil for userId to register a new user. The SDK opens a consent screen, then guides the user through a palm scan.

import VerySDK

// Check device support first
guard VerySDK.isSupported() else {
    print("Device not supported")
    return
}

let config = VeryConfig(
    sdkKey: "your_sdk_key",    // from Developer Portal
    userId: nil,                // nil = new enrollment
    clientReferenceId: "gate-withdrawal-42", // your transaction/session ID
    themeMode: "dark"           // "dark" or "light"
)

VerySDK.authenticate(
    from: self,
    config: config,
    presentationStyle: .modal   // .modal, .push, or .embed
) { result in
    if result.isSuccess {
        print("User ID: \(result.userId)")
        print("User status: \(result.userStatus ?? "unknown")")
        print("Signed token: \(result.signedToken ?? "")")
    } else {
        print("Error: \(result.errorType) — \(result.errorMessage ?? "")")
    }
}

4. Verify an existing user#

Pass the user's ID from a previous enrollment to verify their identity.

let config = VeryConfig(
    sdkKey: "your_sdk_key",
    userId: "vu-1ed0a927-...",  // existing user's ID from previous enrollment
    themeMode: "dark"
)

VerySDK.authenticate(
    from: self,
    config: config,
    presentationStyle: .modal
) { result in
    if result.isSuccess {
        print("Verified user: \(result.userId)")
        print("Signed token: \(result.signedToken ?? "")")
    } else {
        print("Error: \(result.errorType) — \(result.errorMessage ?? "")")
    }
}

5. Verify the signed token (backend)#

When authentication succeeds, the SDK returns userId and signedToken. Send signedToken to your backend:

POST /api/verify-palm
Content-Type: application/json

{
  "signedToken": "eyJhbGciOiJFZERTQSIsImtpZCI6..."
}

Follow the secure backend verification example to validate the EdDSA signature, key ID, issuer, app audience, time window, action, session and token IDs, and expected user. After all checks pass, trust sub as the user's VeryAI ID:

{
  "iss": "https://api.very.org",
  "sub": "vu-1ed0a927-a336-45dd-9c73-20092db9ae8d",
  "aud": "your_app_id",
  "act": "verify",
  "sid": "sdk_session_id",
  "jti": "34fa6d08-28d4-4a29-85f8-5064ea8ae32e",
  "exp": 1761010175,
  "iat": 1761009875
}
  • For enrollment: store the sub (user ID) - use it for future verifications
  • For verification: confirm the sub matches the expected user
  • code is an SDK status string, not an OAuth authorization code

VeryConfig#

Parameter Type Description
sdkKey String Your SDK API key from the Developer Portal
userId String? nil for enrollment, user ID for verification
clientReferenceId String? Your transaction or session ID (up to 255 characters), included in webhook events for the review started by this SDK call
language String? BCP 47 locale code (e.g. "en", "es", "en-IN", "zh-HK") — see supported languages. Defaults to device language.
themeMode String "dark" (default) or "light"
customStrings [String: String]? Override the palm-scan status copy, keyed by VeryCustomString. Set by property assignment after init. See Custom strings.

Custom strings#

Override the palm-scan status copy with customStrings, keyed by the stable VeryCustomString constants. A caller-supplied value takes priority over the SDK's built-in localized string; blank values and unknown keys fall back to the localized default. The SDK renders your value verbatim, so pass already-localized text.

let config = VeryConfig(sdkKey: "your_sdk_key", userId: nil)

// Override the palm-scan status copy. A caller value wins over the
// built-in localized string; blank values and unknown keys fall back
// to the localized default. Pass your own already-localized text.
config.customStrings = [
    VeryCustomString.showYourHand:      "Hold up your palm",
    VeryCustomString.showYourFirstHand: "Hold up your first palm",
    VeryCustomString.connectDots:       "Connect the dots",
]
Key Default text Where it shows
VeryCustomString.showYourHand Show your hand Default scan-page status
VeryCustomString.showYourFirstHand Show your first hand Scan-page status during first-time enrollment
VeryCustomString.connectDots Connect the dots "Connect the dots" gesture prompt

VeryResult#

Property Type Description
isSuccess Bool true if authentication completed successfully
code String SDK status string, not an OAuth authorization code
userId String The user's app-scoped VeryAI ID
signedToken String? Ed25519-signed JWT for backend verification
userStatus String? Consolidated status. pending is a successful submission awaiting review.
errorType VeryErrorType Typed error code (see Error Handling)
errorMessage String? Human-readable error message

Presentation styles#

  • .modal — presented as a modal sheet (default)
  • .push — pushed onto the current navigation stack
  • .embed — embedded as a child view controller

Important: Palm Verification SDK verification uses signedToken and JWKS. It does not use OAuth client_id, client_secret, or code exchange.

VeryAI

Get the VeryAI app

Scan the QR code to download the app