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

# Abonnés

> Inscrire, tenir à jour, étiqueter et désabonner depuis votre application.

Le cas typique : votre boutique inscrit ses clients à la liste « Clients », pose des tags selon ce qu'ils achètent, et répercute les désabonnements.

<Note>
  Tous les exemples utilisent `$LEKALAO_TOKEN` (jeton **Lecture et
  écriture**) et `$LIST`, l'`id` de la liste. L'`id` d'une liste est dans `GET
        /api/v1/lists`.
</Note>

## Inscrire une personne

```bash theme={null}
curl -X POST https://lekalao.example.com/api/v1/lists/$LIST/subscribers \
  -H "Authorization: Bearer $LEKALAO_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "email": "ada@example.com",
    "first_name": "Ada",
    "last_name": "Lovelace",
    "locale": "fr",
    "timezone": "Africa/Douala",
    "attributes": { "ville": "Douala", "client_depuis": "2024-03-01" },
    "tags": ["client", "pain-complet"]
  }'
```

Réponse `201` :

```json theme={null}
{
    "data": {
        "id": "5f0e7c1b-2d4a-4e8f-b1c3-9a7d6e5f4b3a",
        "email": "ada@example.com",
        "first_name": "Ada",
        "last_name": "Lovelace",
        "timezone": "Africa/Douala",
        "locale": "fr",
        "status": "unconfirmed",
        "tags": ["client", "pain-complet"],
        "attributes": { "ville": "Douala", "client_depuis": "2024-03-01" },
        "subscribed_at": null,
        "unsubscribed_at": null,
        "created_at": "2026-09-17T10:02:11+00:00"
    }
}
```

**Gardez l'`id`** dans votre base : c'est lui qui désigne la personne dans les appels suivants.

### Ce qui se passe selon les cas

| Cas                                        | Résultat                                                                                             |
| ------------------------------------------ | ---------------------------------------------------------------------------------------------------- |
| Nouvelle adresse, liste sans double opt-in | `status: subscribed`. Les automatisations d'inscription démarrent.                                   |
| Nouvelle adresse, liste en double opt-in   | `status: unconfirmed`, e-mail de confirmation envoyé.                                                |
| Idem avec `"skip_confirmation": true`      | `status: subscribed` directement.                                                                    |
| Adresse déjà abonnée                       | Mise à jour. Les champs vides ne remplacent rien, les attributs sont fusionnés, les tags s'ajoutent. |
| Adresse désabonnée                         | **Réabonnée**, avec confirmation si la liste l'exige.                                                |
| Adresse dans la liste de suppression       | `422` « This address is blocked. »                                                                   |
| Limite d'abonnés de la formule atteinte    | `422` avec le message de la formule.                                                                 |

<Warning>
  `skip_confirmation` et la réinscription des désabonnés engagent votre
  responsabilité. N'inscrivez directement que des personnes dont vous avez le
  consentement, et ne renvoyez pas à Lekalao quelqu'un qui s'est désabonné :
  écoutez le webhook `subscriber.unsubscribed` pour mettre votre base à jour.
</Warning>

Les adresses sont enregistrées en minuscules, sans espaces autour.

## Inscrire en lot

Jusqu'à 1 000 personnes en un appel, par exemple pour une synchronisation nocturne :

```bash theme={null}
curl -X POST https://lekalao.example.com/api/v1/lists/$LIST/subscribers/batch \
  -H "Authorization: Bearer $LEKALAO_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "subscribers": [
      { "email": "ada@example.com", "first_name": "Ada", "tags": ["client"] },
      { "email": "grace@example.com", "first_name": "Grace", "attributes": { "ville": "Yaoundé" } }
    ],
    "skip_confirmation": false,
    "replace_tags": false
  }'
```

**Jusqu'à 100 lignes**, la réponse arrive tout de suite, ligne par ligne :

```json theme={null}
{
    "data": [
        {
            "index": 0,
            "email": "ada@example.com",
            "id": "5f0e…",
            "outcome": "already_subscribed"
        },
        {
            "index": 1,
            "email": "grace@example.com",
            "id": "8b2d…",
            "outcome": "pending"
        }
    ],
    "meta": { "added": 1, "updated": 1, "failed": 0 }
}
```

| `outcome`            | Signification                                                           |
| -------------------- | ----------------------------------------------------------------------- |
| `subscribed`         | Inscrite.                                                               |
| `pending`            | En attente de confirmation.                                             |
| `already_subscribed` | Déjà là ; fiche mise à jour.                                            |
| `failed`             | Refusée (adresse bloquée, formule pleine). Le motif est dans `message`. |

Une ligne refusée ne fait pas échouer les autres. Si **toutes** échouent, le code est `422`.

**Au-delà de 100 lignes**, le lot part en arrière-plan comme un import. La réponse est `202` avec l'import à suivre :

```json theme={null}
{
    "data": {
        "id": "c41a…",
        "status": "pending",
        "file_name": "API batch of 850",
        "url": "https://lekalao.example.com/api/v1/imports/c41a…"
    },
    "meta": { "queued": 850 }
}
```

Interrogez `GET /api/v1/imports/{id}` jusqu'à `status: completed` ou `failed`. Les compteurs `added`, `updated`, `failed` et le détail des `errors` y sont.

`replace_tags: true` remplace les tags de chaque personne par ceux de sa ligne, au lieu de les ajouter.

## Importer un fichier

Pour un fichier CSV ou Excel déjà prêt, envoyez-le tel quel :

```bash theme={null}
curl -X POST https://lekalao.example.com/api/v1/lists/$LIST/imports \
  -H "Authorization: Bearer $LEKALAO_TOKEN" \
  -H "Accept: application/json" \
  -F "file=@clients.csv" \
  -F "tags[]=import-septembre" \
  -F "mapping[E-mail]=email" \
  -F "mapping[Prénom]=first_name" \
  -F "mapping[Ville]=attribute:ville"
