Events: customers, addresses and marketing opt-ins
This page describes the six keys related to the customer account, addresses and subscription to your marketing lists. Two points to read before writing any code: the customer event fires far more often than you would expect, and an address change always triggers a cascade towards shipments and orders, even when the change has nothing to do with delivery.
Customer object
Section titled “Customer object”| Field | Type | Nullable | Description |
|---|---|---|---|
id | integer | no | Internal identifier. |
email | string | no | Current e-mail address. |
uuid | string | no | Public identifier (cus_...), to be preferred over id as a key. |
refp | string | no | Referral URL, built with your store’s domain. |
has_active_subscription | boolean | no | Recomputed at each delivery, not at the time of the triggering event. |
info | array or null | yes | Internal comments on the customer record. |
Address object
Section titled “Address object”| Field | Type | Nullable | Description |
|---|---|---|---|
id | integer | no | Address identifier. |
user_id | integer | no | Owning customer. |
address | string | no | First address line. |
address1 | string | yes | Additional address line. |
postcode | string | no | Postal code. |
city | string | no | City. |
phone | string | yes | Phone number, normalised to international format when possible. |
first_name, last_name | string | no | Recipient’s name. |
region_id | integer | no | Internal region. |
division, division_name | string | yes | Administrative subdivision, depending on the country. |
deletable | boolean | no | Permission check computed at delivery time, not a stable state: do not store it. |
company_name | string | yes | Company name, for a business address. |
country | object | no | See “Country object”, always present. |
external_id | integer | yes | Identifier coming from a historical import. |
Country object
Section titled “Country object”Always present in the address object, never null.
| Field | Type | Nullable | Description |
|---|---|---|---|
id | integer | no | Internal identifier. |
name | string | no | Country name. |
alphaCode | string | no | Two-letter ISO code (FR). |
Marketing opt-in object
Section titled “Marketing opt-in object”Four fields, with no identifier: the functional key is the pair made of the e-mail address and the store.
| Field | Type | Nullable | Description |
|---|---|---|---|
email | string | no | Subscribed e-mail address. |
tenant_id | integer | no | Identifier of your store. |
valid | boolean | no | True if active, false if unsubscribed or rejected. |
list_id | string | yes | Marketing list at your e-mail delivery provider. |
created_user
Section titled “created_user”Object sent: full customer. Delay before delivery: none. Full example: in the OpenAPI contract (/openapi/ciklik-webhooks.yaml), webhook created_user.
When it is sent
Section titled “When it is sent”On every actual account creation: sign-up on your store, creation through the API (POST /customers), checkout, and validation of a PrestaShop cart (the customer is created at that moment if it did not exist yet).
When it is not sent
Section titled “When it is not sent”On technical creations with no identified merchant: account created by the internal subscription webhook, or by an internal permission-granting action.
What changed contains
Section titled “What changed contains”Always an empty array.
Cascading effects
Section titled “Cascading effects”None.
Example
Section titled “Example”{ "id": 1, "email": "claire.martin@example.com", "uuid": "cus_Qx7hR3eaEowcv1DX", "refp": "https://boutique.example.com/formules?refp=CLAIRE2026", "has_active_subscription": false, "info": null, "changed": []}updated_user
Section titled “updated_user”Object sent: full customer, with up-to-date values. Delay before delivery: none. Full example: in the OpenAPI contract (/openapi/ciklik-webhooks.yaml), webhook updated_user (the rest of the payload is identical to the one of created_user).
This is the sensitive point of this page.
When it is sent
Section titled “When it is sent”On any business change (e-mail, account information), but also on purely technical events related to the session or to account security, without any business data having changed: a login with “remember me”, a simple logout, enabling or disabling two-factor authentication, a password reset.
When it is not sent
Section titled “When it is not sent”On a few silent writes: setting the referrer right after sign-up, importing customers from a CSV file, updating a historical import identifier.
What changed contains
Section titled “What changed contains”The fields that actually changed, as raw values as stored in the database. Some of them are internal authentication or session elements, with no business relevance.
Cascading effects
Section titled “Cascading effects”An e-mail address change produces, in addition to the updated_user, one updated_shippingbox per shipment scheduled since the first day of the month before last (M-2, for example July 1st for a shipment in September). A customer whose e-mail changes and who has 12 shipments in that window triggers 1 updated_user then 12 updated_shippingbox, each with the up-to-date e-mail in changed. See Events: shipments.
Example
Section titled “Example”{ "email": "claire.martin-dupont@example.com"}created_address
Section titled “created_address”Object sent: full address. Delay before delivery: none. Full example: in the OpenAPI contract (/openapi/ciklik-webhooks.yaml), webhook created_address.
When it is sent
Section titled “When it is sent”On every actual address creation: added by the customer or by your team (creation through the vendors API is not currently functional).
When it is not sent
Section titled “When it is not sent”On address imports from a CSV file.
What changed contains
Section titled “What changed contains”Always an empty array.
Cascading effects
Section titled “Cascading effects”None. A newly created address is not linked to any subscription yet.
Example
Section titled “Example”{ "id": 1, "user_id": 1, "address": "12 rue des Lilas", "address1": "Bâtiment B, 3e étage", "postcode": "69003", "city": "Lyon", "phone": "+33612345678", "first_name": "Claire", "last_name": "Martin", "region_id": 1, "division": null, "division_name": null, "deletable": false, "company_name": null, "country": { "id": 1, "name": "France", "alphaCode": "FR" }, "external_id": 4821, "changed": []}updated_address
Section titled “updated_address”Object sent: full address, with up-to-date values. Delay before delivery: none. Full example: in the OpenAPI contract (/openapi/ciklik-webhooks.yaml), webhook updated_address (the rest of the payload is identical to the one of created_address).
When it is sent
Section titled “When it is sent”On every change to an address field: street, postal code, city, phone number, recipient’s name.
When it is not sent
Section titled “When it is not sent”Nothing special to report here: any actual write on the address triggers the event.
What changed contains
Section titled “What changed contains”The fields actually modified by the caller, with their new value.
Cascading effects
Section titled “Cascading effects”updated_address systematically triggers the cascade towards shipments and orders, whatever the modified field, including fields unrelated to delivery: the code does not check which field changed, it reacts to any save of the address. For each subscription linked to this address: one updated_shippingbox per shipment scheduled since the first day of the month before last (M-2), then one or two updated_checkoutorder per order currently being created. An address linked to several subscriptions multiplies the cascade accordingly.
updated_address -> for each linked subscription -> updated_shippingbox (one per shipment since M-2) -> updated_checkoutorder (one or two per order being created)Placeholder for the cascade-adresse.svg diagram (public/doc-resources/images/webhooks/), reusable for the e-mail change cascade above.
Example
Section titled “Example”{ "address": "27 avenue Jean Jaurès", "address1": "", "postcode": "69007"}created_optin
Section titled “created_optin”Object sent: full marketing opt-in. Delay before delivery: 10 seconds. Full example: in the OpenAPI contract (/openapi/ciklik-webhooks.yaml), webhook created_optin.
When it is sent
Section titled “When it is sent”Only on the very first subscription of an e-mail and store pair: at sign-up, or when a subscription is created, cancelled or reactivated while that pair has no opt-in yet.
When it is not sent
Section titled “When it is not sent”Any later re-subscription of the same pair is not a new created_optin: it is an updated_optin, since the opt-in already exists.
What changed contains
Section titled “What changed contains”Always an empty array.
Cascading effects
Section titled “Cascading effects”None.
Example
Section titled “Example”{ "email": "claire.martin@example.com", "tenant_id": 1, "valid": true, "list_id": "9f2c4e7a1b", "changed": []}updated_optin
Section titled “updated_optin”Object sent: full marketing opt-in, with up-to-date values. Delay before delivery: none. Full example: in the OpenAPI contract (/openapi/ciklik-webhooks.yaml), webhook updated_optin (the rest of the payload is identical to the one of created_optin).
When it is sent
Section titled “When it is sent”On four events: a re-subscription of an already known pair, a voluntary unsubscription (valid switches to false), a permanent rejection by your e-mail delivery provider (a “hard bounce” observed during a subscription attempt), and a bulk unsubscription performed by your team. The latter produces one updated_optin per opt-in in the batch, not a single global event.
When it is not sent
Section titled “When it is not sent”Nothing beyond these four cases.
What changed contains
Section titled “What changed contains”Most often valid, alone or together with list_id when the list changes.
Cascading effects
Section titled “Cascading effects”None.
Example
Section titled “Example”{ "valid": false}