Skip to main content

FAQs

How It Works​

What is Actual Activation?

An SDK-based monetization solution that turns receipt scanning into a repeatable engagement and revenue loop. It extends the BlinkReceipt scanning SDK with offers, ads, rewards, and user engagement flows. Retailer-agnostic: any valid receipt can earn rewards.

How does the scan-to-reward flow work?
  1. User photographs receipt. SDK provides camera guidance.
  2. SDK checks the scan on device first: is the photo readable, are the store/date/total there, is the purchase date inside the rewards window. A problem here raises a review screen and the scan is never submitted — see Error Flows.
  3. SDK sends scan data to Actual's backend.
  4. Loading screen appears with an ad while processing.
  5. SDK calls your rewardCallback with a ScanFinished context. Your app returns the base scan reward amount. On iOS, if Actual has configured an amount for the receipt's store, it replaces yours — see Store-specific base scan reward.
  6. Backend validates: submission limits, receipt age, fraud detection, duplicate check (14-day window, cross-client), promotion matching (PVP).
  7. Validation fail → a screen explaining the problem, offering a review request; the shopper is never left at a dead end. Validation pass → receipt summary screen.
  8. Actual sends ReceiptProcessed webhook for every scan, regardless of outcome.
  9. Once a promo reward is validated, Actual sends a RewardUpdated webhook with the amount.
  10. Your server receives the webhook and grants the reward.
Who determines each reward type?
Reward TypeWho DecidesHow It Reaches You
Base Scan RewardYour app (rewardCallback) — or Actual, where it has configured an amount for the receipt's storeSDK callback at scan time and RewardUpdated webhook (the webhook always carries the amount applied)
Promo/Offer RewardActual backend (PVP)RewardUpdated webhook
Boost RewardActual backend (ad completion)RewardUpdated webhook
UGC RewardActual backend (task completion)RewardUpdated webhook
Missed EarningsActual backend (correction review)RewardUpdated webhook (pending → accepted/rejected)
warning

Do NOT use ReceiptProcessed to calculate rewards. Use RewardUpdated exclusively.

Can a single receipt trigger multiple webhooks?

Yes. Separate webhooks are sent for promo, boost, UGC, and missed earnings rewards. There is no "all rewards complete" signal — design for open-ended reward accrual per receipt.

How long does validation take?
  • Standard credits: instantaneous (seconds)
  • Manual edits (missed earnings): up to 6 hours
  • Blurry or suspicious receipts: up to 3 days
Is there a callback for when the user taps Done?

Not currently available.


SDK Integration​

What SDKs are needed?

Both are required:

  • BlinkReceipt SDK — camera and scanning
  • BlinkEngage SDK — monetization (offers, ads, rewards)

Supported platforms: iOS 13.0+, Android. React Native is supported via a wrapper.

On Android, Activation and Paper Receipt versions are released in pairs and must be upgraded together — for example, Paper Receipt 2.5.0 pairs with Activation 1.2.0. See the Android SDK Version Matrix.

What credentials do I need?

A licenceKey and a ProdIntelKey. Contact your Actual account team to have Engage features enabled on your key.

What are the essential setup steps?
  1. Enable Monetization — Activate reward and ad features within the scanning system.
  2. Provide User Identity — Supply a hashed user identifier (SHA-256 lowercase hex of email or phone number) for personalization and fraud prevention.
  3. Define Reward Currency — Specify your in-app currency name (e.g., "points", "coins") and conversion rate to dollars (e.g., 100 points = $1).
After a scan, our didFinishScanning callback returns no results. Is that expected?

Yes. When BlinkEngage is enabled, no results are returned on-device in didFinishScanning. Results are delivered via webhook instead.

What format should hashed email or phone be in?

SHA-256, lowercase hex.


Rewards & Currency​

How do users earn rewards?
  • Base Scan Rewards — Awarded for any successfully scanned receipt. You control the amounts dynamically via rewardCallback.
  • Promo/Offer Rewards — Automatically awarded when receipt items match active promotions in Actual's system.
  • Boost Rewards — Optional bonus earned by watching a short rewarded video ad after the scan.
  • UGC Rewards — Earned by completing barcode collection tasks.
  • Missed Earnings — Correction-based rewards for receipts that were initially missed or under-awarded.
