iOS Migration
Upgrade Paths
From 2023.x to 2025.0.0
New
- This release provides access to Sensibil UI. See Launch Sensibill UI page.
Changed
Platform Compatibility
No change in requirements from 2023.1.2. If upgrading from the earlier 2023.x release, the following significant updates should eb considered:
- The legacy universal framework distribution is no longer provided. The SDK is now distributed only in
.xcframework
format. - Minimal iOS version is 16.0
- Xcode 16.2
Please review the latest Supported Platforms for more information.
Common
In this release a more consistent namespacing was introduced for major SDK use cases (SensibillSDK, Capture, CaptureFlow, SMUI and Branding). This caused the need to rename the following components:
Previous Name | New Name |
---|---|
Credentials | SensibillSDK.Credentials |
Analytics | SensibillSDK.Analytics |
TrackingEvent | SensibillSDK.Analytics.TrackingEvent |
EventListener | SensibillSDKAnalyticsEventListener |
CaptureNavigationController | Capture.NavigationController |
CaptureResult | Capture.CompletionResult |
CaptureFlowCoordinator | CaptureFlow.Coordinator |
CaptureFlowCoordinator.DidFinishCaptureResult | CaptureFlow.ProcessingInfo |
DocumentMetadata | CaptureFlow.DocumentMetadata |
Capture
Advanced Tips feature customization was moved from
UIParts
toCapture
namespace.// Prior to 2025.0, could be accessed as follows: let tipsScreenStyle = UIParts.TipsFeature.TipsScreenStyle(...) // With 2025.0, both elements are accessed in the same way: let tipsScreenStyle = Capture.TipsFeature.TipsScreenStyle(...)
The elements used for advanced Capture customization via
Capture.RuntimeSettings
modification, were moved fromCapture.RuntimeSettings
andUIParts
namespaces toCapture.Theme
namespace.For example:
// Prior to 2025.0, could be accessed as follows: let cropShapeStyle = Capture.RuntimeSettings.CropShape(...) let doneButtonStyle = UIParts.MainActionButtonStyle(...) // With 2025.0, both elements are accessed in the same way: let cropShapeStyle = Capture.Theme.CropShape(...) let doneButtonStyle = Capture.Theme.MainActionButtonStyle(...)
Capture Flow
- Document Monitoring. Access to add/remove observer was simplified. Instead of
SensibillSDK.shared.documentUploadService
these functions can be accessed directly fromSensibillSDK
, i.e.:// Before 2025.0 SensibillSDK.shared.documentUploadService.addObserver(...) SensibillSDK.shared.documentUploadService.removeObserver(...) // With 2025.0 SensibillSDK.addObserver(...) SensibillSDK.removeObserver(...)
Discontinued
Headless Access
Sensibill SDK no longer provides a direct headless access to Sensibill API client and SDK services. This includes the following changes:
Access to
SensibillAPIClient
, which could be accessed viaSensibillSDK.shared.apiClient
, and provided a library of Sensibill APi requests and models, is no longer provided. You can implement a custom client which allows the same functionality. This change also made the following classes, protocols and namespaces unavailable:AuthenticationEndpointsProvider, DocumentsEndpointsProvider, EmailAccountsEndpointsProvider, EmailsEndpointsProvider, EndpointsProvider, ExportsEndpointsProvider, FoldersEndpointsProvider, HomeEndpointsProvider, InterceptsEndpointsProvider, LookupsEndpointsProvider, MerchantsEndpointsProvider, ReceiptsEndpointsProvider, RemindersEndpointsProvider, SensibillAPIProvider, TaskContextProvider, UserAccessTokenDelegate, UsersEndpointsProvider, EndpointVersion, SensibillAPIModel, SensibillAPIModelDocumentType
Access to
IdentityService
, which could be accessed viaSensibillSDK.shared.identityService
, and allowed to access client and user identity information, is no longer provided. You can obtain the same information by implementing direct requests to Sensibill API:users/{userID}
request to obtain user informationclientInfo
request to obtain client information
Access to
DocumentUploadService
, which could be accessed viaSensibillSDK.shared.documentUploadService
is no longer provided.- Access to
addObserver
andremoveObserver
(used for Capture Flow use case) is now available directly throughSensibillSDK
. See Migrate > Capture Flow section above. - Access to functions that allowed adding and removing documents for uploading is no longer provided. Implement Full SDK or Capture Flow use cases to take the advantage of fascilitated upload, or implement custom request to Sensibill API’s’
POST .../v2/document
- Access to
Other
The following components, which are no longer available publicly, didn’t provide any value to integrators, and shouldn’t have been used:
ClientIdentity, DetectedReceipt, IdentityBasedService, SensibillSDK.StateProvider, UserIdentity, BrandingMetadataProvider, CredentialsDelegate, UIParts
From 2022.0.6 to 2025.0.0
New
- In 2023.0 the various branding options in the SDK were unified into a
Branding
object. The main idea behind theBranding
was to allow the integrator override any colors, fonts, images, and strings in any way they like, while providing guaranteed defaults to any parts of branding which were not customized. See iOS Branding Basics for more details onBranding
concepts and usage.
Changed
Platform Compatibility
- The legacy universal framework distribution is no longer provided. The SDK is now distributed only in
.xcframework
format. - Minimal iOS version is 16.0
- Xcode 16.2
Common
Naming
Between 2023.0 and 2025.0 releases, we introduced namespacing for major SDK use cases (SensibillSDK, Capture, CaptureFlow, SMUI and Branding). This caused the need to rename the following components:
Previous Name | New Name |
---|---|
Credentials | SensibillSDK.Credentials |
Analytics | SensibillSDK.Analytics |
TrackingEvent | SensibillSDK.Analytics.TrackingEvent |
EventListener | SensibillSDKAnalyticsEventListener |
CaptureFeatureFlags | Capture.FeatureFlags |
CaptureResult | Capture.CompletionResult |
CaptureNavigationController | Capture.NavigationController |
CaptureFlowCoordinator | CaptureFlow.Coordinator |
SDKConfiguration
SDKConfiguration
, used by all SDK use caases, was replaced with Branding
in SDK 2023.0. See iOS Branding Basics
for more details on Branding
concepts and usage.
Branding
object is not a singleton, like SDKConfiguration was. It is provided as part of SensibillSDK.Configuration
object on SensibillSDK.start
. Also Branding object is created with defaults for all properties, so the integrator can change only items they are interested to customize.
The basic Branding setup is as follows:
// Start from default branding
let branding = Branding()
// Override any aspects of branding (all overrides are optional)
branding.colors = MyCustomColors() // BrandingColorsProvider
branding.fonts = MyCustomFonts() // BrandingFontsProvider
branding.images = MyCustomImages() // BrandingImagesProvider
branding.localization = MyCustomLocalization() // BrandingL10NProvider
// For Full SDK or Capture Flow use cases,
// create a configuration, and pass it to SensibillSDK.start
let configuration = SensibillSDK.Configuration(
environment: .beta,
branding: branding
)
SensibillSDK.start(..., configuration: configuration, ...)
// For Standalone Capture,
// create Capture.RuntimeSettings, and pass them to Capture.NavigationController
let receiptRuntimeSettings = Capture.RuntimeSettings.receipt(branding: branding)
let captureNavigationController = Capture.NavigationController(settings: receiptRuntimeSettings)
The following provides the guidance on migration of every property:
Color Customization:
SDKConfiguration.colors
is replaced withbranding.colors
. To customize, implementBrandingColorsProvider
, and override any colors you wish to customize.Example:
// You can override colors used by all SDK components var primary: Color { Color(red: 0.91, green: 0.57, blue: 0.30) } // You can override Capture-specific colors var captureBackground: Color { .indigo }
Font Customization:
SDKConfiguration.fonts
andSDKConfiguration.sensibillUI.webFonts
are replaced withbranding.fonts
. To customize, implementBrandingFontsProvider
, and override any fonts you wish to customize.Example:
class MyCustomFonts: BrandingFontsProvider { // Override some fonts used for Capture and SDK screens (e.g. Errors) // No need to override every font var caption: Sensibill.Branding.FontDefinition { Branding.FontDefinition(name: Faces.elegant, size: 12, style: .largeTitle) } // Override fonts provided to Sensibill Web UI (replaces sensibillUI.webFonts) var forWebUI: (family: String, url: String)? { ( family: "Lobster, Times, serif", url: "https://fonts.googleapis.com/css2?family=Lobster&display=swap" ) } }
Image Customization: previously only allowed overriding images by providing imageset with exactly the same name as the one you override. With
branding.images
, you can store images in any way you want. ImplementBrandingImagesProvider
, and override any images you like. You can use system images, or custom imagesets stored in any bundle, with any names.Example:
class MyCustomImages: BrandingImagesProvider { // Only override images you want to change // No need to override every image // Using system image var captureTipsIcon: UIImage { UIImage(systemName: Images.info)! } // Or using custom imageset in custom bundle var captureCloseIcon: UIImage { UIImage(named: "myImage", in: Bundle(identifier: "myCustomBundle"), with: nil)! } } // ... branding.images = MyCustomImages()
SDKConfiguration.capture
provided the ability to specify various aspects of Capture configuration. This property is now replaced byBranding
andCapture.FeatureFlags
as explained below:Capture feature flags: renamed to
Capture.FeatureFlags
, Capture feature flags can be provided, much like branding toSensibillSDK.Configuration
(Full SDK, Capture Flow use cases), orCapture.RuntimeSettings
(Standalone Capture):let featureFlags: Capture.FeatureFlags = .default featureFlags.attachLocationData = true // An example of modified feature flag // For Full SDK or Capture Flow use cases, // create a configuration, and pass it to SensibillSDK.start let configuration = SensibillSDK.Configuration( environment: .beta, captureFeatureFlags: featureFlags ) SensibillSDK.start(..., configuration: configuration, ...) // For Standalone Capture, // create Capture.RuntimeSettings, and pass them to Capture.NavigationController let receiptRuntimeSettings = Capture.RuntimeSettings.receipt(featureFlags: featureFlags) let captureNavigationController = Capture.NavigationController(settings: receiptRuntimeSettings)
Capture UI Customization: the overall branding of the capture was unified with the rest of the SDK in
Branding
object (see above). In case an advanced customization of the specific elements is needed (such that doesn’t match the rest of the branding), it can be done inCapture.RuntimeSettings
object. See Capture Customization section.Tips Customization: is done through
Branding
object as well. See Customizeing Tips page.
externalBundle
provided an ability to specify where to look for images, fonts and strings.- With
Branding
, integrator has a complete freedom on where and how to store images and fonts. See Image Customization section above for an example. - Bundle still can be provided for localizations as a static property of
Branding
(you can initialize it at any point before starting SDK):This property is used by a default implementation ofBranding.Resources.localizationBundle = Bundle(...)
BrandingL10NProvider
. Alternatively you can implement your ownBrandingL10NProvider
(to resolve strings and localizations in any way you like) and assign it tobranding.localization
as shown above.
- With
certificatePinningEnabled
was removed, no longer supported by Sensibill API.
Full SDK
SensibillSDK.start
Sensibill.plist
is no longer used and should be removed from the app.SensibillSDK.start
have changed:class func start( userIdentifier: String, // renamed from cacheIdentifier tokenProvider: TokenProvider, // moved to 2nd place configuration: SensibillSDK.Configuration, // NEW, see explanation below completion: @escaping (Result<Void, Error>) -> Void // CHANGED, see explanation below )
The argument
configuration
replacesSensibill.plist
and defines Sensibill API environment to be used.The
completion
signature was changed to returnResult<Void, Error>
instead ofError?
. Note: the function withError?
as a callback result is still provided for usage with Objective-C.The
async
version of the function was introduced as an alternative for the cases where it’s more convenient than a traditional function with callback.Version for use with Objective-C is also available.
Please follow the detailed instructions on Starting iOS SDK page.
SensibillSDK.stop
Similarly to start, the SensibillSDK.stop
function now returns its result in Result<Void, Error>
format, has async
version, and a version for use with Objective-C. Please check Stopping iOS SDK
page for more information.
SensibillSDK.userDefinedLocale
The localization and strings are now managed by a Branding
package. If you wish to override how the localization is applied and handled, please follow the instructions provided in iOS Branding Strings - Advanced Customization
section. For instance, selectedLocale
of the BrandingL10NProvider
allows you to specify how Sensibill SDK should select a locale.
TokenProvider
The signature of provideTokenReplacement
function was changed to include userIdentifier
(the same identifier as used on SDK start). This is done to allow the integrators ensure that the token SensibilL SDK is requesting is for the currently authenticated user. Please see example on how to implement TokenProvider on iOS Authentication
page.
Starting Sensibill UI
The basic way to start Sensibill UI:
// Assuming SDK is already started
// Old way
private var sensibillUICoordinator = SensibillUICoordinator(host: self) // 1
sensibillUICoordinator.delegate = self // 2
sensibillUICoordinator.start() // 3 - default: starts UI modally
// New way
SensibillSDK.shared.smui.delegate = self // same as line 2
SensibillSDK.shared.smui.start( // same as line 3
modalOver: self, // uses the same value, as host from line 1, and starts UI modally
animated: true
)
Additional customization:
To manage the presentation method, the new way provides different methods (instead of options), each with its own set of properties, suitable for that presentation method.
To embed:
// Old way let sensibillUICoordinator = SensibillUICoordinator(host: self, presentationMethod: .embed) sensibillUICoordinator.start() // New way SensibillSDK.shared.smui.start(embedIn: self)
To push:
// Old way let sensibillUICoordinator = SensibillUICoordinator(host: self, presentationMethod: .push) // The SDK would try to extract UINavigationController from the provided UIViewController // If it succeeeds, then sensibillUICoordinator.start() // New way // The integrator is in charge of which UINavigationController to use // For example we can use the one available from the current UIViewController guard let navigationController = self.navigationController else { return } SensibillSDK.shared.smui.start( pushTo: navigationController animated: true )
The
StartOption.animated
is now a direct argument of thestart
function, and is only provided for methods that allow animation (modal and push).The
StartOption.navigationIntent
is now a direct argument of everystart
method.
Capture Flow
CaptureFlowCoordinator, which was renamed to CaptureFlow.Coordinator
, provides an access to a Capture experience, seamlessly integrated with the reliable and easy to use receipt uploading to Sensibill API. Additionally it allows to link a captured document to a bank transaction, monitor document uploading and processing, and display an Edit Metadata screen, which provides an ability to specify Folder, Category and the Notes for all the uploaded documents.
Initialization
Depending on Sensibill API version you use, you can initialize CaptureFlow.Coordinator
as follows:
// With default Sensibill API version (v2)
// Note: Edit Metadata screen cannot be used with API v2
let coordinatorV2 = CaptureFlow.Coordinator(host: self)
// With Sensibill API v1 (can be used with Edit Metadata screen)
let coordinatorV1 = CaptureFlow.Coordinator(apiVersion: .v1, host: self)
Note that to display Edit Metadata screen at the end fo Capture flow, you must specify Sensibill API .v1
.
CaptureFlow.Coordinator.start
- The method
start()
did not change - The methods
start(transaction:)
andstart(expenseType:)
were replaced withstart(metadata: CaptureFlow.DocumentMetadata)
, which allows to specify bank account and bank transaction information at once. See Bank Transaction Linking page for more details.
CaptureFlowCoordinatorDelegate
The delegate provides the same events, however in case of coordinatorDidFinishCapture
event, the Transaction
object was replaced with CaptureFlow.ProcessingInfo
. It contains an array of sourceIds
, which can then be used to monitor document upload, or provided to Edit Metadata screen. The pages Displaying Metadata Screen
provides an example of the delegate that launches Edit Metadata screen.
Discontinued
Certificate pinning was removed
SensibillSDK
no longer provides public access to the following properties and methods. They didn’t provide any value to integrators, and shouldn’t have been used:tokenProvider, locale, updateToken(completion:)
SDK no longer provides password authentication option, thus
PasswordAuthenticator
was removed.The
ReceiptCaptureManager
of Capture Flow is no longer required. UseCaptureFlow.Coordinator
directly instead.The following components, which are no longer available publicly, didn’t provide any value to integrators, and shouldn’t have been used:
User
Transaction Linking is now only available as part of Capture Flow use case (see Bank Transaction Linking ), and not on its own.
Transaction Matching is no longer available.
Web Client is no longer available.