iOS
The iOS SDK wraps the Lean Link SDK in a native WKWebView-backed view, with both SwiftUI and UIKit entry points.
PrerequisitesBefore calling any SDK method you need to have completed the backend setup in the Getting Started section:
- Create your Lean application in the developer dashboard to obtain an
app_token.- Authentication — OAuth flow for minting customer-scoped
access_tokens.- Creating a customer —
POST /customers/v1to obtain acustomer_id.- Sandbox testing — test users and mock bank.
This page covers only the client-side SDK integration.
Installation
Swift Package Manager (recommended)
In Xcode go to File → Add Package Dependencies and paste:
https://github.com/leantechnologies/link-sdk-ios-distribution
Manual xcframework
Download the .xcframework zip from the distribution Package.swift and add it to your target.
Latest version is listed on releases.
Import
import LeanSDKDemo app
See link-ios-demo-application.
Setup
Configure the manager once during app launch (or before any SDK call):
Lean.manager.setup(
appToken: "<YOUR_APP_TOKEN>",
sandbox: true,
version: "latest"
)Usage — SwiftUI
Place Lean.manager.view inside a .fullScreenCover and toggle it via state.
import SwiftUI
import LeanSDK
@main
struct LeanTestApp: App {
init() {
Lean.manager.setup(
appToken: "<YOUR_APP_TOKEN>",
sandbox: true,
version: "latest"
)
}
var body: some Scene { WindowGroup { ContentView() } }
}
struct ContentView: View {
@State private var isPresented = false
var body: some View {
Button("Connect", action: handleConnect)
.fullScreenCover(isPresented: $isPresented) {
Lean.manager.view.ignoresSafeArea()
}
}
func handleConnect() {
Lean.manager.connect(
customerId: "CUSTOMER_ID",
permissions: [.Identity, .Accounts, .Transactions, .Balance],
paymentDestinationId: nil,
bankId: nil,
customization: nil,
success: { isPresented = false },
error: { status in
print(status.status, status.message)
isPresented = false
}
)
isPresented = true
}
}Usage — UIKit
Call setup(...) in viewDidLoad, then pass a presentingViewController to each method. The SDK presents itself modally.
import UIKit
import LeanSDK
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
Lean.manager.setup(appToken: "<YOUR_APP_TOKEN>", sandbox: true, version: "latest")
}
@IBAction func handleConnect(_ sender: Any) {
Lean.manager.connect(
presentingViewController: self,
customerId: "CUSTOMER_ID",
permissions: [.Identity, .Accounts, .Transactions, .Balance],
bankId: nil,
customization: nil,
success: { status in /* ... */ },
error: { status in print(status) }
)
}
}Available methods
Each method has a SwiftUI and a UIKit variant — the SwiftUI form omits presentingViewController. The UIKit variants accept presentingViewController as the first parameter.
.connect()
Link a bank account for data access (and optionally payments).
Required: customerId, permissions.
Lean.manager.connect(
customerId: String,
permissions: [LeanPermission],
paymentDestinationId: String?,
bankId: String?,
customization: LeanCustomization?,
accountType: String? = nil,
endUserId: String? = nil,
accessTo: String? = nil,
accessFrom: String? = nil,
failRedirectUrl: String? = nil,
successRedirectUrl: String? = nil,
accessToken: String? = nil,
showConsentExplanation: Bool? = nil,
destinationAlias: String? = nil,
destinationAvatar: String? = nil,
customerMetadata: String? = nil,
success: () -> (),
error: (LeanStatus) -> ()
).pay()
Initiate a bank-to-bank payment.
Required: exactly one of paymentIntentId or bulkPaymentIntentId.
Lean.manager.pay(
paymentIntentId: String? = nil,
bulkPaymentIntentId: String? = nil,
accountId: String?,
bankId: String? = nil,
customization: LeanCustomization?,
endUserId: String? = nil,
failRedirectUrl: String? = nil,
successRedirectUrl: String? = nil,
accessToken: String? = nil,
destinationAlias: String? = nil,
destinationAvatar: String? = nil,
riskDetails: LeanRiskDetails? = nil,
success: () -> (),
error: (LeanStatus) -> ()
).reconnect()
Restore a broken bank connection.
Required: reconnectId.
Lean.manager.reconnect(
reconnectId: String,
customization: LeanCustomization?,
accessToken: String? = nil,
destinationAlias: String? = nil,
destinationAvatar: String? = nil,
success: () -> (),
error: (LeanStatus) -> ()
).updatePaymentSource()
Add a beneficiary to an existing payment source.
Required: customerId, paymentSourceId (or entityId), paymentDestinationId.
The iOS signature markspaymentSourceIdas non-optional. To upgrade a data-only customer withentityIdon iOS today, setpaymentSourceIdto an empty string and provideentityId. This mismatch vs the Web SDK is tracked for a future release.
Lean.manager.updatePaymentSource(
customerId: String,
paymentSourceId: String,
paymentDestinationId: String,
customization: LeanCustomization?,
endUserId: String? = nil,
accessToken: String? = nil,
entityId: String? = nil,
destinationAlias: String? = nil,
destinationAvatar: String? = nil,
success: () -> (),
error: (LeanStatus) -> ()
).checkout()
Open Finance guest payment — the customer authenticates at the bank and is redirected back to your successRedirectUrl / failRedirectUrl with status query parameters you feed into captureRedirect.
Required by the underlying SDK validator: paymentIntentId, successRedirectUrl, failRedirectUrl. The Swift signature accepts nil for the redirect URLs but they must be supplied for the flow to succeed at runtime.
Lean.manager.checkout(
paymentIntentId: String,
customization: LeanCustomization?,
customerName: String? = nil,
bankId: String? = nil,
accessToken: String? = nil,
successRedirectUrl: String? = nil,
failRedirectUrl: String? = nil,
riskDetails: LeanRiskDetails? = nil,
success: () -> (),
error: (LeanStatus) -> ()
).authorizeConsent()
Grant a long-lived Open Finance consent. Redirects to the bank and returns to your successRedirectUrl / failRedirectUrl.
Required: customerId, consentId, successRedirectUrl, failRedirectUrl.
Lean.manager.authorizeConsent(
customerId: String,
consentId: String,
failRedirectUrl: String,
successRedirectUrl: String,
customization: LeanCustomization? = nil,
accessToken: String? = nil,
destinationAlias: String? = nil,
destinationAvatar: String? = nil,
riskDetails: LeanRiskDetails? = nil,
success: () -> (),
error: (LeanStatus) -> ()
).manageConsents()
Show a customer-facing consent management screen.
Required: customerId.
Lean.manager.manageConsents(
customerId: String,
customization: LeanCustomization?,
accessToken: String? = nil,
success: () -> (),
error: (LeanStatus) -> ()
).captureRedirect()
Show the outcome screen after an Open Finance redirect. Extract the status query parameters Lean appends to your redirect URL (consentAttemptId, granularStatusCode, statusAdditionalInfo) and pass them in.
Required: customerId.
Lean.manager.captureRedirect(
customerId: String,
customization: LeanCustomization?,
accessToken: String? = nil,
consentAttemptId: String? = nil,
granularStatusCode: String? = nil,
statusAdditionalInfo: String? = nil,
success: () -> (),
error: (LeanStatus) -> ()
).verifyAddress()
Proof-of-address check.
Required: customerId, customerName, permissions (typically [.Identity]).
Lean.manager.verifyAddress(
customerId: String,
customerName: String,
permissions: [LeanPermission],
customization: LeanCustomization?,
accessToken: String? = nil,
destinationAlias: String? = nil,
destinationAvatar: String? = nil,
success: () -> (),
error: (LeanStatus) -> ()
)Deprecated methods
.createPaymentSource()
Deprecated — use.connect()withpermissions: [.Payments]instead.
Alias for connect that forces the payments permission. Retained for backwards compatibility.
Lean.manager.createPaymentSource(
customerId: String,
paymentDestinationId: String?,
bankId: String? = nil,
customization: LeanCustomization?,
accessToken: String? = nil,
destinationAlias: String? = nil,
destinationAvatar: String? = nil,
success: () -> (),
error: (LeanStatus) -> ()
)Callback
Success and error closures receive a LeanStatus object. Status codes documented at LinkSDK statuses.
Lean.manager.connect(
customerId: "CUSTOMER_ID",
permissions: [.Identity, .Accounts],
paymentDestinationId: nil,
bankId: nil,
customization: nil,
success: {
// SUCCESS path
},
error: { status in
print(status.status, status.message, status.method)
}
)Customisation
LeanCustomization wraps the same field set as the Web SDK's customization object in camelCase. See Customisation for every property.
let custom = LeanCustomization(
dialogMode: "contained",
themeColor: "#0080ff",
buttonTextColor: "#ffffff",
buttonBorderRadius: "8",
linkColor: "#0080ff",
overlayColor: "rgba(0, 0, 0, 0.8)"
)
Lean.manager.connect(
customerId: "CUSTOMER_ID",
permissions: [.Identity, .Accounts],
paymentDestinationId: nil,
bankId: nil,
customization: custom,
success: { /* ... */ },
error: { _ in /* ... */ }
)Language
Pass language: "ar" to Lean.manager.setup(...) for Arabic (right-to-left). Omit for English.
Bank-list and account-selection shortcuts
Pass bankId to skip the bank-selection screen (Lean bank identifier — see Create your own bank list). Pass accountId on pay to skip the payment-source-selection screen.
Related
Updated 13 days ago