Who controls reward amounts?

You control base scan rewards via rewardCallback — the SDK requests a reward amount from your app in real-time, letting you implement dynamic logic (e.g., higher rewards for premium users or during promotional periods). The exception is a store for which Actual has configured its own base scan reward: that amount replaces yours (see below).

Actual handles validation and calculation for promo, boost, and UGC rewards, and notifies your server via RewardUpdated webhook when amounts should be credited.

Can Actual override our base scan reward?

Yes. Actual can configure a base scan reward for a specific store, or a default for all of your stores. For receipts from that store, the configured amount supersedes the one your app supplies — including when it is lower than yours or zero.

  • The Receipt Summary shows the amount applied, and the base_scan RewardUpdated webhook carries it.
  • If Actual's answer doesn't reach the device within a few seconds, the Receipt Summary falls back to your amount, but the webhook still carries Actual's. Credit the shopper from the webhook.
  • Available on iOS from 1.12.0, where the webhook is the only place your app learns the amount applied. Android support is coming in a future release.

See Store-specific base scan reward.

What is the Missed Earnings feature?

Missed Earnings lets users correct receipt scanning errors and claim rewards they may have missed.

  • Users access the Missed Earnings page from their Receipt Summary.
  • They can correct merchant name, date, or product details.
  • For unrecognized products, users can scan the item's barcode to identify it correctly.
  • After submitting corrections, items show a "Pending Review" status.
  • Once reviewed, Actual sends a RewardUpdated webhook with updateType: missed_earnings and status accepted or rejected.

Review takes up to 6 hours.

What does "Pending Review" mean?

When a user submits a correction, the item enters Actual's review queue. The product card shows "Pending Review" to confirm receipt. The system revalidates with the corrected information and updates rewards via webhook.

Can we use our own currency name?

Yes. Configure the display name via your reward currency configuration (currencyName). Note that some hardcoded UI strings still say "points" and require a future SDK update.

What are the receipt submission caps per user?
  • 10 receipt submissions on any given date
  • 3 receipts at the same merchant per transaction date
  • 7 receipts with the same purchase date (total)
  • 20 receipts in a rolling 7-day window

When a cap is hit, an error is displayed and the user cannot submit until outside the relevant window. The offer wall remains usable during this time.

Is there a testing bypass for scan limits?

Yes, via Debug Mode (development builds only — do NOT enable in production):

  • TestOptions.Test — enables test mode: returns test promotions from the backend and registers the device as a Google Ad Manager test device, so ad units serve test creatives
  • Debug placements — force specific offer wall layouts (carousel, list, grid) to test UI variations

Note: duplicate detection cannot currently be bypassed. Each test scan requires a unique receipt.


Webhooks​

How do we set up webhooks?

Provide the following to your Actual account team:

  • HTTPS endpoint URL
  • Event types to subscribe to (ReceiptProcessed, RewardUpdated, or both)
  • Custom headers (optional)
  • App bundle ID
What's the difference between ReceiptProcessed and RewardUpdated?
WebhookWhen It FiresUse For
ReceiptProcessedEvery scan, regardless of outcome (including failures)Logging, support visibility, audit trails
RewardUpdatedWhen a reward is confirmedGranting rewards to your users
warning

Use RewardUpdated exclusively to grant rewards. Never use ReceiptProcessed for reward calculation.

When are RewardUpdated webhook events fired?
ScenarioupdateTyperewardTypestatusFrequency
Promo rewardrewardpromocompleteOnce per receipt (aggregated)
Rewarded ad (boost)rewardboostcompleteOnce per ad watched
UGC taskrewardugccompleteOnce per task completed
Base Scanrewardbase_scancompleteOnce per receipt
Missed earnings (submitted)missed_earningsn/apendingOnce on submission
Missed earnings (resolved)missed_earningsn/aaccepted/rejectedOnce on resolution
Is one webhook event sent per product or per receipt?

