Skip to main content

Events

Each webhook action subscribes to a specific platform event. When the event fires, Loyal Guru sends a POST request to your endpoint with two custom headers identifying the event type, plus a JSON body.

Available Events​

EventLG-EntityLG-EventDescription
Customer createcustomercreateFires when a new customer is created
Customer updatecustomerupdateFires when a customer profile is updated (including automated inactivation)
Customer deletecustomerdeleteFires when a customer is deleted or anonymized (including automated inactivity deletion)
Customer challenge woncustomerchallenge_wonFires when a customer wins a challenge (threshold reached)
Challenge enrolledchallengeenrolledFires when a customer enrolls in a challenge
Score triggertriggerexecutedFires when a score trigger is executed
Refer a friend score triggertriggerexecutedFires when a referral score trigger is executed
Create profile score triggertriggerexecutedFires when a profile creation score trigger is executed
Cart createactivitycreateFires when a purchase (cart) is created
Customer tier woncustomertier_level_wonFires when a customer reaches a new tier level
Customer tier lostcustomertier_level_lostFires when a customer drops to a lower tier level
Campaign sentcampaigndeliveredFires when a Targeted Delivery campaign is sent (campaign_sent trigger)
Plan campaign sentcampaignplan_deliveredFires per campaign when an Intelligent Delivery plan finishes (plan_campaign_sent trigger)
Plan deliveredplandeliveredFires once when an Intelligent Delivery plan is delivered (Plan delivered trigger)
Voucher createdvouchercreatedFires when a voucher is created in a unit delivery flow (voucher_created trigger)
Voucher redeemedvoucherredeemedFires when a voucher is redeemed
Reward redeemedrewardredeemedFires when a reward is redeemed

Customer Events​

Customer Create​

Headers:

HeaderValue
LG-Entitycustomer
LG-Eventcreate

Body fields:

FieldDescription
idID of the customer (integer). Optional if code is present.
codeAlternative customer identifier (alphanumeric, up to 36 characters)
nameFirst name
surname_1First surname
surname_2Second surname
emailEmail address
phoneMobile phone number
phone_prefixCountry phone prefix (required when phone is filled)
gendermasculine or feminine
birthDate of birth. Format: YYYY-MM-DD
dniIdentification card number
document_typeType of identification document
addressStreet address
address_extraAdditional address info
cityCity
stateRegion / state
postal_codePostal code
countryISO 3166-1 alpha-2 country code (uppercase)
preferred_languageISO 639-1 language code
statusactive / inactive / merged / merging / unverified / deleted
kindclient or card
fraudulenttrue if the customer is flagged as fraudulent
termstrue when the customer accepted GDPR terms
terms_accepted_atDate when GDPR terms were accepted
communicationstrue when the customer accepted receiving communications
profilingtrue when the customer consented to data profiling
profiling_accepted_atDate when profiling consent was accepted
third_party_consenttrue if the customer accepted third-party data sharing
email_unsubscribeUnsubscribe status for email campaigns
sms_unsubscribeUnsubscribe status for SMS campaigns
push_unsubscribeUnsubscribe status for push notifications
paper_freetrue if the customer uses digital receipts
apptrue if registration was done via a mobile app
referred_byCustomer ID of the referrer (must be an existing customer)
registration_location_idRegistration store ID. Optional if registration_location_code is present.
registration_location_codeRegistration store code
collective_idCollective ID
collective_slugCollective slug (used only when collective_id is not present)
attributesAdditional custom attributes stored on the customer
custom1…customNCustom values configured for the company
created_atDateTime of customer creation
updated_atDateTime of last update

Example payload:

{
"address": null,
"address_extra": null,
"birth": null,
"city": null,
"code": null,
"collective_id": null,
"collective_slug": null,
"communications": false,
"country": "ES",
"created_at": "2025-10-21T15:12:24Z",
"custom1": null,
"custom2": null,
"dni": null,
"document_type": null,
"email": null,
"email_unsubscribe": false,
"fraudulent": false,
"gender": null,
"id": "56789112345",
"kind": "client",
"name": "Esther test",
"paper_free": false,
"phone": null,
"phone_prefix": "",
"postal_code": null,
"preferred_language": "es",
"profiling": false,
"profiling_accepted_at": null,
"push_unsubscribe": false,
"referred_by": null,
"app": false,
"registration_location_code": null,
"registration_location_id": 1,
"sms_unsubscribe": false,
"state": null,
"status": "active",
"surname_1": "test2",
"surname_2": null,
"terms": false,
"terms_accepted_at": null,
"updated_at": "2025-10-21T15:12:24Z"
}

