Webhooks
Event Reference

Event Reference

All payloads follow the standard envelope. The data field is documented for each event below.


stamp.earned

Fired when a customer earns stamps from a purchase.

{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "event": "stamp.earned",
  "occurred_at": "2026-04-19T14:30:00Z",
  "organization": "kahveci-mehmet",
  "data": {
    "customer_code": 482193,
    "customer_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "stamps_added": 2,
    "stamp_balance": 7,
    "max_stamps": 10,
    "source": "webhook",
    "transaction_id": "7c9e6679-7bd5-4b1a-9e10-5a9b3e4d6f2c",
    "amount": 85.50
  }
}
FieldTypeDescription
customer_codeint6-digit customer identifier
customer_idUUIDCustomer's internal ID
stamps_addedintNumber of stamps added in this transaction
stamp_balanceintCustomer's total stamp balance after this event
max_stampsintStamps required to fill the card (earn a reward)
sourcestringTransaction source: "webhook" (POS API), "manual" (merchant app)
transaction_idUUIDInternal transaction ID
amountfloatPurchase amount (present when a monetary amount was passed; omitted otherwise)

stamp.redeemed

Fired when a customer's stamp card fills and a reward coupon is issued. This fires during an earn call — not when the customer redeems a coupon at the counter.

stamp.redeemed fires in the same earn transaction that completes the stamp card. It means a coupon was created and is ready to use. See coupon.redeemed for when the customer actually uses the coupon.

{
  "id": "...",
  "event": "stamp.redeemed",
  "occurred_at": "2026-04-19T15:00:00Z",
  "organization": "kahveci-mehmet",
  "data": {
    "customer_code": 482193,
    "customer_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "stamps_added": 1,
    "coupon_id": "e3b0c442-98fc-1c14-9afb-f4c8996fb924",
    "coupon_name": "Free Coffee",
    "transaction_id": "7c9e6679-7bd5-4b1a-9e10-5a9b3e4d6f2c"
  }
}
FieldTypeDescription
customer_codeint6-digit customer identifier
customer_idUUIDCustomer's internal ID
stamps_addedintStamps added in the earn call that triggered the card fill
coupon_idUUIDThe newly issued reward coupon
coupon_namestringReward coupon name as configured by the merchant
transaction_idUUIDInternal transaction ID of the earn call

points.earned

Fired when a customer earns loyalty points.

{
  "id": "...",
  "event": "points.earned",
  "occurred_at": "2026-04-19T14:30:00Z",
  "organization": "my-store",
  "data": {
    "customer_code": 391047,
    "customer_id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
    "points_added": 125,
    "point_balance": 870,
    "source": "webhook",
    "transaction_id": "9a1b2c3d-4e5f-6a7b-8c9d-0e1f2a3b4c5d",
    "amount": 85.50
  }
}
FieldTypeDescription
customer_codeint6-digit customer identifier
customer_idUUIDCustomer's internal ID
points_addedintPoints earned in this transaction
point_balanceintTotal point balance after this event
sourcestringTransaction source: "webhook" (POS API), "manual" (merchant app)
transaction_idUUIDInternal transaction ID
amountfloatPurchase amount (present when a monetary amount was passed; omitted otherwise)

points.spent

Fired when a customer spends loyalty points.

{
  "id": "...",
  "event": "points.spent",
  "occurred_at": "2026-04-19T16:00:00Z",
  "organization": "my-store",
  "data": {
    "customer_code": 391047,
    "customer_id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
    "points_spent": 500,
    "points_earned": 0,
    "point_balance": 370,
    "remaining_amount": 34.50,
    "amount": 85.50,
    "transaction_id": "1a2b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d"
  }
}
FieldTypeDescription
customer_codeint6-digit customer identifier
customer_idUUIDCustomer's internal ID
points_spentintPoints deducted in this transaction
points_earnedintPoints awarded in the same transaction (usually 0 on a pure redemption)
point_balanceintRemaining point balance after this event
remaining_amountfloatPurchase amount not covered by the redeemed points
amountfloatTotal transaction amount
transaction_idUUIDInternal transaction ID

coupon.redeemed

Fired when a customer's coupon is scanned and marked as used — i.e. the customer presents the reward coupon at the counter and the merchant scans it.

Don't confuse this with stamp.redeemed. stamp.redeemed fires when the stamp card fills and a coupon is created. coupon.redeemed fires when that coupon is later used at the counter.

{
  "id": "...",
  "event": "coupon.redeemed",
  "occurred_at": "2026-04-19T17:00:00Z",
  "organization": "kahveci-mehmet",
  "data": {
    "customer_code": 482193,
    "customer_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "coupon_id": "c3d4e5f6-7a8b-9c0d-1e2f-3a4b5c6d7e8f",
    "coupon_name": "Free Coffee",
    "redeemed_at": "2026-04-19T17:00:00Z"
  }
}
FieldTypeDescription
customer_codeint6-digit customer identifier
customer_idUUIDCustomer's internal ID
coupon_idUUIDCoupon's internal ID
coupon_namestringCoupon name as configured by the merchant
redeemed_atISO 8601Timestamp when the coupon was used

customer.enrolled

Fired when a new customer joins the loyalty program. This fires only when a customer is created for the first time (is_new: true) — it does not fire when an existing customer is looked up via the enroll endpoint.

{
  "id": "...",
  "event": "customer.enrolled",
  "occurred_at": "2026-04-19T10:00:00Z",
  "organization": "kahveci-mehmet",
  "data": {
    "customer_code": 482193,
    "customer_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "masked_email": "j***@gmail.com",
    "enrolled_at": "2026-04-19T10:00:00Z"
  }
}
FieldTypeDescription
customer_codeint6-digit customer identifier
customer_idUUIDCustomer's internal ID
masked_emailstringMasked email address (j***@gmail.com) — full email is never exposed
enrolled_atISO 8601Registration timestamp

Privacy: The full customer email is never included in webhook payloads. Only the masked form is sent.