> ## Documentation Index
> Fetch the complete documentation index at: https://developer.voyado.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Webhook use cases

Here are some examples of working with webhooks in Engage.

<Warning>
  A complete list of events and the most updated payload specification can be found in the client's Svix portal.
</Warning>

## 1 - Contact preferences & consents

**Preferences** are a contact's communication channel opt-ins — the acceptsEmail, acceptsPostal, and acceptsSms boolean flags that define how a contact wants to be contacted.

**Consents** are formal agreements a contact makes regarding their data or account (e.g., "Do you agree to receive our newsletter?" or membership terms). Once set, a consent can never revert to "Not set."

The three contact preferences in use in Engage are:

* acceptsEmail
* acceptsSms
* acceptsPostal

Other data regarding a contacts legal settings can be encoded as consent values in Engage. These are handled for every contact as custom fields on a per brand/client level.

To get all consents for your Engage environment use the following endpoint:

```http theme={null}
GET /api/v3/consents
```

As a retailer, you will often need to show the preferences, and sometimes the consent values, for a contact. For example on **My Pages** or at the checkout. And you will need to be sure the values shown are correct.

Since Engage often is the master of these settings, the preferences and consents will either have to be fetched every time they are needed, or you'll need some system in place to **constantly poll Engage** for the current values.

Neither way is efficient. This is why webhooks are a good solution.

### Webhook solution

For this situation, you create a webhook for the systems you want to keep updated about contact preference changes to your contacts in Engage. Then, whenever a preference is changed in Engage, the webhook will be used to inform all the subscribed external systems, keeping them all in sync with Engage.

The webhooks available for syncing of contact preferences are:

<AccordionGroup>
  <Accordion title="contact.acceptsEmail.changed">
    Triggered whenever the `acceptsEmail` preference changes
  </Accordion>

  <Accordion title="contact.acceptsSms.changed">
    Triggered whenever the `acceptsSms` preference changes
  </Accordion>

  <Accordion title="contact.acceptsPostal.changed">
    Triggered whenever the `acceptsPostal` preference changes
  </Accordion>
</AccordionGroup>

Engage also supports a dedicated webhook for changes in consent-typed fields:

<Accordion title="contact.consent.changed">
  Triggered whenever a consent value for a contact is changed

  ```json Payload structure theme={null}
  {
    "eventId": "ac01d383-b83f-45b1-a60b-275bc7bba6b2",
    "eventType": "contact.consent.changed",
    "isEncrypted": false,
    "payload": {
      "consentAlias": "myConsentAlias",
      "consentValue": true,
      "contactId": "e5f70fe1-a0cf-4d16-898e-b3d800ff4103",
      "dateChanged": "2026-01-20T16:28:38.985631+01:00"
    },
    "tenant": "myTenantName"
  }
  ```
</Accordion>

<Warning>
  The webhooks for contact preferences and consents are only triggered for *already existing contacts*. They will not be triggered when a contact is created.
</Warning>

