Skip to main content

RewardUpdate Payload Samples

These are the JSON payloads a client will receive for all supported variations of the RewardUpdate webhook.


1. Reward — Promo

PVP promo reward issued after scan results are processed.

{
"id": "fc5db27e-352e-43e9-a9c3-d72dbfc88d23",
"timestamp": 1776744008387,
"payload_data": {
"blink_receipt_id": "954d737a-c813-4249-8fab-428338abecff",
"update_type": "reward",
"status": "[pending|complete]",
"client_user_id": "test_user_123",
"reward_id": "dfcd3092-3320-4605-9e29-30dd8bce8d54",
"reward_type": "promo",
"reward_amount": 4,
"promo_ids_updated": [123],
"qualified_promos": [
{
"promo_id": 123,
"title": "Save $4.00 on any ONE (1) One A Day® 110ct+",
"qualified_count": 1,
"promo_amount": 4,
"status": "[pending|accepted|rejected]",
"reason": "REASON_CODE",
"products": [
{
"description": "ONE A DAY",
"price": 5,
"quantity": 1
}
]
}
]
},
"payload_type": "RewardUpdate",
"version": 1
}
  • The top-level promo reward payload_data.status follows this state machine: RewardUpdate Top-Level Promo diagram

  • Each individual promo follows this state machine: RewardUpdate Individual-State Promo diagram

Notes

  • All initial promo updates will have top-level status: pending and this status will not change in subsequent updates until all individual promo statuses have been resolved
  • reward_amount represents the total potential awardable amount at a given time - it is the sum of all promo amounts that are in accepted or pending states
  • reward_id will remain constant throughout all related updates
  • promo_ids_updated contains the promo_id values for promos whose status is first reported or changed in this webhook message
  • qualified_count and promo_amount represent the number of instances of that promo and the total amount for that promo, respectively, that currently, or may in the future, qualify. In the case of a partial qualification, these fields will reflect only the portion that actually qualified
  • reason will exist only when status is pending or rejected
  • products will exist only when status is pending or accepted

2. Reward — Boost

Google SSV ad reward issued.

{
"id": "1e74a91c-0b63-4158-9d4c-29fe6e1d7fff",
"timestamp": 1776483872691,
"payload_data": {
"blink_receipt_id": "d4f5a8b2-9c3e-4a1f-b7d6-2e8f0c1a3b5d",
"client_user_id": "user-abc-123",
"reward_id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"update_type": "reward",
"reward_type": "boost",
"reward_amount": 0.25,
"status": "[pending|complete]"
},
"payload_type": "RewardUpdate",
"version": 1
}

Notes

  • For hard currency apps only, boosts cannot be paid out immediately after the user completes the ad watch. In this case only, a pending status will be sent out and then upon the next valid receipt submission, the reward will be paid and a subsequent webhook with status complete will be sent.

3. Reward — Barcode Collection

UGC/barcode collection task reward issued.

{
"id": "1e74a91c-0b63-4158-9d4c-29fe6e1d7fff",
"timestamp": 1776483872691,
"payload_data": {
"blink_receipt_id": "d4f5a8b2-9c3e-4a1f-b7d6-2e8f0c1a3b5d",
"client_user_id": "user-abc-123",
"reward_id": "c3d4e5f6-a7b8-9012-cdef-123456789012",
"update_type": "reward",
"reward_type": "barcode_collection",
"reward_amount": 0.50,
"status": "complete"
},
"payload_type": "RewardUpdate",
"version": 1
}

4. Reward — Base Scan

A paper receipt scan has been accepted and the base scan reward is confirmed.

{
"id": "1e74a91c-0b63-4158-9d4c-29fe6e1d7fff",
"timestamp": 1776483872691,
"payload_data": {
"blink_receipt_id": "bfcf4575-b287-4135-8236-d0eac733f3d0",
"client_user_id": "user-abc-123",
"update_type": "reward",
"status": "complete",
"reward_id": "0bd9a3ff-c79a-4d2a-9aee-0e82d895df81",
"reward_type": "base_scan",
"reward_amount": 0.5
},
"payload_type": "RewardUpdate",
"version": 1
}