For redeemed offers and coupons: all qualified items are sent in one RewardUpdated webhook with details per promotion. For engagement events (boost, UGC): each is sent individually.

Can we add a unique constraint on blink_receipt_id?

Yes. A unique blink_receipt_id (BRID) is always returned for every scan.

Are reward_amount and reward_id always present for a complete promo?

Yes. Both fields will always be present for a complete promo reward.

Can we include our own user ID in webhook payloads?

Yes. Set clientUserId during SDK initialization. It is included on RewardUpdated payloads. You can also correlate events via blink_receipt_id or hashed email/phone.

Note: clientUserId is not currently included on ReceiptProcessed payloads. Until resolved, correlate ReceiptProcessed events using blink_receipt_id.

What SDK telemetry events are available?

Currently exposed via callbacks and/or webhooks:

  • Offer clipped
  • Scan started
  • Scan finished
  • Any reward completed
  • Missed earnings completed

Additional events are being added. Contact your Actual account team to flag requests.

What are the possible fraud_reason values?
ValueMeaning
receipt_counterfeit_textFake text patterns detected
receipt_manipulationReceipt data appears altered
duplicate_submissionSame receipt submitted before
user_burst_activityUnusual scan volume from user
user_geo_inconsistencyUser locations don't match
device_multiple_usersMultiple users on same device
no_matchNo matching receipt pattern found

A fraud flag on its own does not stop a receipt. Only five of these reasons make a receipt actionable — receipt_counterfeit_text, receipt_merchant_mismatch, user_geo_anomaly, user_identity_anomaly, and ip_anomaly — and even then the receipt is not turned away: the summary renders with rewards suppressed and the shopper can dispute it. Any other reason is informational, and the receipt processes and pays out normally.

What is the webhook retry behavior?
AttemptWait TimeTimeout
1 (initial)—30 seconds
2 (retry 1)5 seconds30 seconds
3 (retry 2)15 seconds30 seconds
4 (retry 3)45 seconds30 seconds

After 3 failed retries, the webhook is moved to a dead letter queue for manual investigation.


Offers & Offer Wall​

How does the offer wall work?

The SDK provides a ready-to-use Offer Wall displaying relevant coupons and deals. Actual handles sourcing offers, targeting based on location and shopping patterns, and keeping content fresh. Users can browse by category or filter by favorite merchants.

Can we show offers in our own UI instead of the offer wall?

Yes, with the Client-Side Offer Feed. Your app asks the SDK for the same curated offers the offer wall shows, as plain data (groups, each with its offers), and renders them with its own UI. When the shopper taps one of your cards, your app hands the offer or group back to the SDK, which opens its own offer details or the group's full list. Clipping and scanning work as they do in the offer wall.

PlatformAvailable fromGuide
iOS1.14.0iOS Client-Side Offer Feed
AndroidComing in a future release—

Two things to plan for:

  • Report interactions. Your app renders the offers, so only it knows when one is seen or tapped. Report each with reportOfferFeedEvent(_:).
  • The feed can be turned off for your app. This arrives as an error (code 2), not as an empty feed. Hide your surface and don't retry in a loop — the offer wall itself keeps working.

See Starting from your app's own UI for the full flow.

Can we control the offer wall header?

Yes. Use the offerWallHeaderTitle function to customize the header section. See "Presenting the Offer Wall" in the SDK docs.

How does My Stores get populated?

New users see merchants ranked by overall popularity. Once they interact, personalization kicks in based on recent clicks, store views, and receipt upload recency and frequency. Geo-relevant filtering uses zip code passthrough, IP lookup, and zip extraction from receipts.

How often are offers updated?

Daily, from both third-party and direct brand sources.

Can we change the scan button label?

Yes. Hide the default button via an SDK method and add your own button as a subview.

What percentage of offers require pre-clipping?

Approximately 60% require clipping before purchase; ~40% are automatic. Clippable offers are expected to grow over the next 6 months.

Can users unclip an offer after clipping?

Not currently. This is on the roadmap.

Can we place custom offers on the wall?

Yes. Provide UPCs, merchants, eligibility criteria, and reward details. This requires coordination with Actual — there is no self-service option today.

