Link Search Menu Expand Document

Wallet mutation webhook

Triggered as a result of a mutation (a credit or a debit) occurring on a user’s wallet.

An example of a points wallet mutation webhook

	"type": "shopper.points-mutation",
	"id": "5b63362028701",
	"chain_id": 1743,
	"created": "2019-01-04T16:53:36Z",
	"data": {
		"amount": "10.00",
		"basket": {
			"created_date": "2019-05-17T09:56:34+00:00",
			"id": 432440,
			"retailer_basket_code": "20190517-test-00039",
			"total_value": 235
		"campaign": {
			"campaign_id": 170,
			"campaign_image_dimension_x": null,
			"campaign_image_dimension_y": null,
			"campaign_image_filename": null,
			"campaign_image_link": null,
			"campaign_image_url": null,
			"campaign_title": "ACME Wallet",
			"campaign_title_localised": "ACME Portemonnaie NL",
			"campaign_type": "wallet",
			"contributing_campaign": null
		"created_date": "2019-05-17T10:23:03+00:00",
		"currency_id": 2,
		"earn_or_spend": "earn",
		"receipt_id": null,
		"returned_item": null,
		"timestamp_microsecond": "2019-05-17 10:23:04.026549",
		"type": "handleLoyaltyRule",
		"user": {
			"address_housenumber": null,
			"address_housenumber_extension": null,
			"address_line_2": null,
			"address_line_3": null,
			"address_postalcode": null,
			"address_regionstate": null,
			"address_streetname": null,
			"address_towncity": null,
			"authentication_point_identifier": "1180626",
			"auxiliary_identifier": "eab465uxp41",
			"birthday": "1981-04-29T00:00:00+00:00",
			"country_code": null,
			"first_name": "John",
			"gender": "M",
			"id": 3141779,
			"language": "nl-BE",
			"last_name": "Doe",
			"loyalty_status": {
				"campaign_id": 2095,
				"name": "Level 1",
				"description": "Level 1 in the Programme",
				"loyalty_level_id": 2,
				"points_balance_current": 230,
				"points_to_proceed_next_level": 270,
				"points_to_remain_current_level": 20,
				"last_review_date": "2019-04-04T00:05:22+00:00",
				"next_review_date": "2020-04-04T00:05:22+00:00",
				"date_reached": "2019-06-06T08:06:14+00:00"
			"mailing_list": {
				"mailing_list_sub_offered": true,
				"mailing_list_subscribed": true,
				"printed_mailing_list_subscribed": false
			"member_number": {
				"code": "100130",
				"type": "custom"
			"opt_in_programme": {
				"programme_opted_in": true,
				"join_date": "2019-06-06T08:06:14+00:00"
			"opt_in_secondary": null,
			"push_notification_subscription": {
				"subscribed": false,
				"subscriptions": []
			"registered": true,
			"signup_channel": null,
			"user_id": 3141779,
			"username": ""
		"user_id": 3141779,
		"user_purchase_progress": {
			"id": 203676,
			"log_message": "Loyalty contribution from addPointsToWallet:points_tracker",
			"mutation_owner": null,
			"uniqid": "5f637ba2de54a2.06408515"
		"voucher": {
			"creating_user": {
				"full_name": "Jane Smit",
				"user_id": 1
			"generating_return_transaction": [],
			"parent_voucher": null,
			"voucher_amount": 2,
			"voucher_amount_original": 2,
			"voucher_amount_redeemed": 2,
			"voucher_currency_id": 2,
			"voucher_currency_symbol": "\u20ac",
			"voucher_expiry_datetime_utc": "2020-01-01 00:00:00",
			"voucher_expiry_seconds_remaining": 966521006,
			"voucher_id": 119498,
			"voucher_key": "1d5375bc6471b845503728775f3c8c58eed43a123e71ce3d6356d17bab24146c",
			"voucher_locked": false,
			"voucher_redeemed_datetime": "2019-05-17T09:56:34+00:00",
			"voucher_status": "redeemed",
			"voucher_text": "ACME wallet voucher",
			"voucher_text_localised": "ACME puntenwallet voucher"

Spaaza can call an external webhook when a points or wallet amount is awarded or removed for a customer.

We can configure a webhook URL that you provide. Whenever the points-mutation event occurs we send a simple POST request to the URL. The body of the POST is JSON that includes details of the event and the points award or removal that triggered it. So that you can verify that the POST really originates from Spaaza we provide a signature in a request header (X-Spaaza-Hmac-SHA256).

The value of the header is a base 64 encoded HMAC-SHA256 of the whole body of the request with a shared secret that we would provide. Your code to handle the event should recreate the signature using the shared secret and compare it to the value in the header.