Articles on: Webhook API

Webhook Events

Topic catalogue


Points

Topic

Fires when

points/earned

A customer earns points from any earning rule

points/redeemed

A customer spends points on a reward

points/expired

Points expire under the expiration policy

points/reversed

Points are taken back because an order was refunded, cancelled, or unfulfilled

points/adjusted

A balance changes outside the rules above — admin edit, import, store credit, or Shopify Flow

points/expiring_soon

Scheduled reminder that a balance is about to expire


Customer

Topic

Fires when

customer/joined

A customer joins the loyalty programme


VIP tiers

Topic

Fires when

tier/upgraded

A customer moves up a VIP tier

tier/downgraded

A customer moves down a VIP tier

tier/demotion_reminder

A customer is at risk of losing their tier

tier/perk_granted

A tier perk or reward is issued to a customer


Rewards

Topic

Fires when

reward/expiring_soon

Scheduled reminder that a reward is about to expire


Referrals

Topic

Fires when

referral/invite_sent

A customer sends a referral invitation

referral/reward_earned

A referrer is rewarded for a successful referral

referral/referee_claimed

A referred friend claims their welcome reward


Birthday

Topic

Fires when

birthday/reward_earned

A birthday reward is issued

birthday/updated

A customer's birthday is set or changed

Event payloads

points/earned

Field

Type

Description

points

number

Points actually added, always positive. The final figure, after every modifier below

basePoints

number

Points before the limited-time-offer multiplier. Equals points when no offer applied

earningRuleId

string

The earning rule that awarded the points

orderId

number

Shopify order id, when the rule is order-driven

lto

object

The limited-time offer that multiplied this award, or null if none applied

vipEarning

object

The VIP tier rate used instead of the rule's own rate, or null if the rule's rate was used


{
"oldPoints": 1350,
"newPoints": 1650,
"activityType": "earn_point",
"settingType": "place_order",
"points": 300,
"basePoints": 150,
"earningRuleId": "66c9f21b7e5a4d0193bc2210",
"orderId": 5512094318721,
"lto": {
"id": "66e40a12c7b1f5039a2d6611",
"name": "Double Points Weekend",
"pointMultiplier": 2
},
"vipEarning": {
"earnPoint": 2,
"spent": 1
}
}


The two apply at different stages, so one event can carry both:

  1. vipEarning replaces the earning rule's own rate. When the customer's tier grants a better rate, they earn earnPoint points per spent of order value instead of the rate configured on the rule. That is what basePoints is calculated from.
  2. lto then multiplies the result: points = basePoints × lto.pointMultiplier.null on either field means the modifier was not applied — not that it is unknown.


points/redeemed

Field

Type

Description

pointsRedeemed

number

Points spent, always positive

redeemRuleId

string

The redemption rule used


On this topic settingType is the reward type: amountpercentageshippingfree_productstore_credit, or redirect_url.

{
"oldPoints": 1500,
"newPoints": 1000,
"activityType": "redeem_point",
"settingType": "amount",
"pointsRedeemed": 500,
"redeemRuleId": "66ca0374b19f8c02d47ae115"
}


points/expired

Field

Type

Description

pointsExpired

number

Points removed, always positive

{
"oldPoints": 1000,
"newPoints": 800,
"activityType": "adjust_point",
"settingType": "point_expiration",
"pointsExpired": 200
}


points/reversed

Field

Type

Description

pointsReversed

number

Points taken back, always positive

reason

string

refundedcancelled, or unfulfilled

orderId

number

The order that triggered the reversal

earningRuleId

string

The rule that originally awarded the points


{
"oldPoints": 800,
"newPoints": 650,
"activityType": "adjust_point",
"settingType": "refunded",
"pointsReversed": 150,
"reason": "refunded",
"orderId": 5512094318721,
"earningRuleId": "66c9f21b7e5a4d0193bc2210"
}


points/adjusted

Field

Type

Description

points

number

Signed delta — negative when points were removed

source

string

adminimportstore_credit, or shopify_flow

reason

string

Reason recorded with the adjustment

note

string

Free-text note recorded with the adjustment


{
"oldPoints": 650,
"newPoints": 900,
"activityType": "adjust_point",
"settingType": null,
"points": 250,
"source": "admin",
"reason": "Goodwill credit",
"note": "Ticket #4821"
}


points/expiring_soon

Field

Type

Description

pointsExpiring

number

Points due to expire

