Skip to main content

RewardUpdate

Description: Triggered when an existing reward is updated.

When to use: Subscribe to this event if you need to update your records when reward data changes.

Sources:

  • iOS and Android Mobile SDK reward events are triggered.

Payload Structure:

{
"id": "UUID for webhook message",
"timestamp": 1778077677000,
"payload_data": {
"blink_receipt_id": "UUID - Primary Blink Receipt ID",
"update_type": "[reward|missed_earnings]",
"status": "[pending|complete]",
"reward_id": "uuid",
"reward_type": "[promo|boost|barcode_collection|base_scan|correction]",
"reward_amount": 1.00,
"promo_ids_updated": [123],
"qualified_promos": [
{
"promo_id": 123,
"title": "Name of the promotion the user's receipt qualified for",
"qualified_count": 1,
"promo_amount": 1.00,
"status": "[pending|accepted|rejected]",
"reason": "Reason for status=pending or status=rejected",
"products": [
{
"description": "Product description of the specific qualified promo",
"price": 1.00,
"quantity": 1
}
]
}
],
"client_user_id": "The client-specific user identifier"
},
"payload_type": "RewardUpdate",
"version": 1
}
note

RewardUpdate never sends null values — fields are either present with a value or omitted entirely.

For promo and missed earnings updates, qualified_promos contains the current full state for all qualifying promos, while promo_ids_updated contains the promo IDs whose status is first reported or changed in that specific webhook message.

Field Reference

payload_data fields

FieldTypeRequiredNullableNotes
blink_receipt_idstringAlwaysNoPresent on every update for correlation.
update_typereward | missed_earningsAlwaysNo
statuspending | completeAlwaysNo
reward_idstring (uuid)OptionalNoOmitted when absent — e.g. a missed_earnings initial update where all promos were rejected. Always present when update_type = reward.
reward_typepromo | boost | barcode_collection | base_scan | correctionOptionalNoOnly sent when update_type = reward. Always omitted for missed_earnings. correction is an out-of-band reward manually issued by Actual — see below.
reward_amountnumberOptionalNoSum of non-rejected promo_amounts. May be omitted for missed_earnings with no promo amount. Always the gross amount — see note below.
promo_ids_updatednumber[]OptionalNoOnly for promo rewards and missed earnings. May be an empty array.
qualified_promosobject[]OptionalNoPresent only when there is at least one promo entry; omitted otherwise.
client_user_idstringOptionalNoOmitted when not provided.

qualified_promos[] entry fields

FieldTypeRequiredNullableNotes
promo_idnumberAlwaysNo
titlestringAlwaysNo
qualified_countnumberAlwaysNo0 for rejected entries.
promo_amountnumberAlwaysNo0 for rejected entries.
statuspending | accepted | rejectedAlwaysNo
reasonstringOptionalNoOmitted for fully-accepted entries; present for pending, rejected, or partial when a reason exists.
productsobject[]OptionalNoOmitted entirely for rejected entries.

products[] entry fields

FieldTypeRequiredNullableNotes
descriptionstringAlwaysNoMay be an empty string.
pricenumberAlwaysNo
quantitynumberAlwaysNo

Base Scan Lifecycle

The base_scan reward is tied to the receipt's own validation outcome and is no longer sent immediately upon submission.

  • If the receipt resolves as accepted (via ReceiptSummary), a RewardUpdate with reward_type = base_scan and status = complete is sent.
  • If the receipt resolves as rejected, no RewardUpdate for the base scan is sent at all.
  • If the receipt enters pending (error review), the base scan reward is held until the review concludes and then follows the same accept/reject rule above.

Out-of-Band Corrections

Actual may manually issue a reward tied to a specific receipt at any point — for example, to credit a user outside of the normal review process. These appear as a RewardUpdate with reward_type = correction. They carry their own reward_id but share the same blink_receipt_id as the original receipt.

Contingent Coupons

Some promotions are marked as contingent, meaning they do not auto-approve after the standard 24-hour window. Instead they follow the same longer review trajectory as missed earnings — waiting on a provider decision, with an extended timeout that resolves to rejected if no decision arrives. These promos remain in pending state longer than standard promos; the existing reason codes and state machine apply.


reward_amount is always the gross amount — not adjusted by userPayoutPercentage

reward_amount in every RewardUpdate payload reflects the full reward value before any client-side payout scaling is applied.

The userPayoutPercentage SDK setting (configured in BlinkEngageRewardConfig on iOS and RewardCurrency on Android) controls how much of that value is displayed to the user inside the mobile app. It is applied on-device only and has no effect on the amount sent to your webhook endpoint.

Example: If reward_amount is $1.00 and your app's userPayoutPercentage is 0.6, the user sees $0.60 in the app — but your webhook always receives $1.00.

If you use webhook amounts to credit users or reconcile rewards in your backend, apply your own payout percentage logic server-side rather than expecting the webhook to reflect the scaled amount.

RewardUpdate sequence diagram