Customer Update​

Headers:

HeaderValue
LG-Entitycustomer
LG-Eventupdate

Same body structure as Customer Create.

note

Also fires when the Inactivity Lifecycle job sets a Customer to inactive. Plan for additional customer / update volume when a Company enables inactivation.


Customer Delete​

Headers:

HeaderValue
LG-Entitycustomer
LG-Eventdelete
note

Also fires when the Inactivity Lifecycle job anonymizes a Customer (deleted). Soft anonymization uses hard: false. Plan for additional customer / delete volume when a Company enables the delete rule.

Example payload:

{
"customer_code": "123fdrgg",
"customer_id": 134345,
"hard": false
}

Customer Challenge Won​

Event generated when a customer wins a challenge (threshold reached).

Headers:

HeaderValue
LG-Entitycustomer
LG-Eventchallenge_won

Body fields:

FieldDescription
customer.idCustomer ID
customer.codeCustomer code
customer.scoreUpdated total balance
customer.score_availableUpdated available balance
customer_attribute_valueCalculated attribute value for the challenge
challenge.idChallenge definition ID
challenge.nameChallenge name
challenge.level_idAchievement definition ID
challenge.level_nameAchievement level name
challenge.thresholdGoal value to reach
challenge.expires_atChallenge expiration datetime
challenge.created_atFirst win datetime
challenge.updated_atLast win datetime
scores[].scorePoints won
scores[].available_fromPoints activation date
scores[].available_toPoints expiration date
scores[].loyalty_score_idLoyalty rule ID applied

Example payload:

{
"customer": {
"id": 12100002,
"code": "12100002X",
"score": 122389,
"score_available": 122379
},
"customer_attribute_value": 10000,
"challenge": {
"id": 73,
"name": "[Open to all] Run more than 10k",
"level_id": 108,
"level_name": "10000 kms",
"threshold": 10000,
"expires_at": "2024-07-14T23:59:59Z",
"created_at": "2024-05-07T00:00:00Z",
"updated_at": "2024-05-07T08:00:00Z"
},
"scores": [
{
"available_from": "2024-05-07",
"available_to": "2024-06-07",
"score": 100,
"loyalty_score_id": 43219393
}
]
}

Challenge Enrolled​

Event generated when a customer enrolls in a challenge.

Headers:

HeaderValue
LG-Entitychallenge
LG-Eventenrolled

Body fields:

FieldTypeDescription
idIntegerEnrollment ID
challenge_idIntegerChallenge definition ID
challenge_nameStringChallenge name
customer_idIntegerCustomer ID
customer_codeStringCustomer code
enrolled_atUTC DatetimeEnrollment datetime
structure[].levelIntegerAchievement level number
structure[].thresholdNumberPoints/value threshold for this level
structure[].nameStringLevel name

Example payload:

{
"id": 12345,
"challenge_id": 67890,
"challenge_name": "Ultimate Fitness Challenge",
"customer_id": 54321,
"customer_code": "CUST001",
"enrolled_at": "2024-07-29T12:34:56Z",
"structure": [
{ "level": 1, "threshold": 100.0, "name": "Beginner" },
{ "level": 2, "threshold": 200.0, "name": "Intermediate" },
{ "level": 3, "threshold": 300.0, "name": "Advanced" }
]
}

Score Trigger​

Fires when a score trigger (manual or automated) is executed.

Headers:

HeaderValue
LG-Entitytrigger
LG-Eventexecuted

Body fields:

FieldTypeDescription
slugStringSlug of the trigger
commentsStringComments attached to the trigger
created_atStringEvent generation timestamp
total_scoresIntegerTotal points awarded
scores[].loyalty_score_idIntegerLoyalty rule ID
scores[].scoreIntegerPoints awarded by this rule
scores[].available_fromStringPoints validity start date
scores[].available_toStringPoints validity end date
customer.idIntegerCustomer ID
customer.codeString (nullable)Customer code
customer.scoreIntegerUpdated total balance
customer.score_availableIntegerUpdated available balance

Body example:

{
"slug": "manual",
"comments": "Commercial action",
"created_at": "2024-08-31T15:00:01Z",
"total_scores": 30,
"scores": [
{
"loyalty_score_id": 12,
"score": 30,
"available_from": "2024-01-01",
"available_to": "2025-01-01"
}
],
"customer": {
"id": 12345,
"code": "12345a",
"score": 10,
"score_available": 10
}
}
note

The Refer a friend and Create profile trigger events share the same header structure (LG-Entity: trigger, LG-Event: executed) as Score trigger, with a slug identifying the specific trigger type (refer_a_friend_executed, after_create_profile).


