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

# Votre premier e-mail transactionnel en 5 minutes

> Un jeton, un modèle, un appel : une confirmation de commande envoyée par votre application, et comment savoir qu’elle est partie.

D'un jeton d'API à un e-mail dans votre propre boîte : un modèle dans l'interface, un appel depuis votre code, une lecture pour le voir partir.

> [!TIP]
>
> Pas encore de fournisseur d'envoi ni de domaine vérifié ? Une [clé de
> test](https://docs.lekalao.com/fr/developers/sandbox.md) déroule chaque étape ci-dessous sans rien
> envoyer : écrivez à `delivered@sink.lekalao.dev` au lieu de votre propre
> adresse, et l'e-mail est journalisé, marqué `sent` et signalé délivré,
> webhooks compris.

## Avant de commencer

Les cinq minutes commencent quand ces trois conditions sont remplies. Les deux premières dépendent de votre fournisseur et de votre DNS, pas de Lekalao : elles peuvent prendre plus longtemps.

**1. Un fournisseur d'envoi qui envoie**

Lekalao n'envoie rien lui-même : il remet chaque e-mail à un fournisseur. **Paramètres → Fournisseurs d'envoi** liste ceux que votre équipe peut utiliser : les vôtres, et celui que le service partage avec toutes les équipes quand il en propose un. L'un d'eux doit être choisi pour les **E-mails transactionnels**, ou être le **Fournisseur par défaut**.

Si la liste est vide, **Ajouter un fournisseur d'envoi** (SES, Postmark, Mailgun, SendGrid, Brevo, Resend ou SMTP), puis **Envoyer un e-mail de test** : il prouve les identifiants. Voir [Fournisseurs d'envoi](https://docs.lekalao.com/fr/deliverability/mailers.md).

**2. Un expéditeur sur un domaine vérifié**

Sur le service Lekalao, l'adresse d'expédition doit être sur un domaine que votre équipe a ajouté et vérifié dans **Délivrabilité**. Sinon l'appel est refusé (`422`), et le message nomme le domaine. Les enregistrements DNS mettent de quelques minutes à quelques heures à être vus : commencez par là. Voir [Domaines d'envoi](https://docs.lekalao.com/fr/deliverability/domains.md).

Sur votre propre installation, cela ne s'applique que si son administrateur l'exige.

**3. Le bon rôle**

Créer un jeton demande le rôle **éditeur** ou **propriétaire** dans l'équipe.

## 1. Créez un jeton

**Paramètres → Jetons d'API → Nouveau jeton**. Donnez-lui un nom (« Boutique en ligne »), et sous **Ce qu'il peut faire**, choisissez **Lecture et écriture** : envoyer est une écriture, suivre l'e-mail une lecture. Activez **Clé de test** pour essayer sans envoyer. **Créer**, puis copiez le jeton : il ne sera plus affiché.

```bash theme={null}
export LEKALAO_TOKEN="12|kJ3v8mQ2xP9…"
```

Gardez-le sur votre serveur. Voir [Authentification](https://docs.lekalao.com/fr/developers/authentication.md).

## 2. Écrivez le modèle

**Transactionnel → Modèles transactionnels → Nouveau modèle**. Nommez-le `confirmation-commande`, gardez l'éditeur **HTML**, **Créer**. Puis, sur sa page :

* **Objet** : `Commande {{ order.number }} confirmée`

* le contenu :

  ```html theme={null}
  <p>Bonjour {{ customer.name }},</p>
  <p>Votre commande <strong>{{ order.number }}</strong> est confirmée.</p>
  ```

* **Adresse d'expédition** : une adresse de votre domaine vérifié. Vide, celle de l'équipe dans **Paramètres → Général** est utilisée.

**Enregistrer l'e-mail**. Le nom est ce que votre application envoie ; le reste peut changer sans toucher à votre code. Voir [Modèles transactionnels](https://docs.lekalao.com/fr/transactional/templates.md).

## 3. Envoyez-le

Mettez **votre propre adresse** dans `to`, pour voir l'e-mail arriver. Une adresse qui n'existe pas rebondit, et part dans votre liste de suppression.

```bash curl theme={null}
curl -X POST https://api.lekalao.com/v1/transactional-mails/send \
  -H "Authorization: Bearer $LEKALAO_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -H "Idempotency-Key: commande-2026-00481-confirmation" \
  -d '{
    "template": "confirmation-commande",
    "to": ["vous@votre-entreprise.example"],
    "variables": {
      "customer": { "name": "Ada" },
      "order": { "number": "2026-00481" }
    }
  }'
```

```javascript Node.js theme={null}
// Node 18 ou plus : fetch est intégré.
const response = await fetch('https://api.lekalao.com/v1/transactional-mails/send', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.LEKALAO_TOKEN}`,
    'Content-Type': 'application/json',
    Accept: 'application/json',
    'Idempotency-Key': 'commande-2026-00481-confirmation',
  },
  body: JSON.stringify({
    template: 'confirmation-commande',
    to: ['vous@votre-entreprise.example'],
    variables: { customer: { name: 'Ada' }, order: { number: '2026-00481' } },
  }),
});

