---
title: "Events: customers, addresses and marketing opt-ins"
description: "When webhooks related to customer accounts, addresses and marketing opt-ins are sent, and what each of these deliveries contains."
url: https://www.ciklik.academy/en/webhooks/evenements-clients-adresses-optins/
lang: en
lastUpdated: 2026-10-09
---

# Events: customers, addresses and marketing opt-ins

> Box and PrestaShop
>
> This page applies to both box stores and PrestaShop stores.

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

| 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

| 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

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

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`

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

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

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

### What `changed` contains

Always an empty array.

### Cascading effects

None.

### Example

```json
{
    "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`

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

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

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

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.

> Careful with interpretation
>
> Only trigger a business action if a field you actually use has really changed: the event very often fires without any business change, on mere session or account security events. Do not store fields you do not understand: some of them are authentication elements internal to the customer, never useful on the merchant side, and their presence in `changed` may vary without notice.

### 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](https://www.ciklik.academy/en/webhooks/evenements-expeditions/).

### Example

```json
{
    "email": "claire.martin-dupont@example.com"
}
```

## `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

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

On address imports from a CSV file.

### What `changed` contains

Always an empty array.

### Cascading effects

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

### Example

```json
{
    "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`

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

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

### When it is not sent

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

### What `changed` contains

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

### 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)
```

### Example

```json
{
    "address": "27 avenue Jean Jaurès",
    "address1": "",
    "postcode": "69007"
}
```

## `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

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

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

Always an empty array.

### Cascading effects

None.

### Example

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

## `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

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

Nothing beyond these four cases.

### What `changed` contains

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

### Cascading effects

None.

### Example

```json
{
    "valid": false
}
```

> What does not exist
>
> There is no `deleted_address`, `deleted_user` or `deleted_optin`: these three keys are not supported and are not part of the list of available events. Do not enter them in your site’s **Webhooks** field: they would not produce any usable delivery. Deleting an address through the API does not trigger any delivery. Do not rely on a webhook to detect the deletion of a customer, an address or a marketing opt-in: query the API if you need to know.

## See also

[Understanding a webhook delivery](https://www.ciklik.academy/en/webhooks/comprendre-un-envoi-de-webhook/)

[Events: shipments](https://www.ciklik.academy/en/webhooks/evenements-expeditions/)

[Events: orders, transactions and invoices](https://www.ciklik.academy/en/webhooks/evenements-commandes-transactions-factures/)