Cart Events​

Cart Create​

Headers:

HeaderValue
LG-Entityactivity
LG-Eventcreate

Fires when a purchase (cart) is created via the Streaming API. The body contains the cart payload returned by the platform.

Body example:

{
"id": 5704568633556992,
"currency": "EUR",
"code": "test-ticket-create-post-action-event-0004",
"total": 18.57,
"location_id": 1496,
"customer": {
"id": 10010010124,
"score": 0,
"score_as_money": 0,
"score_available": 0,
"score_available_as_money": 0,
"score_to_reach_cashback": 0,
"money_to_spend_to_reach_cashback": 0,
"score_threshold_cashback": 0,
"score_threshold_cashback_as_money": 0,
"money_threshold_cashback": 0,
"fraudulent": false
},
"creation_date": "2023-06-08T15:14:05Z",
"lines": [
{
"order": 1,
"total": 19.57,
"quantity": 1,
"product_code": "22SMTK055000L",
"original_total": 19.57
},
{
"order": -1,
"total": -1,
"quantity": 1,
"original_total": 0
}
],
"business_name": "testdiporpre",
"score": 0,
"score_as_money": 0,
"score_used": 0,
"score_used_as_money": 0,
"score_returned_to_customer": 0,
"score_returned_to_customer_as_money": 0,
"score_returned_from_customer": 0,
"score_returned_from_customer_as_money": 0,
"custom1": "322001-10456",
"custom3": {
"nested": {
"is": true
},
"test": "test"
},
"custom5": "",
"total_discount_promotion_applied": 1,
"total_discount_applied": 1,
"effects": [
{
"rule_id": 666555922,
"rule_name": "test direct value validator",
"type": "discount",
"effect_type": "direct_value",
"distribution_type": "total",
"value": 100,
"select_customers": "loyalty"
}
]
}

Customer Tier Events​

Customer Tier Won​

Fires when a customer reaches a new tier level (threshold reached).

Headers:

HeaderValue
LG-Entitycustomer
LG-Eventtier_level_won

Body fields:

FieldDescription
customer.id / customer.codeCustomer identity
customer.score / customer.score_availableUpdated points balances
customer_attribute_valueCalculated attribute value used by the tier
tier.id / tier.nameTier definition identifier and name
tier.level_id / tier.level_name / tier.level_numberWon level details
tier.thresholdThreshold achieved
tier.expires_at / tier.created_at / tier.updated_atLevel expiration and win timestamps
scores[]Points awarded with the tier win (score, loyalty_score_id, availability dates)

Body example:

{
"customer": {
"id": 12345,
"code": "CUST123",
"score": 2,
"score_available": 0
},
"customer_attribute_value": 51,
"tier": {
"id": 3,
"name": "Runner",
"level_id": 222,
"level_number": 2,
"level_name": "silver",
"threshold": 50,
"expires_at": "2022-12-31T23:59:59Z",
"created_at": "2022-01-01T00:00:00Z",
"updated_at": "2022-01-01T00:00:00Z"
},
"scores": [
{
"available_from": "2023-01-01",
"available_to": "2023-01-01",
"score": 2,
"line_order": -1,
"loyalty_score_id": 1
}
]
}

Customer Tier Lost​

Fires when a customer drops to a lower tier level.

Headers:

HeaderValue
LG-Entitycustomer
LG-Eventtier_level_lost

Body fields:

FieldDescription
customer_id / customer_codeCustomer identity
attribute_valueCalculated attribute value used by the tier
current_dateEvaluation timestamp
current_tierCurrent level after the drop (achievement_id, level_name, level_number, level_threshold)
previous_tierPrevious level (achievement_id, level_name, level_number)
tier_id / tier_nameTier definition identifier and name
expires_atCurrent level expiration
to_reach_next_level / to_reach_next_level_nameProgress needed to regain the next level

Body example:

{
"attribute_value": 1268.93,
"current_date": "2023-06-20 03:00:00+00:00",
"current_tier": {
"achievement_id": 55,
"level_name": "Silver",
"level_number": 1,
"level_threshold": 0
},
"customer_code": "a97fd304ead449cd94bf5c0524ec121c",
"customer_id": 614472060,
"expires_at": "2025-11-18 22:59:59.999999+00:00",
"previous_tier": {
"achievement_id": 57,
"level_name": "Gold",
"level_number": 2
},
"tier_id": 19,
"tier_name": "DESIGUAL CLUB POLAND",
"to_reach_next_level": 231.07,
"to_reach_next_level_name": "Gold"
}