expiresAt

string

ISO 8601 timestamp of the expiry

daysRemaining

number

Days until the points expire

{
"pointsExpiring": 900,
"expiresAt": "2026-09-24T00:00:00.000Z",
"daysRemaining": 30
}


customer/joined

Field

Type

Description

source

string

storefront when the customer joined on the shop, api when enrolled through the API

pointsEarned

number

Sign-up bonus awarded, 0 if none

{
"source": "storefront",
"pointsEarned": 100
}


tier/upgraded and tier/downgraded

Both topics carry the same fields.

Field

Type

Description

previousTier

object

{ id, name, targetValue }null if the customer had no tier

currentTier

object

{ id, name, targetValue } of the new tier

achieveType

string

What the VIP programme measures: amount (spend) or point (points earned)

source

string

points for an automatic change, manual for an admin change, reset for a VIP period reset

{
"previousTier": { "id": "66d1b4e7c2a9f80315de7740", "name": "Silver", "targetValue": 500 },
"currentTier": { "id": "66d1b4e7c2a9f80315de7742", "name": "Gold", "targetValue": 1500 },
"achieveType": "point",
"source": "points"
}


tier/demotion_reminder

Field

Type

Description

tierAtRisk

object

{ id, name, targetValue } of the tier about to be lost

currentValue

number

The customer's progress against targetValue

daysRemaining

number

Days left to requalify

{
"tierAtRisk": { "id": "66d1b4e7c2a9f80315de7742", "name": "Gold", "targetValue": 1500 },
"currentValue": 1120,
"daysRemaining": 7
}


tier/perk_granted

Field

Type

Description

reward

object

{ id, code, name, discountType, value, expiresAt }

perkType

string

vip_perk or vip_reward

vipDiscountId

string

The VIP discount rule that issued it


{
"reward": {
"id": "66f2c9a4b81d3e0217af7c58",
"code": "GOLD-9F2A4C",
"name": "Gold members: 15% off",
"discountType": "percentage", # amount | percentage | shipping | free_product | custom | bonus_points
"value": 15,
"expiresAt": "2026-09-30T23:59:59.000Z"
},
"perkType": "vip_perk",
"vipDiscountId": "66d1c07fa4b2e5031f8ac913"
}


reward/expiring_soon

Field

Type

Description

reward

object

{ id, code, name, expiresAt }

daysRemaining

number

Days until the reward expires

{
"reward": {
"id": "66f2c9a4b81d3e0217af7c58",
"code": "GOLD-9F2A4C",
"name": "Gold members: 15% off",
"expiresAt": "2026-09-01T23:59:59.000Z"
},
"daysRemaining": 7
}


referral/invite_sent

The customer in the envelope is the referrer.

Field

Type

Description

referralCode

string

The referrer's code

referralLink

string

The shareable referral URL

invitedEmail

string

Email the invitation was sent to

{
"referralCode": "MAI-4F2A",
"referralLink": "https://example-store.com?bloy_ref=MAI-4F2A",
"invitedEmail": "friend@example.com"
}


referral/reward_earned

The customer in the envelope is the referrer.

Field

Type

Description

role

string

Always referrer

referralCode

string

The referrer's code

rewardType

string

Always points

pointsEarned

number

Points awarded for the referral

earningName

string

Name of the referral earning rule

{
"role": "referrer",
"referralCode": "MAI-4F2A",
"rewardType": "points",
"pointsEarned": 200,
"earningName": "Refer a friend"
}


referral/referee_claimed

The customer in the envelope is the referred friend.

Field

Type

Description

role

string

Always referee

rewardType

string

Always coupon

couponCode

string

The discount code issued

rewardName

string

Human-readable description of the reward

discountValue

number

Value of the discount

{
"role": "referee",
"rewardType": "coupon",
"couponCode": "WELCOME-7B1E",
"rewardName": "10% off your first order",
"discountValue": 10
}


birthday/reward_earned

Field

Type

Description

rewardType

string

points when points were awarded, discount when a coupon was issued

pointsEarned

number

Points awarded, 0 when the reward was a discount

{
"rewardType": "points",
"pointsEarned": 500
}


birthday/updated

Field

Type

Description

birthday

string

null

The new birthday as stored, ISO 8601, null if cleared

{
"birthday": "1994-03-18T00:00:00.000Z"
}

Updated on: 26/08/2026

Was this article helpful?

Share your feedback

Cancel

Thank you!