Can we change section headers like "New Offers" or "Last Chance"?

Yes. These are server-side controlled by Actual and can be updated quickly on request.


Ads & GAM​

Do we need a Google Ad Manager account?

Yes, for production ads. Not a blocker for SDK testing. Note that identity verification for a new GAM account can take weeks — plan accordingly.

How does the GAM invite process work?
  1. Send Actual the email address of your GAM account admin.
  2. Actual sends an invite to that address.
  3. Open the email while logged into your existing GAM account and accept the invite.

This does not affect your existing account — it grants Actual the ability to create new ad placements within Actual's GAM network for your app. Actual then provides additional lines to add to your app-ads.txt file.

Do we need to serve all ad types?

No. The scan loading ad plays automatically during receipt processing. The boost/rewarded video is opt-in by the user.


Receipt Scanning & Fraud​

What are the receipt validation rules?

Checks run in two tiers. Device-tier checks run before the scan is submitted, so a receipt one of them stops is never registered server-side — it can never come back as a duplicate either.

CheckRuleWhereResult
Non-receiptPhoto can't be read as a receiptDeviceInvalid-receipt screen; retake or send for review
Missing fieldsStore, date, or total not foundDeviceForm asking for what's missing; scan continues to processing on submit
Receipt agePurchase date older than the rewards window (14 days)Device and serverReceipt-too-old screen; review request with the correct date
Submission limitsUser hit a daily, per-merchant, or rolling 7-day capServerFrequency-cap screen naming each limit; dispute available
DuplicateSame receipt in any Actual app within 14 daysServerSummary with a duplicate banner, rewards suppressed; dispute available
Counterfeit text / merchant mismatch / geo, identity, or IP anomalyAn actionable fraud flagServerSummary with an invalid banner, rewards suppressed; dispute available
Burst activity, manipulation, other flagsInformational fraud flagsServerNone — the receipt processes and pays out normally

No result is a dead end: every row above either continues to the Receipt Summary or offers a review request. See Error Flows for check precedence and reward timing.

What happens when a receipt can't be processed?

It is not turned away. The shopper gets a screen explaining the problem, with a retake where a new photo could help and a review request in every case. Dismissing the screen returns them to the offer wall, ready to scan again.

Two consequences for your integration:

  • A scan that ends at a review request earns nothing yet. The base scan reward is deferred and granted only if a reviewer accepts, arriving later as a RewardUpdate webhook. The exception is the missing-fields flow, which continues to processing, so its reward lands immediately.
  • A correction the shopper types is evidence, not data. It travels to the reviewer only; the scan submitted for processing is always exactly what the scanner read. A field that was missing at scan time is still missing on the Receipt Summary.

See Error Flows for the full behavior and Error Flows Summary for what the shopper sees in each case.

How do we test scanning without test receipts?

Use any real receipt with a purchase date within the last 14 days. Actual does not currently provide test receipts.

Duplicate detection is enforced across all Actual apps, so each successful scan requires a different receipt — you cannot rescan the same one.

Test mode accepts everything. With test mode enabled, both tiers resolve to accepted: the device age check is skipped (so fixture receipts of any age scan) and the backend returns a rewardable verdict before reading any flag. To exercise a server verdict — submission limit, receipt too old, duplicate, or fraud — turn test mode off.

The two device checks that describe the scan itself rather than policy still apply under test mode: an unreadable photo still raises the invalid-receipt screen, and a missing store, date, or total still raises the form.


UI Customization​

Can we customize colors, fonts, and icons?

Yes. Pass a custom theme to match your brand. The SDK supports customizing colors, fonts, and icons throughout the offer wall and receipt summary screens. Contact your Actual account team for the advanced styling guide.

Can we customize the icon/points display order?

Not currently. The display order on the offer wall and receipt summary is fixed.

Can we send push notifications for new deals?

Push notifications are not built into the SDK. Publishers handle this using webhook data.


UGC (Barcode Collection)​

How are UGC submissions validated?

Two matching submissions of the same barcode from unique devices are required for validation.

How many UGC tasks can be completed per receipt?

A maximum of 3 UGC tasks per receipt.