Campaign Events​

Campaign Sent​

Fires when a Targeted Delivery (manual) campaign has been sent successfully. In Owner, subscribe with the campaign_sent trigger.

The webhook body includes campaign metadata, a temporary signed URL to the vouchers CSV, checksum, and a promotion snapshot.

Headers:

HeaderValue
LG-Entitycampaign
LG-Eventdelivered

Body fields:

FieldTypeDescription
campaign_history_idIntegerID of the campaign delivery history
campaign_idIntegerID of the sent campaign
campaign_nameStringCampaign name
sent_atDatetimeCampaign delivery time in ISO 8601 format
voucher_typeStringcoupon or discount
record_countIntegerNumber of records in the exported CSV
file_urlStringTemporary signed HTTPS URL for downloading the CSV
file_url_expires_atDatetimeExpiration of file_url in ISO 8601 format
checksumStringMD5 digest of the CSV as lowercase hexadecimal
promotionObjectSnapshot of the coupon used by the campaign
warning

file_url β€” parse before use. Read file_url by parsing the webhook JSON body (do not extract it from a raw log line or a partially copied string). Use the full value as returned, including all query parameters (for example X-Goog-Signature). Truncating, stripping, or re-encoding the URL invalidates the signature and the download fails.

Body example:

{
"campaign_history_id": 98765,
"campaign_id": 12345,
"campaign_name": "Summer Coupons",
"sent_at": "2026-07-06T10:00:00Z",
"voucher_type": "coupon",
"record_count": 50000,
"file_url": "https://storage.googleapis.com/example/summer-coupons.csv?X-Goog-Signature=abc123",
"file_url_expires_at": "2026-07-07T11:00:00Z",
"checksum": "a3f5c1d9e7b24a6c8f0d123456789abc",
"promotion": {
"id": 54321,
"name": "5 EUR discount",
"coupon_type": "standard",
"discount": 5.5,
"discount_type": "cash",
"available_from": "2026-07-01",
"available_to": "2026-08-31",
"affectation": "activity",
"applies_to": "all",
"min_money": 30.25,
"max_redemptions": 3,
"cumulative": false
}
}
note

Bulk campaign sends do not emit per-voucher voucher.created events. Use this campaign payload and the CSV download for mass delivery.


Plan Campaign Sent​

Fires once per campaign when an Intelligent Delivery plan finishes exporting vouchers. In Owner, subscribe with the plan_campaign_sent trigger.

The JSON body uses the same schema as Campaign sent. Distinguish plan campaigns from Targeted Delivery campaigns with the LG-Event header.

Headers:

HeaderValue
LG-Entitycampaign
LG-Eventplan_delivered

Body fields and examples: same as Campaign sent.

note

This is not the same as Plan delivered. Plan campaign sent uses LG-Entity: campaign and fires per campaign inside a plan. Plan delivered uses LG-Entity: plan and fires once for the whole plan.


Plan Delivered​

Fires once when an Intelligent Delivery plan has been delivered successfully (including pumps). In the Owner App, subscribe with the Plan delivered trigger.

Use this event when an external system only needs to know that the plan finished β€” for example, to start a file generation or downstream batch job keyed by plan_id. For per-campaign voucher CSV payloads, use Plan campaign sent instead.

Headers:

HeaderValue
LG-Entityplan
LG-Eventdelivered

Body fields:

FieldTypeDescription
plan_idIntegerID of the delivered Intelligent Delivery plan

Example payload:

{
"plan_id": 12345
}

Voucher Events​

Voucher Created​

Fires when a voucher is created in a unit delivery flow (manual assignment, game, challenge, reward, or recipe). In the Owner App, subscribe with the voucher_created trigger.

Mass campaign or plan sends do not emit this event per voucher; those flows use Campaign sent / Plan campaign sent plus the CSV file. For plan-level completion only, see Plan delivered.

Headers:

HeaderValue
LG-Entityvoucher
LG-Eventcreated

Body fields:

FieldTypeDescription
created_atUTC DatetimeVoucher creation time
originStringmanual, game, challenge, reward, or recipe
origin_idInteger, optionalIdentifier of the originating object
voucher_typeStringcoupon or discount
customer.idIntegerCustomer ID
customer.codeStringCustomer code
voucher.idIntegerVoucher ID
voucher.codeStringVoucher code
voucher.nameString, optionalCoupon snapshot name
voucher.statusStringVoucher status
voucher.discountNumber, optionalDiscount value
voucher.discount_typeString, optionalDiscount type
voucher.available_fromUTC Datetime, optionalValidity start
voucher.available_toUTC Datetime, optionalValidity end
voucher.available_redemptionsInteger, optionalRemaining redemptions
voucher.affectationString, optionalVoucher affectation
voucher.descriptionString, optionalVoucher description
coupon.idIntegerCoupon ID
coupon.coupon_typeString, optionalCoupon type
loyalty_rule.idInteger, discount onlyLoyalty rule ID
loyalty_rule.nameString, discount onlyLoyalty rule name
campaign.idInteger, optionalCampaign ID
campaign.campaign_history_idInteger, optionalCampaign history ID
campaign.nameString, optionalCampaign name
campaign.sent_atUTC Datetime, optionalCampaign delivery time
campaign.customersInteger, optionalNumber of campaign customers

Coupon example:

{
"created_at": "2026-07-06T15:00:00Z",
"origin": "game",
"origin_id": 1234,
"voucher_type": "coupon",
"customer": {
"id": 4135,
"code": "CUST-4135"
},
"voucher": {
"id": 78901,
"code": "9900031393759",
"name": "5 EUR en compras >30 EUR",
"status": "pending",
"discount": 5.5,
"discount_type": "cash",
"available_from": "2026-07-01T00:00:00Z",
"available_to": "2026-08-31T23:59:59Z",
"available_redemptions": 1,
"affectation": "activity",
"description": "Valid in purchases over 30 EUR"
},
"coupon": {
"id": 54321,
"coupon_type": "standard"
},
"campaign": {
"id": 12345,
"campaign_history_id": 98765,
"name": "Cupones Verano",
"sent_at": "2026-07-06T10:00:00Z",
"customers": 50000
}
}

Discount example:

{
"created_at": "2026-07-06T15:00:00Z",
"origin": "manual",
"voucher_type": "discount",
"customer": {
"id": 4135,
"code": "CUST-4135"
},
"voucher": {
"id": 78902,
"code": "9900031393760",
"name": "Descuento fidelidad",
"status": "pending",
"available_from": "2026-07-01T00:00:00Z",
"available_to": "2026-08-31T23:59:59Z",
"available_redemptions": 1
},
"coupon": {
"id": 54322
},
"loyalty_rule": {
"id": 24680,
"name": "Descuento fidelidad"
},
"campaign": {
"id": 12345,
"campaign_history_id": 98765,
"name": "Cupones Verano",
"sent_at": "2026-07-06T10:00:00Z",
"customers": 50000
}
}

Voucher Redeemed​

Headers:

HeaderValue
LG-Entityvoucher
LG-Eventredeemed

Body fields:

FieldDescription
activity_id / activity_codeCart where the voucher was redeemed
created_atRedemption timestamp
voucher.codeRedeemed voucher code
voucher.discount / voucher.discount_typeDiscount value and type (e.g., percent, cash)
voucher.available_from / voucher.available_toValidity window
voucher.available_redemptionsRemaining redemptions after this use
voucher.name / voucher.description / voucher.affectationVoucher details
customer.id / customer.codeCustomer who redeemed the voucher

Body example:

{
"activity_id": 109977132684614129,
"activity_code": "POS-2026-0415-8831",
"customer": {
"id": 4135,
"code": "CUST-4135"
},
"created_at": "2026-04-15T14:22:03.512Z",
"voucher": {
"code": "9900031393759",
"discount": 12.5,
"discount_type": "percent",
"available_from": "2026-04-10T00:00:00Z",
"available_to": "2026-08-08T23:59:59Z",
"available_redemptions": 2,
"name": "Spring promo 15% off footwear",
"description": "Valid on selected SKUs in store and online.",
"affectation": "category",
"purchased_product_ids": ["100", "200", "201"]
}
}

Reward Events​

Reward Redeemed​

Headers:

HeaderValue
LG-Entityreward
LG-Eventredeemed

Body fields:

FieldDescription
redemption_idUnique redemption ID
redemption_typemanual or loyalty_rule
reward.id / reward.name / reward.typeReward details
score_usedPoints spent on the redemption
codeRedeemed reward code when applicable
customer.id / customer.code / customer.score / customer.score_availableCustomer identity and updated balances
created_atRedemption timestamp

Body example:

{
"redemption_id": 35,
"redemption_type": "manual",
"reward": {
"id": 835,
"name": "coupon discount 10",
"type": "coupon",
"extra_money": 2.3,
"currency": "EUR"
},
"customer": {
"id": 3232,
"code": "43243jdg6675d",
"score": 10,
"score_available": 10
},
"created_at": "2024-10-01T09:00:00Z",
"score_used": 200,
"code": "Xyguyfuiyuh"
}