Skip to content

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.

FieldTypeNullableDescription
idintegernoInternal identifier.
emailstringnoCurrent e-mail address.
uuidstringnoPublic identifier (cus_...), to be preferred over id as a key.
refpstringnoReferral URL, built with your store’s domain.
has_active_subscriptionbooleannoRecomputed at each delivery, not at the time of the triggering event.
infoarray or nullyesInternal comments on the customer record.
FieldTypeNullableDescription
idintegernoAddress identifier.
user_idintegernoOwning customer.
addressstringnoFirst address line.
address1stringyesAdditional address line.
postcodestringnoPostal code.
citystringnoCity.
phonestringyesPhone number, normalised to international format when possible.
first_name, last_namestringnoRecipient’s name.
region_idintegernoInternal region.
division, division_namestringyesAdministrative subdivision, depending on the country.
deletablebooleannoPermission check computed at delivery time, not a stable state: do not store it.
company_namestringyesCompany name, for a business address.
countryobjectnoSee “Country object”, always present.
external_idintegeryesIdentifier coming from a historical import.

Always present in the address object, never null.

FieldTypeNullableDescription
idintegernoInternal identifier.
namestringnoCountry name.
alphaCodestringnoTwo-letter ISO code (FR).

Four fields, with no identifier: the functional key is the pair made of the e-mail address and the store.

FieldTypeNullableDescription
emailstringnoSubscribed e-mail address.
tenant_idintegernoIdentifier of your store.
validbooleannoTrue if active, false if unsubscribed or rejected.
list_idstringyesMarketing list at your e-mail delivery provider.

Object sent: full customer. Delay before delivery: none. Full example: in the OpenAPI contract (/openapi/ciklik-webhooks.yaml), webhook created_user.

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).

On technical creations with no identified merchant: account created by the internal subscription webhook, or by an internal permission-granting action.

Always an empty array.

None.

created_user
{
"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": []
}

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.

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.

On a few silent writes: setting the referrer right after sign-up, importing customers from a CSV file, updating a historical import identifier.

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.

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.

changed of updated_user
{
"email": "claire.martin-dupont@example.com"
}

Object sent: full address. Delay before delivery: none. Full example: in the OpenAPI contract (/openapi/ciklik-webhooks.yaml), webhook created_address.

On every actual address creation: added by the customer or by your team (creation through the vendors API is not currently functional).

On address imports from a CSV file.

Always an empty array.

None. A newly created address is not linked to any subscription yet.

created_address
{
"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": []
}

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).

On every change to an address field: street, postal code, city, phone number, recipient’s name.

Nothing special to report here: any actual write on the address triggers the event.

The fields actually modified by the caller, with their new value.

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.

changed of updated_address
{
"address": "27 avenue Jean Jaurès",
"address1": "",
"postcode": "69007"
}

Object sent: full marketing opt-in. Delay before delivery: 10 seconds. Full example: in the OpenAPI contract (/openapi/ciklik-webhooks.yaml), webhook created_optin.

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.

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.

Always an empty array.

None.

created_optin
{
"email": "claire.martin@example.com",
"tenant_id": 1,
"valid": true,
"list_id": "9f2c4e7a1b",
"changed": []
}

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).

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.

Nothing beyond these four cases.

Most often valid, alone or together with list_id when the list changes.

None.

changed of updated_optin
{
"valid": false
}