```

Sans `mapping`, les colonnes sont reconnues d'après leur titre. Les personnes importées sont inscrites **sans e-mail de confirmation**, et les désabonnés ne sont réinscrits que si `resubscribe_unsubscribed` vaut `true`. Voir [Import et export](/fr/contacts/import-export).

## Retrouver quelqu'un

```bash theme={null}
# Par adresse
curl "https://lekalao.example.com/api/v1/lists/$LIST/subscribers?email=ada@example.com" \
  -H "Authorization: Bearer $LEKALAO_TOKEN" -H "Accept: application/json"

# Les nouveaux abonnés depuis hier, par tag
curl "https://lekalao.example.com/api/v1/lists/$LIST/subscribers?status=subscribed&tag=client&since=2026-09-16" \
  -H "Authorization: Bearer $LEKALAO_TOKEN" -H "Accept: application/json"
```

| Filtre              | Valeurs                                                    |
| ------------------- | ---------------------------------------------------------- |
| `status`            | `subscribed`, `unconfirmed`, `unsubscribed`                |
| `email`             | Une adresse exacte.                                        |
| `tag`               | Le nom d'un tag.                                           |
| `since`             | Créés depuis cette date.                                   |
| `sort`, `direction` | `email` ou l'ordre de création ; `asc` ou `desc` (défaut). |

`GET /api/v1/subscribers/{id}` lit une personne.

## Mettre à jour

```bash theme={null}
curl -X PUT https://lekalao.example.com/api/v1/subscribers/$SUBSCRIBER \
  -H "Authorization: Bearer $LEKALAO_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{ "first_name": "Ada", "locale": "en", "attributes": { "ville": "Kribi", "points": 120 } }'
```

* Un champ absent ou `null` ne change pas.
* `attributes`, s'il est envoyé, **remplace** tous les attributs.
* `tags`, s'il est envoyé, **remplace** tous les tags.

## Poser et retirer des tags

Pour ajouter ou retirer sans connaître les autres tags :

```bash theme={null}
curl -X POST https://lekalao.example.com/api/v1/subscribers/$SUBSCRIBER/tags \
  -H "Authorization: Bearer $LEKALAO_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{ "add": ["panier-abandonné"], "remove": ["a-commandé"] }'
```

Un tag qui n'existe pas encore sur la liste est créé. Poser un tag peut [démarrer une automatisation](/fr/automations/triggers).

Les tags de la liste se lisent avec `GET /api/v1/lists/{id}/tags` et se créent à l'avance avec `POST /api/v1/lists/{id}/tags`.

## Désabonner, réabonner, supprimer

| Appel                                        | Effet                                                                        |
| -------------------------------------------- | ---------------------------------------------------------------------------- |
| `POST /subscribers/{id}/unsubscribe`         | Désabonne. La personne reste dans la liste et dans les statistiques.         |
| `POST /subscribers/{id}/resubscribe`         | Réabonne **sans confirmation**. `422` si l'adresse est bloquée.              |
| `POST /subscribers/{id}/resend-confirmation` | Renvoie l'e-mail de confirmation. `422` si la personne n'est pas en attente. |
| `DELETE /subscribers/{id}`                   | Supprime la fiche. Préférez le désabonnement, qui garde l'historique.        |

## En PHP

```php theme={null}
use Illuminate\Support\Facades\Http;

$lekalao = Http::withToken(config('services.lekalao.token'))
    ->baseUrl('https://lekalao.example.com/api/v1')
    ->acceptJson()
    ->retry(3, 500, throw: false);

$response = $lekalao->post("lists/{$listUuid}/subscribers", [
    'email' => $customer->email,
    'first_name' => $customer->first_name,
    'locale' => $customer->locale,
    'tags' => ['client'],
]);

if ($response->successful()) {
    $customer->update(['lekalao_id' => $response->json('data.id')]);
}
```

## En JavaScript (Node)

```js theme={null}
const response = await fetch(
    `https://lekalao.example.com/api/v1/lists/${listUuid}/subscribers`,
    {
        method: 'POST',
        headers: {
            Authorization: `Bearer ${process.env.LEKALAO_TOKEN}`,
            'Content-Type': 'application/json',
            Accept: 'application/json',
        },
        body: JSON.stringify({
            email: 'ada@example.com',
            first_name: 'Ada',
            tags: ['client'],
        }),
    },
);

if (response.status === 422) {
    const { message, errors } = await response.json();
    console.warn(message, errors);
}
```
