This guide covers everything you need to integrate account linking into your iOS app: how it works, authentication, order retrieval, background processing, account management, and references.
How It Works
- Connect — The user links their retailer account through your app. The SDK handles authentication, including two-factor authentication and CAPTCHA challenges.
- Verify — The SDK verifies the credentials against the retailer.
- Retrieve — The SDK fetches purchase history from the linked account and returns structured order data.
- Enrich (optional) — If Product Intelligence is enabled, line items are matched against the product catalog for UPC, brand, and category.
Credentials are encrypted and stored locally on the device’s keychain. They never leave the device and are only used when the retailer session expires and re-authentication is required.
Installation
Add the BlinkEReceipt extension SDK to your project:
CocoaPods:
pod 'BlinkEReceipt'
Swift Package Manager:
https://github.com/BlinkReceipt/blinkereceipt-ios
Prerequisites: Xcode 12+, iOS 11.0+ deployment target.
License Keys
You need two keys: a license key and a Product Intelligence key. Both are available from your account team or by emailing blinkreceipt@microblink.com.
Initialize the SDK
In your AppDelegate, set both keys and initialize the account linking manager:
import UIKit
import BlinkReceipt
import BlinkEReceipt
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
BRScanManager.shared().licenseKey = "YOUR-LICENSE-KEY"
BRScanManager.shared().prodIntelKey = "YOUR-PROD-INTEL-KEY"
BRAccountLinkingManager.shared()
return true
}
}
Authentication Options
Account linking offers two authentication experiences.
Option A: Host App Authentication
Your app collects credentials. The SDK handles the rest in a hidden webview, only surfacing a visible webview when the retailer requires additional input (2FA, CAPTCHA, etc.).
let username = "user@domain.com"
let password = "secure-password"
let connection = BRAccountLinkingConnection(retailer: .walmart, username: username, password: password)
connection.configuration.dayCutoff = 30
Option B: Retailer Webview Authentication
No credentials needed. The SDK presents the retailer’s own login page in a webview. The user authenticates directly with the retailer. The webview closes automatically after successful authentication.
let connection = BRAccountLinkingConnection(retailer: .walmart)
connection.configuration.dayCutoff = 30
Switching Authentication Mode
You can switch an already-linked connection between modes:
if let connection = BRAccountLinkingManager.shared().getLinkedRetailerConnection(.walmart) {
connection.webviewAuthEnabled = true // Switch to retailer webview
connection.webviewAuthEnabled = false // Switch to host app
BRAccountLinkingManager.shared().update(connection)
}
Link a Retailer
let error = BRAccountLinkingManager.shared().linkRetailer(with: connection)
if error == .none {
// Success
}
Verify Credentials
Verification confirms the credentials are valid before linking. Recommended but not required.
let taskId = BRAccountLinkingManager.shared().verifyRetailer(with: connection,
withCompletion: { error, viewController, sessionId in
if error == .verificationNeeded {
// Present the view controller for 2FA / CAPTCHA
self.present(viewController!, animated: true)
} else if error == .verificationCompleted {
// Dismiss the view controller
self.dismiss(animated: false)
} else if error == .none {
// Verification succeeded — safe to link
BRAccountLinkingManager.shared().linkRetailer(with: connection)
} else {
// Handle errors: .invalidCredentials, .noCredentials,
// .unsupportedRetailer, .cancelled, .webViewClosed, .internal, .parsingFail
}
})
Retrieve Orders
Once linked and verified, retrieve purchase history:
let taskId = BRAccountLinkingManager.shared().grabNewOrders(for: .walmart) {
retailer, order, remaining, viewController, errorCode, sessionID in
if errorCode == .verificationNeeded {
// Present view controller for 2FA / CAPTCHA
self.present(viewController!, animated: true)
} else if errorCode == .verificationCompleted {
// Dismiss the view controller
self.dismiss(animated: false)
} else if errorCode == .none {
// Process the order
if remaining <= 0 {
// All orders retrieved
}
} else if errorCode == .webViewClosed {
// User dismissed the webview
} else {
// Handle other errors
}
}
The SDK tracks the last successful retrieval date per retailer. Subsequent calls only return new orders since then, subject to your dayCutoff.
Background Order Retrieval
To check for new orders while the app is in the background:
- Add background task support to your app with a task identifier. See Apple’s background tasks guide.
- Enable background fetch in the SDK using your task identifier:
BRAccountLinkingManager.shared().enableBackgroundFetch(withIdentifier: taskIdentifier)
- Implement the background fetch callback:
BRAccountLinkingManager.shared().backgroundFetchCompletion = { retailer, errorCode, sessionId, order in
// Same flow as grabNewOrders above
}
Full example in AppDelegate:
import UIKit
import BlinkReceipt
import BlinkEReceipt
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
BRScanManager.shared().licenseKey = "YOUR-LICENSE-KEY"
BRScanManager.shared().prodIntelKey = "YOUR-PROD-INTEL-KEY"
let taskIdentifier = "com.yourapp.account-linking-background"
BRAccountLinkingManager.shared().enableBackgroundFetch(withIdentifier: taskIdentifier)
BRAccountLinkingManager.shared().backgroundFetchCompletion = { retailer, errorCode, sessionId, order in
// Handle background orders
}
return true
}
}
Account Management
Unlink an Account
BRAccountLinkingManager.shared().unlinkAccount(for: .walmart) {
// Account unlinked
}
Reset Order History
Unlinking does not reset the order history cache. To clear it:
BRAccountLinkingManager.shared().resetHistory(for: .walmart)
Change Credentials
Unlink first, then create and link a new connection:
BRAccountLinkingManager.shared().unlinkAccount(for: .walmart) {
let newConnection = BRAccountLinkingConnection(retailer: .walmart, username: "new-user", password: "new-pass")
newConnection.configuration.dayCutoff = 30
BRAccountLinkingManager.shared().linkRetailer(with: newConnection)
}
It is recommended to call verifyRetailer before linking if you are unsure whether the new credentials are valid.
Multiple Accounts
Linking multiple accounts for the same retailer is not supported. Unlink the existing account before linking a different one for the same retailer.
Order Types
| Type | Description |
|---|---|
| In-Store | Purchases made in a physical store (if visible in the retailer account) |
| Delivery | Online purchases shipped to the customer |
| Pickup | Online purchases picked up in store |
| Digital | Movies, eBooks, songs, digital storage, etc. |
Not all order types are available for every retailer. Target, Walmart, and Kroger are examples of retailers that surface in-store purchases through their online accounts.
Order Status
Each order can include status information at three levels:
| Level | What it tracks |
|---|---|
| Order status | Overall order status (ordered, completed, cancelled, refunded, returned) |
| Shipment status | Status of a specific shipment within the order (delivery orders only) |
| Product status | Status of a specific product within the order |
Important: Account linking returns each order only once. If an order’s status changes after it has been retrieved (e.g., shipped → delivered), you need to reset the order history and re-retrieve to get the updated status.
Configuration Options
| Setting | What it does | Default |
|---|---|---|
dayCutoff | How many days of purchase history to retrieve | 15 days |
dateCutoff | Specific earliest date to retrieve from | None |
webviewAuthEnabled | Use retailer webview instead of host app credentials | false |
Error Handling
Common error codes and what they mean:
| Error | Description | How to handle |
|---|---|---|
verificationNeeded | Retailer requires 2FA, CAPTCHA, or other user input | Present the provided view controller |
verificationCompleted | User successfully completed additional authentication | Dismiss the view controller |
invalidCredentials | Username or password is incorrect | Prompt the user to re-enter credentials |
noCredentials | No credentials provided | Ensure credentials are set on the connection |
unsupportedRetailer | Retailer is not supported | Check the supported retailers list |
cancelled | Operation was cancelled | Dismiss any presented view controllers |
webViewClosed | User dismissed the webview | Dismiss any presented view controllers |
Full iOS Error Codes Reference
Testing Recommendations
- Test linking and verification for multiple retailers
- Test 2FA and CAPTCHA flows (most retailers trigger these intermittently)
- Test with accounts that have both in-store and online purchase history
- Verify that
dayCutoffcontrols the retrieval window correctly - Test unlinking and re-linking with the same and different credentials
- Test background order retrieval
- Remember to call reset history between test runs, or you will only see new orders since the last retrieval
- Run all account linking operations on the main thread (the SDK is not thread-safe)
Implementation Timeline
| Scope | Estimated Dev Time |
|---|---|
| Standard integration (single retailer) | ~1 week + QA |
| Full integration (all retailers + background) | ~2 weeks + QA |
Key Classes & References
| Class | What it does |
|---|---|
| BRAccountLinkingManager | Main manager for linking, verifying, and retrieving orders |
| BRAccountLinkingConnection | Represents a retailer connection (credentials + config) |
| BRAccountLinkingConfiguration | Configuration options (dayCutoff, dateCutoff) |
| BRAccountLinkingError | Error codes |
| BRAccountLinkingRetailer | Retailer enum values |