console.log(response.status, await response.json());
```

```python Python theme={null}
# Python 3, bibliothèque standard seulement.
import json
import os
import urllib.error
import urllib.request

request = urllib.request.Request(
    'https://api.lekalao.com/v1/transactional-mails/send',
    method='POST',
    headers={
        'Authorization': f"Bearer {os.environ['LEKALAO_TOKEN']}",
        'Content-Type': 'application/json',
        'Accept': 'application/json',
        'Idempotency-Key': 'commande-2026-00481-confirmation',
    },
    data=json.dumps({
        'template': 'confirmation-commande',
        'to': ['vous@votre-entreprise.example'],
        'variables': {'customer': {'name': 'Ada'}, 'order': {'number': '2026-00481'}},
    }).encode(),
)

try:
    with urllib.request.urlopen(request, timeout=15) as response:
        print(response.status, json.load(response))
except urllib.error.HTTPError as error:  # les 4xx et 5xx arrivent ici
    print(error.code, json.load(error))
```

```php PHP theme={null}
<?php
// PHP 8, avec l'extension curl.
$curl = curl_init('https://api.lekalao.com/v1/transactional-mails/send');

curl_setopt_array($curl, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 15,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('LEKALAO_TOKEN'),
        'Content-Type: application/json',
        'Accept: application/json',
        'Idempotency-Key: commande-2026-00481-confirmation',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'template' => 'confirmation-commande',
        'to' => ['vous@votre-entreprise.example'],
        'variables' => ['customer' => ['name' => 'Ada'], 'order' => ['number' => '2026-00481']],
    ]),
]);

$body = json_decode(curl_exec($curl), true);

echo curl_getinfo($curl, CURLINFO_RESPONSE_CODE), ' ', json_encode($body), PHP_EOL;
```

Sur votre propre installation, l'adresse est `https://votre-domaine/api/v1/transactional-mails/send`.

L'`Idempotency-Key` rend l'appel sûr à répéter : envoyé deux fois, il envoie un seul e-mail. Donnez à chaque e-mail sa propre clé, par exemple le numéro de commande et l'action.

## 4. Lisez la réponse

La réponse arrive dès que Lekalao a écrit l'e-mail dans le journal : `202`, avec `status` à `pending`.

```json 202 Accepted theme={null}
{
    "data": {
        "id": "e3b0c442-98fc-4c14-9a1e-2f6b7d8a9c10",
        "template": "confirmation-commande",
        "subject": "Commande 2026-00481 confirmée",
        "from": "bonjour@votre-entreprise.example",
        "to": ["vous@votre-entreprise.example"],
        "cc": [],
        "bcc": [],
        "status": "pending",
        "sandbox": false,
        "failure_reason": null,
        "failure_code": null,
        "opens": 0,
        "clicks": 0,
        "sent_at": null,
        "delivered_at": null,
        "bounced_at": null,
        "complained_at": null,
        "created_at": "2026-10-31T10:14:02+00:00"
    }
}
```

