This guide covers everything you need to integrate paper receipt scanning into your iOS app: how it works, setup, camera options, correction flows, and references.
How It Works
- Capture — The user photographs a receipt using the device camera.
- Extract — OCR processes the image on-device and returns structured data: merchant, date, total, line items, payment method, and more.
- Enrich (optional) — If Product Intelligence is enabled, extracted line items are matched against the product catalog for UPC, brand, category, and normalized product names.
All processing happens on-device. No receipt images are sent to the cloud.
Installation
CocoaPods:
pod 'BlinkReceipt'
Swift Package Manager:
https://github.com/BlinkReceipt/blinkreceipt-ios
Prerequisites: Xcode 12+, iOS 11.0+ deployment target, camera permissions.
License Configuration
Set your license key in the AppDelegate at app launch:
Objective-C:
#import <BlinkReceipt/BlinkReceipt.h>
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[BRScanManager sharedManager].licenseKey = @"YOUR-LICENSE-KEY";
return YES;
}
Swift:
import BlinkReceipt
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
BRScanManager.shared().licenseKey = "YOUR-LICENSE-KEY"
return true
}
Add camera permissions to your Info.plist:
<key>NSCameraUsageDescription</key>
<string>This app uses the camera to scan receipts</string>
Camera Options
Option A: Out-of-the-Box Camera (Standard)
The fastest path. The SDK provides a complete camera interface with alignment guidance, blur detection, and real-time feedback.
- (IBAction)btnTouched:(id)sender {
BRScanOptions *scanOptions = [BRScanOptions new];
[[BRScanManager sharedManager] startStaticCameraFromController:self
cameraType:BRCameraUXStandard
scanOptions:scanOptions
withDelegate:self];
}
Implement the delegate callback:
@interface MyViewController () <BRScanResultsDelegate>
- (void)didFinishScanning:(UIViewController *)cameraViewController
withScanResults:(BRScanResults *)scanResults {
[cameraViewController dismissViewControllerAnimated:YES completion:nil];
// Use scan results
}
Configurable scan options:
| Option | What it does |
|---|---|
enableAutoCapture | Automatically captures when receipt is properly positioned |
enableTorch | Enables flash control |
enablePhotoGallery | Allows scanning from photo library |
detectDuplicates | Checks for duplicate receipts and fraud |
returnVoidedProducts | Returns voided products with isVoided flag |
countryCode | ISO 2-character country code for the receipts being scanned |
Option B: Enhanced Camera UX
Same setup as Option A, but specify BRCameraUXEnhanced for improved graphics, messaging, and animations:
[[BRScanManager sharedManager] startStaticCameraFromController:self
cameraType:BRCameraUXEnhanced
scanOptions:scanOptions
withDelegate:self];
Data Chips: Enable on-screen indicators that show the user when key fields are detected:
scanOptions.enableDateChip = YES;
scanOptions.enableTotalChip = YES;
scanOptions.enableMerchantChip = YES;
Note: Some merchant detection methods only run at the end of the scan session. The merchant chip may not appear during scanning but the merchant will still be returned in the results.
Option C: Custom Camera Controller
Build your own UI on top of the SDK’s scanning engine.
Step 1: Subclass BRCameraViewController:
#import <BlinkReceipt/BlinkReceipt.h>
@interface MyCameraController : BRCameraViewController
Step 2: Set background to transparent:
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor clearColor];
}
Step 3: Set the scanning region (values are percentages, 0.0 to 1.0):
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
self.scanningRegion = CGRectMake(0.1, 0.05, 0.8, 0.65);
}
Step 4: Wire your UI to the base class methods:
| Method | When to call |
|---|---|
userSnappedPhotoOnReady: | User taps the capture button |
userConfirmedFrame: | User accepts the captured image |
userFinishedScan | User indicates the scan is complete |
userCancelledScan | User cancels the session |
Step 5: Launch your custom controller:
MyCameraController *cameraController = [MyCameraController new];
[[BRScanManager sharedManager] startCustomCamera:cameraController
fromController:self
scanOptions:scanOptions
withDelegate:self];
→ Custom Camera Controller Guide → BRCameraViewController Reference
Long Receipts
For receipts that don’t fit in a single frame, the SDK supports multi-frame capture:
- The user captures the first section of the receipt normally.
- After the first capture, the bottom edge of the previous frame appears at the top of the screen as an alignment guide.
- The user positions the next section with slight overlap and captures again.
- Repeat until the entire receipt is captured.
- The SDK stitches all frames together and returns a single set of results.
The out-of-the-box and enhanced cameras handle this flow automatically. If using a custom camera controller, you are responsible for displaying alignment cues and managing the multi-frame flow through the base class methods.
Receipt Correction
An optional flow that lets users review and edit extracted data after scanning. Especially useful for promotion validation workflows.
Stock Correction UI
[[BRScanManager sharedManager] startReceiptCorrection:@"BLINK-RECEIPT-ID"
fromViewController:self
withCustomFont:nil
withCompletion:^(BRScanResults *results, NSError *error) {
[self dismissViewControllerAnimated:YES completion:nil];
// Use corrected results
}];
You can pass a custom UIFont to style the correction UI. Font size is ignored; the font family is applied.
To enable correction of historical receipts:
[BRScanManager sharedManager].daysToStoreReceiptData = 30; // Default is 0 (no local storage)
Custom Correction UI
Step 1: Load receipt data:
[[BRScanManager sharedManager] getResultsForReceiptCorrection:@"BLINK-RECEIPT-ID"
withCompletion:^(BRScanResults *results, NSArray<UIImage *> *images) {
// Display your own UI
}];
Step 2: Modify products:
[product userCorrectedBrand:@"Kraft"
upc:@"12345678901"
productName:@"Macaroni & Cheese"
imageUrl:@"https://example.com/image.png"
totalPrice:2.99
quantity:1.0];
Step 3: Submit for validation:
[[BRScanManager sharedManager] submitUpdatedResultsForValidation:scanResults
withCountryCode:nil
withCompletion:^(BRScanResults *results, NSError *error) {
// Results include updated qualifiedPromotions
}];
Fields in corrected results:
userAdded— Product was added by the user during correctionuserModified— One or more properties were changed during correction
Localization
[BRScanManager sharedManager].preferredLanguage = @"es"; // Spanish
Available: en, es, fr, de, it, pt, nl, sv, da, no, fi.
Receipt Quality & Feedback
| Field | What it tells you |
|---|---|
is_receipt | Whether the image appears to be a valid receipt |
is_blurry | Whether the image is too blurry to extract reliably |
is_screen | Whether the image appears to be a photo of a screen |
is_fraudulent | Whether the receipt appears manipulated or counterfeit (US only, select banners) |
is_duplicate | Whether this receipt has been submitted before (2-week window, within your instance) |
ocr_confidence | Average OCR confidence score across all characters |
Debug Mode
[BRScanManager sharedManager].debugMode = YES;
Testing Recommendations
- Test with various receipt types: thermal, inkjet, laser-printed
- Test in different lighting conditions: bright, dim, mixed
- Test with challenging receipts: crumpled, faded, long, torn
- Test across device types: older phones, budget devices, different screen sizes
Implementation Timeline
| Scope | Estimated Dev Time |
|---|---|
| Out-of-the-Box Camera | ~1 week + QA |
| Custom Camera | ~2 weeks + QA |
Key Classes & References
| Class | What it does |
|---|---|
| BRScanManager | Main SDK manager — license, scanning, correction |
| BRScanOptions | Configuration options for scanning sessions |
| BRScanResults | Scan results including trip and basket data |
| BRProduct | Individual product from a receipt |
| BRCameraViewController | Base class for custom camera controllers |
| BRScanResultsDelegate | Protocol for receiving scan results |
| BRErrorCodes | Error codes |