Notes

  • The base scan RewardUpdate is sent only after the corresponding ReceiptSummary resolves as accepted. If the receipt is rejected, no base scan webhook is sent. If the receipt enters pending (error review), the base scan is held until the review concludes.

5. Missed Earnings

Missed earnings request submitted and queued for processing.

{
"id": "251e0d6e-d117-4684-b047-98b6d4896b9f",
"timestamp": 1776458765539,
"payload_data": {
"blink_receipt_id": "d4f5a8b2-9c3e-4a1f-b7d6-2e8f0c1a3b5d",
"client_user_id": "user-abc-123",
"update_type": "missed_earnings",
"status": "[pending|complete]",
"reward_id": "0bd9a3ff-c79a-4d2a-9aee-0e82d895df81",
"reward_amount": 0,
"promo_ids_updated": [123],
"qualified_promos": [
{
"promo_id": 123,
"title": "Save $4.00 on any ONE (1) One A Day® 110ct+",
"qualified_count": 1,
"promo_amount": 4,
"status": "[pending|accepted|rejected]",
"reason": "REASON_CODE",
"products": [
{
"description": "ONE A DAY",
"price": 5,
"quantity": 1
}
]
}
]
},
"payload_type": "RewardUpdate",
"version": 1
}

Notes

  • Similar structure and semantics to promo updates but with some notable differences:
    • All amounts, promos, and products relate only to incremental earnings that have been preliminarily identified on this receipt in response to the user's corrections and/or supplementary data as part of the Missed Earnings process
    • The reward_amount starts at 0 rather than the total potential rewardable amount as in promos, and is updated only when one or more promos are resolved as accepted - this reflects the lower likelihood of missed earnings requests being validated
    • If a user's missed earnings request does not result in any preliminary incremental qualifications, the only webhook that will be sent out will have top level status: complete and no qualified_promos array.

6. Reward — Out-of-Band Correction

A reward manually issued by Actual, tied to an existing receipt but outside of the normal review or promo workflow.

{
"id": "7f3a2b1c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
"timestamp": 1776483999999,
"payload_data": {
"blink_receipt_id": "bfcf4575-b287-4135-8236-d0eac733f3d0",
"client_user_id": "user-abc-123",
"update_type": "reward",
"status": "complete",
"reward_id": "9ea1b2c3-d4e5-6f7a-8b9c-0d1e2f3a4b5c",
"reward_type": "correction",
"reward_amount": 1.00
},
"payload_type": "RewardUpdate",
"version": 1
}

Notes

  • correction rewards are always sent with status = complete.
  • They carry their own unique reward_id but share the blink_receipt_id of the receipt they are associated with.
  • These are issued by Actual manually — no user action triggers them.

Statuses / Reason Codes

For promo and missed earnings updates, these are the possible combinations of status and reason for entries in the qualified_promos array.