`pending` n'est pas un problème : l'e-mail part d'une file d'attente un instant plus tard. Gardez son `id`.

## 5. Voyez-le partir

Lisez l'e-mail par son `id` :

```bash theme={null}
curl https://api.lekalao.com/v1/transactional-mails/e3b0c442-98fc-4c14-9a1e-2f6b7d8a9c10 \
  -H "Authorization: Bearer $LEKALAO_TOKEN" \
  -H "Accept: application/json"
```

| `status` | Signification |
| - | - |
| `pending` | Encore dans la file, ou en attente d'un nouvel essai. Relisez-le dans quelques secondes. |
| `sent` | Votre fournisseur l'a. Regardez dans votre boîte. |
| `failed` | Pas envoyé. `failure_code` dit pourquoi en un mot, `failure_reason` en une phrase. |

Quand le fournisseur échoue, Lekalao réessaie pendant six heures au plus avant d'abandonner. Dans votre application, laissez Lekalao vous prévenir plutôt que de demander : les [webhooks](https://docs.lekalao.com/fr/developers/transactional.md#le-suivre-par-les-webhooks) `transactional.*` disent quand l'e-mail est envoyé, délivré, a rebondi ou a échoué.

L'e-mail est aussi dans **Transactionnel**, le journal, avec son contenu et ses ouvertures. Voir [Journal](https://docs.lekalao.com/fr/transactional/log.md).

## Quand il n'arrive pas

| Vous voyez | Où regarder |
| - | - |
| `401` | Le jeton : copié en entier, après `Bearer `, et pas révoqué. |
| `403` | `code` dit lequel : `missing_ability` (un jeton **Lecture**), `role_not_allowed` (son propriétaire est devenu lecteur), `two_factor_required` (l'équipe demande un second facteur que son propriétaire n'a pas configuré), `team_suspended`. |
| `422` `sender_not_allowed` | L'expéditeur n'est pas sur un domaine vérifié : **Délivrabilité**. |
| `422` `validation_error`, `errors.template` | Aucun modèle de ce nom dans l'équipe. Le nom est exactement celui de **Modèles transactionnels**. |
| `422` `recipients_suppressed` | Journalisé, pas envoyé : l'adresse est dans la liste de suppression. |
| `429` `monthly_quota_exceeded` | Journalisé, pas envoyé : les e-mails du mois de la formule sont épuisés. |
| `502` | Journalisé, pas envoyé : la file d'attente n'a pas pu le prendre. Renvoyez-le avec la même `Idempotency-Key`. |
| `failed`, un peu plus tard | `failure_reason` porte la dernière erreur du fournisseur. Vérifiez le fournisseur avec **Envoyer un e-mail de test**. |
| `pending` pendant des minutes | Le fournisseur est réessayé, ou la limite de débit du fournisseur retient l'e-mail. Sur votre propre installation, **Paramètres → Maintenance** montre si les workers tournent. |
| `sent`, et rien dans la boîte | Le dossier spam d'abord, puis les enregistrements du domaine. Voir [Dépannage](https://docs.lekalao.com/fr/help/troubleshooting.md#les-e-mails-arrivent-en-spam). |

## Ensuite

> [card] [Tout sur l'envoi](https://docs.lekalao.com/fr/developers/transactional.md)
>
> Sans modèle, pièces jointes, langues, nouveaux essais et renvois.

> [card] [Webhooks](https://docs.lekalao.com/fr/developers/webhooks.md)
>
> Envoyé, délivré, rebondi, ouvert : la vie de chaque e-mail, signée, dans votre application.

> [card] [Depuis Laravel](https://docs.lekalao.com/fr/developers/laravel-transport.md)
>
> Gardez `Mail::to()->send()`, et envoyez par Lekalao.

> [card] [Erreurs](https://docs.lekalao.com/fr/errors.md)
>
> Chaque code, et quand réessayer.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.