Getting Started with the SDK
About CafSDK
This technical documentation covers the implementation of CafSDK for iOS, detailing the configuration, initialization, execution of capture flows, and advanced customizations.
Currently, CafSDK integrates 2 main modules: Face Liveness (FL) and Document Detector (DD), executed sequentially with a unified configuration interface.
What is Face Liveness
It is the module that validates the authenticity of a face captured by a photo application, ensuring that the image corresponds to a real person.
Technical characteristics:
URL configuration for authentication (
authBaseUrl
) and liveness verification (livenessBaseUrl
).Flags to enable screen capture and debug mode.
Support for multiple authentication providers.
What is Document Detector
It is the module that enables the capture and processing of documents (e.g., ID card, social security card, passport, etc.).
Technical characteristics:
Configuration of a step-by-step flow defined by
CafDocumentDetectorStep
for document capture.Operational parameters, such as timeout, manual capture flags, and other settings.
Possibility of using the camera for framing validations, or document file upload.
Get started with the SDK
Add the dependency
CafSDK supports integration via both Swift Package Manager (SPM) and CocoaPods, providing flexibility to choose the dependency manager that best suits your project. This guide explains the necessary steps to add CafSDK to your iOS project and provides details about the available modules.
Requirements to add
To use the CafSDK modules in iOS, ensure that your project meets the minimum requirements:
iOS Deployment Target
13.0+
Xcode
16.2+
Swift
5.10+
Note: configure your project's Info.plist with the necessary permissions for camera and network access.
CAF Mobile Token: valid CAF mobileToken
Steps to add
Via Swift Package Manager (SPM)
Step 1 - Add the dependency
Open your project's Package.swift
file and add the following dependency. This tells Swift Package Manager where to locate the CafSDK repository:
dependencies: [
.package(url: "https://github.com/combateafraude/caf-ios-sdk.git", from: "4.1.0")
]
Step 2 - Include the desired products
After adding the dependency, include the necessary products in your application target. This allows you to integrate the full SDK or select only specific modules, according to your needs:
.target(
name: "YourApp",
dependencies: [
.product(name: "CafSDK", package: "CafSDKiOS"), // Full SDK
.product(name: "DocumentDetector", package: "CafSDKiOS"), // Only DocumentDetector
.product(name: "CafFaceLiveness", package: "CafSDKiOS"), // Only CafFaceLiveness
.product(name: "IproovProvider", package: "CafSDKiOS"), // Optional iProov provider
.product(name: "FaceTec2DProvider", package: "CafSDKiOS") // Optional FaceTec 2D provider
]
)
Additional information
Modularity: integrate only the necessary modules to keep your project lightweight.
Compatibility: the SDK is compatible with iOS 13.0+ and was developed with Swift 5.10+.
Version management: Always check the official repository for the latest version (now v4.1.0).
Via CocoaPods
Step 1 - Update your Podfile
To integrate CafSDK using CocoaPods, open your project's Podfile and add the following lines. This will instruct CocoaPods to download the necessary artifacts from the official repository:
# Full SDK
pod 'CafSDKiOS'
# Only DocumentDetector
pod 'CafSDKiOS/DocumentDetector'
# Only CafFaceLiveness
pod 'CafSDKiOS/CafFaceLiveness'
# Optional iProov provider
pod 'CafSDKiOS/IproovProvider'
# Optional FaceTec 2D provider
pod 'CafSDKiOS/FaceTec2DProvider'
Step 2 - Install the dependencies
After updating your Podfile, open a terminal in your project's root directory and run:
pod install
This command downloads and integrates all the specific modules into your project.
Additional Information
Selective integration: choose only the modules necessary for your project, optimizing performance.
Automatic dependency management: CocoaPods automatically manages version resolution and dependency conflicts.
Documentation and support: for more detailed instructions or troubleshooting, consult the CafSDK documentation.
How to initialize the SDK
This guide explains how to initialize the CafSDK on iOS. It covers the requirements, permissions, global configuration, module-specific configuration, and builder initialization.
Permissions
For the SDK modules to function correctly, you must declare the following permissions in your Info.plist:
For Face Liveness:
Camera Usage Description (
NSCameraUsageDescription
): explains why the application needs camera access for face detection.Network access: no explicit permission is required, but ensure your application supports secure connections (HTTPS/WSS).
For Document Detector:
Camera Usage Description (
NSCameraUsageDescription
): required to capture document images.Photo Library Usage Description (
NSPhotoLibraryUsageDescription
): required if your application supports sending images from the library (optional).
Configurations
The initialization process is divided into two parts: global configuration and module-specific configuration.
Global configuration
Create a CafSDKConfiguration
object, which serves as the central container for all configurations. This configuration defines the execution order of the modules and the visual identity (through a color configuration).
Code example:
let sdkConfig = CafSDKConfiguration(
presentationOrder: [.faceLiveness, .documentDetector] // Required
)
Module-Specific configuration
After the global configurations, configure each module individually to adjust the operational, security and visual parameters.
Document Detector configuration
Configure the Document Detector module by specifying the capture flow and options such as manual capture and pop-up confirmations.
Code example:
sdkConfig.setDocumentDetectorConfig(CafDocumentDetectorConfig(
flow: [CafDocumentDetectorStep(stepType: .cnhFull)] // Required for document detector flow
))
Consult: DocumentDetector
Face Liveness configuration
Configure the Face Liveness module to validate that the captured face belongs to a living person. Define options for loading indicators, endpoints and security certificates.
Code example:
sdkConfig.setFaceLivenessConfig(CafFaceLivenessConfig())
Consult: FaceLiveness
Builder initialization
Builder initialization is the step where the CafSDK capture flow is configured for execution. Use CafSdkProvider.Builder
to provide the necessary parameters, including a mobile token, person ID, environment, and the unified callback to handle events.
Code example:
// Create the SDK configuration with the desired modules and custom settings
var sdkConfig = CafSDKConfiguration(
presentationOrder: [.faceLiveness, .documentDetector]
).setDocumentDetectorConfig(CafDocumentDetectorConfig(flow: [CafDocumentDetectorStep(stepType: .cnhFront)])) // Example required document
.setFaceLivenessConfig(CafFaceLivenessConfig())
// Build the SDK with required parameters and a callback for events
let builder = CafSDKProvider.Builder(
self,
mobileToken: "yourToken",
personId: "personId",
environment: .prod,
configuration: sdkConfig,
callback: { [weak self] event in
self?.handleUnifiedEvent(event)
}
)
let sdk = builder.build()
// Start the SDK session
sdk.start()
// Example unified event handler
private func handleUnifiedEvent(_ event: CafUnifiedEvent) {
DispatchQueue.main.async { [weak self] in
guard let self = self else { return }
switch event {
case .loading:
print("🔄 Loading...")
case .loaded:
print("🔄 Loaded")
case .success(let responses):
responses.forEach { response in
print("Module: \(response.moduleName) SignedResponse: \(response.signedResponse)")
}
case .failure(let jwtResponse, let type, let description):
print("Failure: \(type) - \(description ?? "No description")")
if let jwt = jwtResponse {
print("JWT response: \(jwt)")
}
case .error(let type, let desc):
print("Error: \(type) \(desc)")
case .cancelled:
print("⚠️ Cancelled")
case .log(let level, let message):
print("[\(level)] \(message)")
}
}
}
Process details
Global configuration: defines the overall flow and appearance using
presentationOrder
andCafColorConfiguration
.Module-specific configuration: customizes the Document Detector and Face Liveness modules with individual settings (e.g., capture flow, loading indicator, API endpoints).
Initialization with the Builder: the builder pattern gathers all the necessary parameters (mobile token, person ID, environment, configuration, and callback) to create and start the SDK.
Following these steps, your iOS project will be correctly configured to use CafSDK, ensuring a robust and efficient integration of the document detection and face verification modules.
Completing a session
A complete session in CafSDK covers the entire flow, from initialization to completion - whether this completion is a successful validation, an error, or a cancellation by the user.
Session event handling
The builder's callback returns a set of events defined by the CafUnifiedEvent
enumeration. These events include:
Loading
: Indicates a sdk loading requestLoaded
: Indicates a sdk loading finished requestSuccess(responses: [CafUnifiedResponse])
: Final results (whenwaitForAllServices=true
)Failure(response: String?, type: CafFailureType, description: String?)
: Module-specific failuresError(type: CafErrorType, description: String)
: Critical execution errorsCancelled
: User-initiated cancellationLog(level: CafLogLevel, message: String)
: Debugging information
Error Types Breakdown
Failure Types (CafFailureType)
unknown
"unknown"
Generic failure
tooMuchMovement
"too_much_movement"
Excessive head motion
tooBright
"too_bright"
Over-illumination
tooDark
"too_dark"
Low light conditions
misalignedFace
"misaligned_face"
Face alignment failure
eyesClosed
"eyes_closed"
Closed eyes during capture
faceTooFar
"face_too_far"
Face too distant
faceTooClose
"face_too_close"
Face too close
sunglasses
"sunglasses"
Eye-obscuring eyewear
obscuredFace
"obscured_face"
Partial face obstruction
multipleFaces
"multiple_faces"
Multiple faces detected
case .failure(let jwtResponse, let type, let desc):
switch type {
case .eyesClosed:
showAlert("Keep eyes open")
case .multipleFaces:
showAlert("Only one face allowed")
// Handle other cases
}
Error Types (CafErrorType)
unsupportedDevice
Unsupported device specs
cameraPermission
Camera access denied
networkException
Network connectivity issues
serverException
Backend processing failure
tokenException
Invalid/expired token
captureAlreadyActiveException
Concurrent iProov session
unexpectedErrorException
Critical unrecoverable error
userTimeoutException
Capture timeout exceeded
imageNotFoundException
Missing image data
tooManyRequestsException
API rate limit exceeded
unknownException
Unclassified error
libraryException
Low-level framework error
permissionException
Missing system permissions
invalidResponseException
Invalid response received
case .error(let type, let desc):
switch type {
case .cameraPermission:
requestCameraAccess()
case .networkException:
showRetryButton()
case .invalidResponseException:
showAlert("Received invalid response from server")
// Handle other errors
}
Important
A session is considered complete when all modules in the capture flow have finished their operation successfully or when the process is interrupted by an error or a cancellation by the user. In a complete session:
Full execution
Each module that finishes successfully sends a Success
event, including:
moduleName
: identifies the module (e.g., "documentDetector" or "faceLiveness") that completed the operation.signedResponse
: A JWT Token containing the result data obtained by the module`s execution, This data may include information relevant to the process, such as captured images or validation results.
Interrupted flow
If an error occurs or the user cancels the process:
Error
: aCafUnifiedEvent.Error
event is triggered with a descriptive error message, allowing you to recover or notify the user.Cancelled
: aCafUnifiedEvent.Cancelled
event is activated, which allows you to clear resources or present a cancellation message.
Event Handling Example
Check out an example of how to handle these events in the unified callback for iOS:
func handleUnifiedEvent(_ event: CafUnifiedEvent) {
switch event {
case .loading:
// Show a loading indicator
break
case .loaded:
// Update UI to show that modules are ready
break
case .success(let responses):
// Process all successful responses
responses.forEach { response in
print("Module: \(response.moduleName) Result: \(response.signedReponse)")
}
case .failure(let response, let type, let description):
// Handle SDK-specific failures with detailed diagnostics
print("Failure: \(type) - \(description)")
if let response = response {
print("JWT response: \(response)")
}
case .error(let type, let desc):
print("Error: \(type) \(desc)")
case .cancelled:
// Handle cancellation gracefully
break
case .log(let level, let message):
// Log internal messages for debugging purposes
print("[\(level)] \(message)")
}
}
Summary
Complete session: a session is considered complete when all configured modules finish their tasks successfully, or when an error/cancellation occurs.
Centralized management: The unified callback ensures that, regardless of the outcome, your application will be notified and can take the appropriate action.
This approach ensures robust integration with CafSDK, efficiently handling each state of the capture flow, from start to finish.
Advanced flow
This section explains how to customize and adjust the CafSDK capture flow to meet specific business requirements and enhance the user experience on iOS.
Module execution order
The order in which modules are executed is defined by the presentationOrder
field of the CafSDKConfiguration
object. This sequence is crucial, as it directly impacts the flow logic. For example, if the process requires the document to be captured before facial validation, the order must reflect this priority.
Code example:
let sdkConfig = CafSDKConfiguration(
presentationOrder: [.documentDetector, .faceLiveness],
colorConfig: CafColorConfiguration(
primaryColor: "#FF0000",
secondaryColor: "#FFFFFF",
contentColor: "#FF0000",
backgroundColor: "FFFFFFF",
mediumColor: "00FF00"
), // Optional
waitForAllServices: true // Optional
)
Dark Mode / Light Mode
Dark Mode support is enabled by default in the SDK to ensure a consistent user experience across system themes. However, if you want to apply a custom color scheme, they must first check whether the device is currently using Dark Mode or Light Mode, and configure the CafColorConfiguration
accordingly.
Use the system’s interface style to determine the current mode, then adjust the color configuration to match the desired appearance.
let userInterfaceStyle = UITraitCollection.current.userInterfaceStyle
let colorConfig: CafColorConfiguration
if userInterfaceStyle == .dark {
colorConfig = CafColorConfiguration(
primaryColor: "#FFFFFF",
secondaryColor: "#222222",
contentColor: "#FFFFFF",
backgroundColor: "#000000",
mediumColor: "#555555"
)
} else {
colorConfig = CafColorConfiguration(
primaryColor: "#FF0000",
secondaryColor: "#FFFFFF",
contentColor: "#FF0000",
backgroundColor: "#FFFFFF",
mediumColor: "#00FF00"
)
}
let sdkConfig = CafSDKConfiguration(
presentationOrder: [.documentDetector, .faceLiveness],
colorConfig: colorConfig
)
Module-Specific configuration
Customize individual modules using the setDocumentDetectorConfig
and setFaceLivenessConfig
methods. These methods allow you to adjust essential parameters, such as:
Capture timeout: defines the maximum time for manual capture.
Request timeout: sets the maximum wait time for a service response.
Debugging flags: enable or disable debugging modes to identify issues during development.
Layout and other settings: adjust visual and operational parameters specific to each module.
Visual customization
With the CafColorConfiguration
object, you can align the visual identity of the capture flow with your application's design. This ensures that visual elements (buttons, backgrounds, and indicators) are consistent with your brand identity.
Log Registration and Monitoring
The unified callback implements different log levels (DEBUG, USAGE, INFO), allowing detailed monitoring of each step in the flow. These logs are essential for integration with monitoring tools, performance tuning, and real-time issue detection.
Example in the callback:
callback = { event in
switch event {
case .log(let level, let message):
// Log messages for detailed monitoring of the flow
print("[LOG] \(level): \(message)")
default:
break
}
}
Example of configuration chaining:
var sdkConfig = CafSDKConfiguration(
presentationOrder: [.faceLiveness, .documentDetector],
colorConfig: CafColorConfiguration(
primaryColor: "#FF0000",
secondaryColor: "#FFFFFF",
contentColor: "#FF0000",
backgroundColor: "FFFFFFF",
mediumColor: "00FF00"
)
)
.setDocumentDetectorConfig(CafDocumentDetectorConfig(
flow: [CafDocumentDetectorStep(stepType: .cnhFull)]
))
.setFaceLivenessConfig(CafFaceLivenessConfig())
Consult: DocumentDetector and FaceLiveness
* By chaining these configuration calls, you can precisely control the behavior and appearance of each module in the unified flow.
Custom settings - Face Liveness
The Face Liveness module in CafSDK offers robust measures to ensure that the user's face is real and belongs to a living person. It supports multiple providers, such as iProov and FaceTec2D, allowing you to choose or combine solutions based on your requirements.
For detailed customization options, see: Face Liveness Configurations.
To configure Face Liveness
The main configuration object is CafFaceLivenessConfig
, which includes:
Instruction configuration: customizable instructions and steps (via
CafInstructionsConfiguration
) that guide the user.Loading indicator: a flag (
loadingEnabled
) to display a loading indicator during processing.Endpoint URLs (optional):
authBaseUrl
(HTTPS) andlivenessBaseUrl
(WSS) for API communication when using a reverse proxy.Certificates (optional): a list of SHA-256 SPKI encoded base64 hashes for secure communication over WSS, required only when using a reverse proxy.
customLocalization (optional):: This method allows you to specify a custom localization resource name for the iProov module. When a name is provided, the SDK will load the matching localization file instead of the default resource bundle. For further details on the localization files format and integration, please refer to the iProov Localization documentation.
Configuration example:
sdkConfig.setFaceLivenessConfig(CafFaceLivenessConfig(
instructionsConfig: CafInstructionsConfiguration(
enabled: true,
title: "Scan Your Face",
descriptionText: "Follow these steps:",
steps: ["Hold the phone steady", "Ensure good lighting"],
buttonTitle: "Start Scan",
headerImage: UIImage(named: "scan_icon")
),
loadingEnabled: true,
authBaseUrl: "https://my.proxy.io/v1/faces/", // Optional, only used with reverse proxy
livenessBaseUrl: "wss://my.proxy.io/ws/", // Optional, only used with reverse proxy
certificates: ["4d69f16113bed7d62ca56feb68d32a0fcb7293d3960="], // Optional, only used with reverse proxy
customLocalization: "your-customs-strings-file-name"
))
How it works
When faceLivenessConfig
is set in your CafSDKConfiguration
, the Face Liveness module will automatically execute when its position in the presentation order is reached. After successful execution, a CafUnifiedEvent.Success
event is triggered, containing:
moduleName
: the module identifier (e.g., "faceLiveness").signedResponse
: A JWT Token containing the result data obtained by the module`s execution, This data may include information relevant to the process, such as captured images or validation results.
These results can then be processed in your unified callback to update the UI or proceed with your application's flow.
Custom settings
SDK configuration summary
The SDK is configured via CafSDKConfiguration
, which includes settings for:
UI customization (colors, instructions, and images).
Reverse proxy endpoints and security certificates (optional).
Optional parameters like
personId
.
Reverse Proxy Configuration
For Face Liveness (optional)
Use this configuration only if you're routing Face Liveness requests through a reverse proxy.
Requirements:
Protocol:
wss://
(WebSocket Secure).Certificates: Base64-encoded SHA-256 hashes of the certificate's Subject Public Key Info (SPKI).
Configuration:
All reverse proxy settings for Face Liveness are defined using the CafFaceLivenessConfig
structure.
Set the base URL
Use the
livenessBaseUrl
property to define the WSS endpoint.Example:
"wss://my.proxy.io/ws/"
Set the certificates
Use the
certificates
property to provide the SPKI hashes.Example:
["4d69f16113bed7d62ca56feb68d32a0fcb7293d3960="]
Code example:
.setFaceLivenessConfig(CafFaceLivenessConfig(
livenessBaseUrl: "wss://my.proxy.io/ws/", // Optional, only used with reverse proxy
certificates: ["4d69f16113bed7d62ca56feb68d32a0fcb7293d3960=",
"50f71c5dda30741ee4be1ac378e12539b0d1d511f99=",
"9f85e26c1ae41f7ac97adc4099be7f2a40759510ab9="] // Optional, only used with reverse proxy
))
Authentication reverse proxy (optional)
Use this configuration only if you're routing authentication requests through a reverse proxy.
Requirement:
Protocol:
https://
Configuration:
All reverse proxy settings for authentication are defined using the CafFaceLivenessConfig
structure.
Set the Base URL
Use the
authBaseUrl
property to define the HTTPS endpoint.Example:
"https://my.proxy.io/v1/faces/"
Code example:
.setFaceLivenessConfig(CafFaceLivenessConfig(
authBaseUrl: "https://my.proxy.io/v1/faces/" // Optional, only used with reverse proxy
))
Configuration Structures
Caf Face Liveness
Customize the Face Liveness instruction screen.
loadingEnabled
Bool
Enables/disables the loading screen.
true
authBaseUrl
String
HTTPS URL for authentication requests. Optional. Required only for reverse proxy.
""
livenessBaseUrl
String
WSS URL for FaceLiveness WebSocket. Optional. Required only for reverse proxy.
""
certificates
[String]
Base64-encoded SHA-256 SPKI hashes. Optional. Required only for WSS via proxy.
[]
instructionsConfig
CafInstructionsConfiguration
Customize instructions screen (title, steps, images).
See below
Configuration instructions
Customize the Face Liveness instruction screen.
enabled
Bool
Show/hide the instructions screen.
true
title
String?
Header title (e.g., "Face Scan Instructions").
nil
descriptionText
String?
Brief description (e.g., "Follow these steps").
nil
steps
[String]?
Ordered list of instructions (e.g., ["Step 1", "Step 2"]).
nil
buttonTitle
String?
Text for the confirmation button (e.g., "Start Scan").
nil
headerImage
UIImage?
Image displayed at the top of the screen.
nil
Caf Color Configuration
Personalize the interface. All UI elements from both Face Liveness and Document Detector modules will use these colors.
primaryColor
String
Primary buttons, highlights.
Hex code (e.g., #FF0000
)
secondaryColor
String
Secondary elements, borders.
Hex code
contentColor
String
Text and icons.
Hex code
backgroundColor
String
Screen background.
Hex code
mediumColor
String
Neutral elements (e.g., progress bars).
Hex code
Code example
Complete Configuration Code Example.
var facelivenessConfig = CafFaceLivenessConfig(
instructionsConfig: CafInstructionsConfiguration(
enabled: true,
title: "Scan Your Face",
descriptionText: "Follow these steps:",
steps: ["Hold the phone steady", "Ensure good lighting"],
buttonTitle: "Start Scan",
headerImage: UIImage(named: "scan_icon")
), loadingEnabled: true,
authBaseUrl: "https://my.proxy.io/v1/faces/",
livenessBaseUrl: "wss://my.proxy.io/ws/",
certificates: ["4d69f16113bed7d62ca56feb68d32a0fcb7293d3960="]
)
More Information
Certificate Requirements
Certificates must be the base64-encoded SHA-256 hash of the certificate's Subject Public Key Info (SPKI).
Protocol Application
The Face Liveness URL must use wss:// when using a reverse proxy.
The Authentication URL must use https:// when using a reverse proxy.
Default Values
loadingEnabled
istrue
by default.instructionsConfig.enabled
istrue
by default.
SDK Results
Success cases
After successful execution, the CafUnifiedEvent.success
event will contain a [CafUnifiedResponse]
array. For Face Liveness:
case .success(let responses):
if let faceResponse = responses.first(where: { $0.moduleName == "faceLiveness" }) {
let signedResponse = faceResponse.signedResponse
// Process JWT
}
SignedResponse params
Within the signedResponse
, the parameter isAlive
defines the execution of liveness, where true
is approved and false
is rejected.
requestId
Request identifier.
isAlive
Validation of a living person, identifies whether the user passed successfully or not.
token
Request token.
userId
User identifier provided for the request.
imageUrl
Temporary link to the image, generated by our API.
personId
User identifier provided for the SDK.
sdkVersion
Sdk version in use.
iat
Token expiration.
The isAlive parameter is VERY IMPORTANT, as it dictates whether the validation process proceeds or halts. When isAlive: true
, the user gains passage to continue their journey; conversely, if isAlive: false
, the user is deemed invalid and access to further stages of the journey should be denied. This parameter plays a pivotal role in guiding the flow of operations.
Error cases
Refer to Error Types Breakdown
Failure Types
The Face Liveness module provides detailed failure reasons through the CafUnifiedEvent.failure
case. These failure types help identify specific issues during face validation.
public enum CafFailureType: String, Encodable {
case unknown = "unknown"
case tooMuchMovement = "too_much_movement"
case tooBright = "too_bright"
case tooDark = "too_dark"
case misalignedFace = "misaligned_face"
case eyesClosed = "eyes_closed"
case faceTooFar = "face_too_far"
case faceTooClose = "face_too_close"
case sunglasses = "sunglasses"
case obscuredFace = "obscured_face"
case multipleFaces = "multiple_faces"
}
All failure reasons are exclusively returned in GPA liveness validation flows. In LA (Liveness Assurance) flows, any failure will consistently return the generic unknown
error.
unknown
Try again.
✅
✅
tooMuchMovement
Keep still.
❌
✅
tooBright
Move somewhere darker.
❌
✅
tooDark
Move somewhere brighter.
❌
✅
misalignedFace
Keep your face in the oval.
❌
✅
eyesClosed
Keep your eyes open.
❌
✅
faceTooFar
Move your face closer to the screen.
❌
✅
faceTooClose
Move your face farther from the screen.
❌
✅
sunglasses
Remove sunglasses.
❌
✅
obscuredFace
Remove any face coverings.
❌
✅
multipleFaces
Ensure only one person is visible.
❌
✅
Custom Settings - Document Detector
The DocumentDetector module uses machine learning (via TensorFlow Lite) to securely detect and validate documents. This module is highly configurable, allowing you to define custom document flows, preview screens, and manual capture settings.
Document Detector configuration
The main configuration object for this module is the CafDocumentDetectorConfig, which offers options such as:
Flow: An array of
CafDocumentDetectorStep
objects to determine the order and type of document captures.Layout Customization: Define the appearance of the capture interface using the
DocumentDetectorLayout
class. Colors are primarily inherited from the globalCafColorConfiguration
.Upload Settings: Control file format, compression, and maximum file size with
CafUploadSettings
.Manual Capture Options: Enable manual capture, adjust the timeout.
UI String and Asset Customization: Use
ddCustomizations
to provide custom texts and images for specific screens like the upload popup and preview screen.Proxy and Timeout Settings: Configure a proxy and adjust the network timeout for secure document uploads (optional).
Code example:
let documentConfig = CafDocumentDetectorConfig(
flow: [/* Array of CafDocumentDetectorStep items */], // Required
layout: CafDocumentDetectorLayout(),
uploadSettings: CafUploadSettings(enable: true),
manualCaptureEnabled: true,
manualCaptureTime: 45,
requestTimeout: 60,
showPopup: true,
ddCustomizations: [
CafPreviewCustomization(
title: "Is the photo clear?",
message: "Ensure all information is readable.",
okButton: "Yes, it's good!",
tryAgainButton: "Take again"
)
]
)
Available Documents and Customization
CafSDK provides a set of pre-configured documents (e.g., rgFront
, cnhFront
, passport
, etc.). You can customize these documents or create your own flows by adjusting the properties of each CafDocumentDetectorStep
and CafDocument
.
How It Works
When documentConfig
is set in your CafSDKConfiguration
, the Document Detector module automatically runs when it reaches its designated position in the flow.
After a successful execution, a CafUnifiedEvent.Success
event is triggered, containing:
moduleName: The module identifier (e.g.,
"documentDetector"
).signedResponse: A JWT Token containing the result data obtained by the module`s execution, This data may include information relevant to the process, such as captured images or validation results.
These results are then processed in your unified call response, allowing you to proceed with the flow or store the captured information as needed.
Code example:
sdkConfig.setDocumentDetectorConfig(CafDocumentDetectorConfig(
flow: [CafDocumentDetectorStep(stepType: .rgFront)],
manualCaptureEnabled: true,
manualCaptureTime: 45,
requestTimeout: 60,
showPopup: true
))
After the document capture and processing are completed, the Document Detector module triggers a CafUnifiedEvent.Success
event, which includes:
moduleName: The module identifier (e.g.,
"documentDetector"
).result: The captured document data.
Custom configurations - Document Detector
To configure the Caf Document Detector, use the CafDocumentDetectorConfig
structure, which includes:
Document capture flow steps.
User interface (UI) layout customization.
UI String and Asset customizations for specific screens.
Upload behavior.
Proxy settings.
Core configuration
Properties of CafDocumentDetectorConfig
.
flow
[CafDocumentDetectorStep]
Ordered list of document capture steps.
[]
layout
CafDocumentDetectorLayout
UI customization (buttons, fonts, feedback overlays). Colors are primarily themed by global CafColorConfiguration
.
Default layout
uploadSettings
CafUploadSettings
Controls document upload behavior.
enable: false
manualCaptureEnabled
Bool
Enables manual capture button.
true
manualCaptureTime
TimeInterval
Timeout (seconds) for manual capture.
45
requestTimeout
TimeInterval
HTTP request timeout.
60
showPopup
Bool
Shows/hides the initial instruction popup.
true
proxySettings
CafProxySettings?
Reverse proxy configuration (host, port, auth).
nil
previewShow
Bool
Enables post-capture preview screen.
false
ddCustomizations
[CafDDCustomization]?
Array of UI string and asset customizations for Document Detector screens (e.g., upload popup, preview screen).
nil
enableMultiLanguage
Bool
Enables auto-translation of default messages.
true
allowedPassportCountryList
[CafCountryCodes]?
Whitelist of allowed passport countries (e.g., .BR
, .US
).
nil
selectDocumentConfig
CafSelectDocumentConfig?
Configures document selection screen (title/description)
nil
currentStepDoneDelay
TimeInterval
Delay (in seconds) before proceeding after completing a capture step
1.0
Layout customization
Properties of CafDocumentDetectorLayout
. The colors for these elements are primarily influenced by the global CafColorConfiguration
set in CafSDKConfiguration
.
closeButtonImage
UIImage?
Image for the close button.
System default
closeButtonColor
UIColor?
Color of the close button.
Global primaryColor
closeButtonSize
CGFloat?
Size (width/height) of the close button.
44
closeButtonContentMode
UIView.ContentMode?
Content mode for the close button image.
.scaleAspectFit
feedbackColors
CafDocumentFeedbackColors
Colors for feedback overlays (default/error/success).
Predefined colors
font
String?
Custom font name (e.g., "Avenir-Bold").
System font
Code example:
var layout = CafDocumentDetectorLayout()
layout.closeButtonImage = UIImage(named: "close_icon")
// layout.primaryColor is no longer available here, use global CafColorConfiguration
layout.font = "Helvetica-Bold"
layout.feedbackColors = CafDocumentFeedbackColors(
defaultColor: .gray,
errorColor: .red,
successColor: .green
)
UI String and Asset Customization (CafDDCustomization
)
CafDDCustomization
)The ddCustomizations
property in CafDocumentDetectorConfig
allows you to provide an array of objects conforming to CafDDCustomization
to override default texts and images on specific Document Detector screens.
If a customization object for a particular screen is not provided, or a specific property within that object is nil
, the SDK will use its default localized strings and assets.
CafPreviewCustomization
CafPreviewCustomization
Customizes the document preview screen shown after a document image is captured (if previewShow
is true
).
title
String?
Title text on the preview screen.
"Is the photo good?"
message
String?
Subtitle/message text on the preview screen.
"Check if all info is legible..."
okButton
String?
Text for the confirmation ("accept") button.
"Yes, it's good!"
tryAgainButton
String?
Text for the retry ("take again") button.
"Take again"
Example:
let previewCustom = CafPreviewCustomization(
title: "Confirm Photo Quality",
message: "Ensure all details are clear and there are no reflections.",
okButton: "Confirm",
tryAgainButton: "Recapture"
)
// Add to CafDocumentDetectorConfig:
// ddCustomizations: [previewCustom]
CafDDUploadCustomization
CafDDUploadCustomization
Customizes the popup shown when the user chooses to upload a document file.
image
UIImage?
Image displayed at the top of the popup.
Default SDK illustration
title
String?
Title text of the upload popup.
"Upload Document"
message
String?
Message text within the upload popup.
"Select the file..."
uploadButton
String?
Text for the "Upload" button.
"Upload"
cancelButton
String?
Text for the "Cancel" button.
"Cancel"
Example:
let uploadCustom = CafDDUploadCustomization(
title: "Select Your Document",
message: "Please choose the document file you want to upload.",
uploadButton: "Choose File",
cancelButton: "Go Back"
)
// Add to CafDocumentDetectorConfig:
// ddCustomizations: [uploadCustom, previewCustom] // Can have multiple customizations
CafUploadMessagesCustomization
CafUploadMessagesCustomization
Customizes the in-flow quality messages shown during document upload scheduling.
sending
String?
Message shown when the upload starts.
"Sending document... Please wait..."
verifyingIntegrity
String?
Message shown while verifying document integrity.
"Verifying document integrity..."
processingData
String?
Message shown while processing the data.
"Processing document data..."
almostDone
String?
Message shown when upload is nearly complete.
"Almost there... Finalizing upload..."
timeBetweenMessages
TimeInterval?
Interval (in seconds) between each message.
15
Example:
let messagesCustom = CafUploadMessagesCustomization(
sending: "Enviando documento...",
verifyingIntegrity: "Verificando integridade...",
processingData: "Processando dados...",
almostDone: "Quase lá!",
timeBetweenMessages: 20
)
// Add to CafDocumentDetectorConfig:
// ddCustomizations: [messagesCustom]
CafFailedPhotoCustomization
CafFailedPhotoCustomization
Customizes the failure screen shown when a photo fails to send.
title
String?
Title text displayed on the failure screen.
description
String?
Description text explaining the failure.
continueButton
String?
Text for the retry button.
Example:
let failedPhotoCustom = CafFailedPhotoCustomization(
title: "Foto não enviada!",
description: "Não foi possível enviar a foto. Verifique sua conexão.",
continueButton: "Tentar novamente"
)
// Add to CafDocumentDetectorConfig or UploadValidationViewController:
// ddCustomizations: [failedPhotoCustom]
CafMessageCustomization
CafMessageCustomization
Customizes various in-flow messages displayed during the document capture process (e.g., sensor messages, AI feedback).
waitMessage
Shown during SDK initialization.
"Wait"
holdDocumentMessage
Shown when asking user to hold the document steady.
"Hold the document"
fitTheDocumentMessage
Advises aligning document to the mask.
"Fit the document in the marking"
verifyingQualityMessage
Shown during quality check.
"Verifying quality…"
lowQualityDocumentMessage
Shown on capture failure due to quality.
"Oops, try again"
uploadingImageMessage
Shown during image upload.
"Uploading image..."
sensorLuminosityMessage
Low brightness warning.
"Environment too dark"
manualCaptureMessage
Text for manual capture button.
"Manual Capture"
sensorOrientationMessage
Device orientation warning.
"Phone is not horizontal"
sensorStabilityMessage
Device stability warning.
"Keep the phone steady"
popupDocumentSubtitleMessage
Subtitle for the initial instruction popup.
Default instruction subtitle
passportCountryNotValidMessage
Shown if selected passport country is not valid.
"Selected country is not valid"
passportCountryLoadingMessage
Shown while loading passport country data.
"Loading countries..."
aiScanDocumentMessage
Prompt to scan a document (AI).
"Scan a document"
aiGetCloserMessage
Prompt to move closer (AI).
"Get closer to the document"
aiCentralizeMessage
Prompt to center the document (AI).
"Center the document"
aiMoveAwayMessage
Prompt to move farther away (AI).
"Move away from the document"
aiAlignDocumentMessage
Prompt to align the document (AI).
"Align the document"
aiTurnDocumentMessage
Prompt to turn/rotate the document (AI).
"Turn the document"
aiCapturedMessage
Confirmation of successful capture (AI).
"Capturing the document"
Example:
let messageCustom = CafMessageCustomization(
waitMessage: "Please wait...",
fitTheDocumentMessage: "Align your document within the frame."
)
// Add to CafDocumentDetectorConfig:
// ddCustomizations: [messageCustom, previewCustom, uploadCustom]
Document capture flow
Properties of CafDocumentDetectorStep
.
stepType
CafDocumentStepType
Document type to capture (e.g., .rgFront
).
Yes
customStepLabel
String?
Text shown at the bottom of the screen for this step.
No
Document's default label
customIllustration
UIImage?
Image shown in the instruction popup for this step.
No
Document's default illustration
showStepLabel
Bool
Toggles visibility of the step label.
No
true
customMessage
String?
Custom message text for the instruction popup of this step.
No
Document's default message
customOkButtonTitle
String?
Custom text for the 'OK' button in the instruction popup of this step.
No
"OK" (localized)
Code example:
let step = CafDocumentDetectorStep(
stepType: .rgFront,
customStepLabel: "Front of ID",
customIllustration: UIImage(named: "id_front_icon"),
customMessage: "Please place the front of your ID card in the frame.",
customOkButtonTitle: "Got it!"
)
Upload customization
Properties of CafUploadSettings
.
enable
Bool
Enables document upload functionality.
false
compress
Bool
Compresses files before upload.
true
fileFormats
[FileFormat]
Allowed formats: .png
, .jpeg
, .pdf
.
All formats
maximumFileSize
Int
Max file size in KB.
10000
(10MB)
Code example:
let uploadSettings = CafUploadSettings(
enable: true,
fileFormats: [.jpeg, .pdf],
maximumFileSize: 5000
)
Proxy customizations
Properties of CafProxySettings
.
hostname
String
Proxy host (e.g., "proxy.com").
Yes
port
Int
Proxy port (e.g., 8080
).
Yes
user
String?
Authentication username.
No
password
String?
Authentication password.
No
Code example:
let proxy = CafProxySettings(hostname: "my.proxy.io", port: 443)
Supported documents in Document Detector
Use these static values of CafDocumentStepType
(which internally map to CafDocument
):
.rgFront
Front of Brazilian ID (RG)
.rgBack
Back of Brazilian ID (RG)
.rgFull
Brazilian ID (opened, showing front and back)
.cnhFront
Front of Brazilian Driver's License (CNH)
.cnhBack
Back of Brazilian Driver's License (CNH)
.cnhFull
Brazilian Driver's License (opened)
.crlv
Brazilian Vehicle Registration (CRLV)
.rneFront
Front of Brazilian Foreigner ID (RNE)
.rneBack
Back of Brazilian Foreigner ID (RNE)
.ctpsFront
Front of Brazilian Work Card (CTPS)
.ctpsBack
Back of Brazilian Work Card (CTPS)
.passport
Passport (any country)
.any
Generic document (no specific validation)
Note: All enum cases are in camelCase (e.g., use .rgFront
instead of .RG_FRONT
)
Code example:
var layout = CafDocumentDetectorLayout()
// Primary color is set globally via CafColorConfiguration
layout.closeButtonImage = UIImage(named: "close")
let previewCustomization = CafPreviewCustomization(title: "Check Photo", okButton: "Looks Good")
let uploadCustomization = CafDDUploadCustomization(uploadButton: "Select File")
let messageCustomization = CafMessageCustomization(waitMessage: "Please Wait...")
let config = CafDocumentDetectorConfig(
flow: [
CafDocumentDetectorStep(stepType: .rgFront, customMessage: "Place the front of your RG here."),
CafDocumentDetectorStep(stepType: .rgBack)
],
layout: layout,
uploadSettings: CafUploadSettings(enable: true),
proxySettings: CafProxySettings(hostname: "proxy.example.com", port: 8443),
ddCustomizations: [previewCustomization, uploadCustomization, messageCustomization]
)
Technical Support and Usage Tips
For more details and advanced usage scenarios, refer to the following resources:
GitHub Repository: access the source code, issue tracking, and release notes in the CafSDK GitHub repository.
FAQs and Troubleshooting: check our FAQ section for common issues and troubleshooting tips.
Support: for additional assistance, contact our support team or join our developer community forum.
We continuously update the documentation as new features and improvements are released. Stay up to date for future updates!
Release notes
CafSDK iOS v4.1.1
Improvements
Improvements for hibrid analytics (
Flutter / React Native
)
CafSDK iOS v4.1.0
New Features
Added
customLocalization: String?
to FaceLiveness builders.New customization types for DocumentDetector:
CafUploadMessagesCustomization
CafFailedPhotoCustomization
CafSDK iOS v4.0.0
Major Changes
Unified Response API:
CafUnifiedResponse
now exposes onlysignedResponse: String
(no more[String: Any]
result dictionary).Error Handling: Added
invalidResponseException
toCafErrorType
;Breaking Changes:
CafUnifiedResponse
initializer signature changed: noresult
parameter.Property
result
removed; replace all uses withsignedResponse
.
Updated Retry on document upload: in slower connections or interrupted uploads, the documentDetector flow integrated a retry option for document upload
Migration Guide from v3.x
Update Dependency
SPM: use
from: "4.0.0"
CocoaPods:
pod 'CafSDKiOS', '~> 4.0.0'
Callback Handling
case .success(let responses): responses.forEach { response in print("Module: \(response.moduleName) SignedResponse: \(response.signedResponse)") }
Remove
response.result
All references to the
[String: Any]
result map should use response.signedResponse
instead.
Handle
invalidResponseException
In your
.error
switch, add a case for.invalidResponseException
.
Document Detector Flows
If you relied on the old result dictionary, migrate to parsing your JWT from
signedResponse
.
CafSDK iOS v3.0.0
New Features
Improved Analytics
Failure Event Handling: Added detailed
failure
case toCafUnifiedEvent
with server response, error type and descriptionDocument Detector UI Customization:
Introduced
CafDDCustomization
protocol and concrete types (CafPreviewCustomization
,CafDDUploadCustomization
,CafMessageCustomization
) to allow overriding default texts and images on specific Document Detector screens (e.g., preview, upload popup, in-flow messages). This is configured via the newddCustomizations
property inCafDocumentDetectorConfig
.CafDocumentDetectorStep
now includescustomMessage
andcustomOkButtonTitle
properties to customize the instruction popup for each step.
Theming Update:
Document Detector specific color properties (like
primaryColor
,uploadBackGroundColor
,previewBackGroundColor
) have been removed fromCafDocumentDetectorLayout
. The UI now primarily inherits its theme from the globalCafColorConfiguration
set inCafSDKConfiguration
, ensuring a more consistent look and feel.
Updates
Improved error handling differentiation:
Use
CafFailureType
enum type for SDK module-specific operational failuresUse
CafErrorType
enum type for general execution errors
Breaking Changes
Event Signature Updates:
case .failure(response: String?, type: CafFailureType, description: String?)
case .error(type: CafErrorType, description: String) // Replaces old String-based error
Type Safety Enforcement:
All error/failure type comparisons must use enum cases instead of raw strings
CafDocumentDetectorConfig
Changes:Removed
previewTitle
,previewSubtitle
,previewConfirmLabel
,previewRetryLabel
properties. UseCafPreviewCustomization
withinddCustomizations
instead.Removed
messageSettings
property. UseCafMessageCustomization
withinddCustomizations
instead.
CafDocumentDetectorLayout
Changes:Removed
primaryColor
,uploadBackGroundColor
,previewBackGroundColor
properties. Colors are now themed globally viaCafColorConfiguration
.
Migration Guide
Update to v3.0.0+.
Include new
.failure
event
case .failure(response: String?, type: CafFailureType, description: String?)
Update
.error
event
case .error(type: CafErrorType, description: String) // Replaces old String-based error
Update
CafDocumentDetectorConfig
:If you were using
previewTitle
,previewSubtitle
, etc., create aCafPreviewCustomization
object, set its properties, and add it to theddCustomizations
array inCafDocumentDetectorConfig
.If you were using
messageSettings
, create aCafMessageCustomization
object, set its properties, and add it to theddCustomizations
array.
Update
CafDocumentDetectorStep
:If you need to customize the instruction popup message or OK button text for a specific step, use the new
customMessage
andcustomOkButtonTitle
initializers/properties ofCafDocumentDetectorStep
.
Review Theming:
Ensure your global
CafColorConfiguration
(inCafSDKConfiguration
) is set up as desired, as Document Detector UI elements will now primarily use these colors.
CafSDK iOS v2.0.0
New Features
Batch Results Flag:
CafSDKConfiguration(waitForAllServices: true)
now aggregates all module responses into a single.success(responses: [...])
.Unified
.success
Update:.success
now always carries an array of responses.
Breaking Changes
Signature of
CafUnifiedEvent.success
changed tosuccess(responses: [CafUnifiedResponse])
.
Migration Guide
Update to v2.0.0+.
Change handler to expect an array:
case .success(let responses): responses.forEach { resp in /* ... */ }
CafSDK iOS v1.4.0
New Features
Introducing
CafSDKProvider
: A unified entry point for integrating Face Liveness and Document Detector modules with a single configuration.Builder Pattern: Simplified initialization using
CafSDKProvider.Builder
for modular, type-safe setup.Unified Configuration: Configure both modules using
CafSDKConfiguration
, including execution order (presentationOrder
) and UI theming (CafColorConfiguration
).Cross-Module Consistency: Shared authentication, environment, and logging across modules.
Documentation Updates
Revised guides for Swift Package Manager (SPM) and CocoaPods integration.
Added detailed examples for
CafFaceLivenessConfig
andCafDocumentDetectorConfig
.
Configuration Enhancements
Face Liveness
Customize instructions (
CafInstructionsConfiguration
).Configure reverse proxy endpoints (
authBaseUrl
,livenessBaseUrl
).
Document Detector
Define multi-step capture flows (
[CafDocumentDetectorStep]
).UI customization (
CafDocumentDetectorLayout
,CafMessageSettings
).Proxy support (
CafProxySettings
).
Breaking Changes
New integration Module:
CafSDK
Module Renaming:
FaceLiveness
→CafFaceLiveness
,DocumentDetector
→CafDocumentDetector
Updated Dependencies: Requires Xcode 16.2+ and iOS 13.0+
Migration Guide
Replace standalone module initializers with
CafSDKProvider
Update enum cases to lowercase (e.g.,
.CNH_FRONT
→.cnhFront
)Use
CafDocumentDetectorStep(stepType:)
instead of legacy constructors
Last updated