StatusReason codeDescription
accepted[reason key will not exist in case of full acceptance]Fully validated
acceptedACCEPTED_PARTIALOffer was partially validated
pendingINITIALInitial offer match, awaiting downstream updates.
pendingPENDING_AUTO_REVIEWStandard happy-path pending — pipeline still running, no risk or review flags raised.
pendingPENDING_HOLD_PERIODApproved and placed in a hold. Varying subrisk levels may be either auto-approved or remain in holding period.
pendingPENDING_MANUAL_REVIEWRouted for human review (standard manual, fraud specialist, admin-requested).
pendingPENDING_MISSING_INFOProcessing paused on missing data (unparsed fields, awaited OCR retry, awaited match). Not user-actionable.
pendingPENDING_SECONDARY_REVIEWAlready-reviewed submission pulled into senior/QA tier for a second look. Decision can flip.
pendingPENDING_USER_ACTION_SUPPORTSupport has reached out to the user (clarification or additional images); paused until they respond.
rejectedREJECTED_DUPLICATEReceipt or transaction already redeemed/submitted — same user, different user, or anywhere in system.
rejectedREJECTED_EMAIL_NO_MATCHNo merchant e-receipt email matched within the expected window.
rejectedREJECTED_FRAUDFraud signals — image-forensic flags (screen, edit, banned phrases), ML decision, or generic 'fraud'.
rejectedREJECTED_MEMBER_OFFER_MAXPer-offer redemption cap hit.
rejectedREJECTED_OFFER_NOT_ACTIVATEDOffer wasn't activated/clipped before purchase, or wasn't on the user's list.
rejectedREJECTED_OFFER_RULES_CHANNELFulfilment channel/medium not eligible (e.g., curbside pickup, ineligible online channel).
rejectedREJECTED_OFFER_RULES_DATEPurchase date outside the offer window — before start, after end, or past grace period.
rejectedREJECTED_OFFER_RULES_ITEMEligible product not found, or didn't meet product/quantity/UPC/return conditions.
rejectedREJECTED_OFFER_RULES_LOCATIONOffer not available in the user's area (state, zip, region).
rejectedREJECTED_OFFER_RULES_MERCHANTMerchant unrecognised or ineligible for the offer.
rejectedREJECTED_OFFER_UNAVAILABLEOffer no longer available — expired, exhausted, capped, or removed.
rejectedREJECTED_QUALITYReceipt image or parsed data inadequate (blurry, incomplete, missing fields, unparseable). User can resubmit a fresh image.
rejectedREJECTED_RATE_LIMITVelocity threshold hit (uploads, redemptions, or dollars in the rate-limit window). Don't expose to end customer.
rejectedREJECTED_SYSTEM_ERRORInternal/partner-side error or config issue.
rejectedREJECTED_USER_BLOCKUser on the partner's blocklist (prior fraud history or other reputation signals). Don't expose to end customer.

Field Reference

FieldTypeDescription
versionnumberAlways 1
idstring (UUID)Top-level ID for the webhook
timestampnumberUnix timestamp of the reward update in milliseconds
payload_typestringAlways "RewardUpdate"
payload_data.blink_receipt_idstring (UUID)Unique receipt ID
payload_data.client_user_idstringThe client-specific user identifier, if one was provided during registration or on a subsequent SDK request. Omitted when no value is available.
payload_data.reward_idstring (UUID)Unique reward identifier
payload_data.update_typestring"reward" or "missed_earnings"
payload_data.reward_typestring"promo", "boost", "barcode_collection", "base_scan", "correction"
payload_data.reward_amountnumberTotal dollar amount of the reward (see notes above for meaning in promo and missed_earnings contexts). Always the gross amount — not scaled by userPayoutPercentage.
payload_data.statusstring"pending", "complete"
payload_data.promo_ids_updatednumber[]Promo IDs whose status is first reported or changed in this webhook message
payload_data.qualified_promos.promo_idnumberIdentifier of this promo
payload_data.qualified_promos.titlestringName of the promotion the user's receipt qualified for
payload_data.qualified_promos.qualified_countnumberNumber of instances of the promo that qualified
payload_data.qualified_promos.promo_amountnumberDollar amount of the reward for the specific qualified promo
payload_data.qualified_promos.statusstring"pending", "accepted", "rejected"
payload_data.qualified_promos.reasonstringSee table of reason codes above
payload_data.qualified_promos.products.descriptionstringProduct description of the specific qualified promo
payload_data.qualified_promos.products.pricenumberPrice of the product(s) associated with the specific qualified promo
payload_data.qualified_promos.products.quantitynumberQuantity of the product(s) associated with the specific qualified promo

note

client_user_id is included in the payload only when a non-empty value was provided by the client during user registration or on a subsequent SDK request (GET /activations or POST /activations/scan_results). If no value has been set, the field is omitted entirely.