Be aware of the [legal requirements](/docs/webhooks/webhooks#legal-requirements) when working with webhooks.

## 2 - Contact changes

Many retailers operate several systems that need access to up-to-date customer data, such as e-commerce, POS, CRM, customer service, or data platforms. If Engage is used as the source of truth for your customer data, contact webhooks can be used to keep those systems synchronized in your system whenever this data changes.

The webhooks available for changes to contact data are:

<AccordionGroup>
  <Accordion title="contact.created">
    Triggered when a contact is created in Engage.

    ```json Payload structure theme={null}
    {
      "eventId": "4ff4d68b-d299-4a17-81cc-e81abbf8932f",
      "eventType": "contact.created",
      "isEncrypted": true,
      "payload": {
        "careOf": "c/o John Smith",
        "city": "Stockholm",
        "contactId": "515c1b2a-7124-4bb9-826b-aedbbe5da8c4",
        "contactTypeId": "Member",
        "countryCode": "SE",
        "creationTime": "2024-03-15T10:30:15Z",
        "customAttributes": {
          "myCustomAttribute": "myCustomAttributeValue"
        },
        "dateOfBirth": "2004-02-17",
        "email": "john.doe@example.com",
        "externalId": "CRM-12345",
        "firstName": "John",
        "gender": "male",
        "language": "sv",
        "lastName": "Doe",
        "marketingGroupId": "ce62abff-aeb5-45b1-90f0-909194f33c29",
        "memberNumber": "1234567",
        "mobilePhone": "+46701234567",
        "postalCode": "11122",
        "registrationByStoreId": "560d70fe-7a47-43af-87d4-875afe4f8cc3",
        "registrationDate": "2024-03-15T10:30:00Z",
        "registrationSourceType": "API",
        "registrationSpecificSource": "newsletter-signup",
        "street": "Storgatan 1",
        "swedishFinnishPersonalIdentityNumber": "20040217-7935"
      },
      "tenant": "myTenantName"
    }
    ```
  </Accordion>

  <Accordion title="contact.updated">
    Triggered when a contact is updated in Engage.

    ```json Payload structure theme={null}
    {
      "eventId": "4ff4d68b-d299-4a17-81cc-e81abbf8932f",
      "eventType": "contact.updated",
      "isEncrypted": true,
      "payload": {
        "careOf": "c/o John Smith",
        "changedValues": [
          {
            "path": "Email",
            "previousValue": "previousEmail@email.com",
            "value": "myNewEmail@email.com"
          }
        ],
        "city": "Stockholm",
        "contactId": "515c1b2a-7124-4bb9-826b-aedbbe5da8c4",
        "contactTypeId": "Member",
        "countryCode": "SE",
        "creationTime": "2024-03-15T10:30:15Z",
        "customAttributes": {
          "myCustomAttribute": "myCustomAttributeValue"
        },
        "dateOfBirth": "2004-02-17",
        "email": "john.doe@example.com",
        "externalId": "CRM-12345",
        "firstName": "John",
        "gender": "male",
        "language": "sv",
        "lastName": "Doe",
        "marketingGroupId": "ce62abff-aeb5-45b1-90f0-909194f33c29",
        "memberNumber": "1234567",
        "mobilePhone": "+46701234567",
        "postalCode": "11122",
        "registrationByStoreId": "560d70fe-7a47-43af-87d4-875afe4f8cc3",
        "registrationDate": "2024-03-15T10:30:00Z",
        "registrationSourceType": "API",
        "registrationSpecificSource": "newsletter-signup",
        "street": "Storgatan 1",
        "swedishFinnishPersonalIdentityNumber": "20040217-7935",
        "updatedViaSourceType": "API",
        "updatedWithSpecificSource": "myEcom"
      },
      "tenant": "myTenantName"
    }
    ```
  </Accordion>

  <Accordion title="contact.deleted">
    Triggered when a contact is deleted in Engage.

    ```json Payload structure theme={null}
    {
      "eventId": "6a21bf40-56c1-49cf-ae6e-53b987ff2da4",
      "eventType": "contact.deleted",
      "isEncrypted": true,
      "payload": {
        "contactId": "d3bdcad4-3f90-46ce-be4c-b3d800dc7979",
        "deletionReason": "cancelled membership"
      },
      "tenant": "myTenantName"
    }
    ```
  </Accordion>
</AccordionGroup>

A typical use case for these webhooks is to create, update, or remove customer records in downstream systems whenever the customer profile changes in Engage.

<Tip>
  The `contact.updated` event includes delta tracking through changedValues, which helps the system receiving the data to understand what has changed without having to infer it from the full payload.
</Tip>

## 3 - Loyalty

There are three webhooks available for syncing of points and vouchers in Engage:

<AccordionGroup>
  <Accordion title="loyalty.addPoints">
    Triggered when points are added to a contact via the Engage UI or through an automation. The transaction is sent in the webhook.

    <Warning>
      This is *only* for customers using the point follower solution.
    </Warning>

    ```json Payload structure theme={null}
    {
      "eventType": String,
      "id": String,
      "isEncrypted": Boolean,
      "payload": : {
        "amount": Decimal,
        "contactId": String,
        "pointDefinitionId": Int,
        "source": String,
        "description": String,
        "userId": String,
        "userName": String,
        "reason": String,
        "sourceId": String,
      },
      "tenant": String
    }
    ```
  </Accordion>

  <Accordion title="point.balance.updated">
    Triggered whenever a contact's point balance is changed.

    ```json Payload structure theme={null}
    {
      "eventType": String,
      "id": String,
      "isEncrypted": Boolean,
      "payload": : {
        "balance": Decimal,
        "contactId": String,
        "accountId": Int,
        "definitionId": String,
        "balanceExpires": DateTimeOffset
      },
      "tenant": String
    }
    ```
  </Accordion>

  <Accordion title="reward.voucher.created">
    Triggered when a new reward voucher is created for a contact.

    ```json Payload structure theme={null}
    {
      "eventId": String,
      "eventType": String,
      "isEncrypted": Boolean,
      "payload": {
        "Amount": Decimal,
        "ContactId": String,
        "Currency": String,
        "Id": String,
        "UniqueCode": String,
        "ValidFrom": DateTimeOffset,
        "ValidTo": DateTimeOffset
      },
      "tenant": String
    }
    ```
  </Accordion>

  <Accordion title="promotion.multichannel.assigned">
    In some retail setups, it is Engage that decides if a customer has been assigned a promotion while another system is responsible for making that benefit available in checkout, e-commerce, or POS.

    The multichannel promotion assignment webhook can be used to notify external systems when a promotion has been assigned, so they can create or expose the corresponding coupon or voucher.

    This supports event-driven orchestration across channels and helps external systems react immediately when a promotion is assigned in Engage. The event is intended to be triggered regardless of where the assignment originated, the UI, an automation activity, or by API.
  </Accordion>
</AccordionGroup>
