# Premier envoi depuis Node.js

À la fin de cette page, un e-mail sera parti depuis ton script Node.js, et tu le verras dans **E-mails**.

## Avant de commencer

- Un **domaine vérifié** dans ton espace, avec le statut **Prêt**. Sans lui, l’API refuse l’expéditeur. Voir [Ajouter un domaine](/docs/guides/ajouter-un-domaine/).
- Une **clé d’API**, créée dans **Clés d’API**. Elle commence par `am_`. Copie-la tout de suite : elle n’est plus jamais affichée.

1. **Récupère le client**

   Le client est un seul fichier, sans dépendance. Il fonctionne avec Node, Bun, Deno et les environnements edge. [Ouvre-le](https://mail.hgdc.ch/sdk/agentmail.ts), copie tout son contenu dans ton projet, par exemple dans `src/lib/agentmail.ts`.

   Tu peux aussi appeler l’API directement avec `fetch`. Les deux formes sont décrites dans [Envoyer depuis ton logiciel](/docs/guides/envoyer-depuis-ton-logiciel/).

2. **Mets la clé dans \`.env\`**

   Dans le fichier `.env` à la racine de ton projet :

   ```text
   AGENTMAIL_API_KEY=am_…
   ```

   Ajoute `.env` à ton `.gitignore` si ce n’est pas déjà fait. Le client lit `AGENTMAIL_API_KEY` tout seul. Bun et Next.js chargent `.env` d’eux-mêmes. Avec Node 20.6 ou plus, lance ton script avec `node --env-file=.env`.

   > **Attention**
   >
   > La clé donne le droit d’envoyer au nom de ton espace. Elle reste dans ton serveur, jamais dans le code d’une page web. Le client refuse de tourner dans un navigateur, sauf si tu forces l’option `dangerouslyAllowBrowser`.

3. **Envoie un premier e-mail**

   ```ts
   import { Agentmail } from "./lib/agentmail"

   const mail = new Agentmail()

   const { id } = await mail.emails.send({
     from: "Hugo <hugo@envoi.tonentreprise.ch>",
     to: "toi@tonentreprise.ch",
     subject: "Premier envoi depuis Node",
     html: "<p>Ça marche. Ce message part de ton domaine.</p>",
     text: "Ça marche. Ce message part de ton domaine.",
   })

   console.log("E-mail parti :", id)
   ```

   `from` doit être une adresse d’un domaine vérifié de ton espace. `to` accepte une adresse ou un tableau d’adresses.

4. **Lis la réponse et gère l'erreur**

   Un envoi réussi renvoie `{ id }`. Garde cet `id` : il sert à retrouver l’e-mail dans l’application et avec `GET /emails/:id`.

   Quand l’API refuse la requête, le client lève une `AgentmailError`. Elle indique ce qui s’est passé et si un nouvel essai a des chances d’aboutir :

   ```ts
   import { Agentmail, AgentmailError } from "./lib/agentmail"

   const mail = new Agentmail()

   try {
     const { id } = await mail.emails.send({
       from: "Hugo <hugo@envoi.tonentreprise.ch>",
       to: "toi@tonentreprise.ch",
       subject: "Premier envoi depuis Node",
       html: "<p>Ça marche.</p>",
     })
     console.log("E-mail parti :", id)
   } catch (error) {
     if (error instanceof AgentmailError) {
       console.error(error.statusCode, error.name, error.message)
       if (error.retryable) {
         // Réessayer plus tard a des chances d'aboutir.
       }
     }
     throw error
   }
   ```

   Les cas les plus fréquents :

   | Ce que tu vois              | Ce qu’il faut faire                                                      |
   | --------------------------- | ------------------------------------------------------------------------ |
   | `422 validation_error`      | Corrige le champ indiqué dans le message. Ne réessaie pas tel quel.      |
   | `403 invalid_api_key`       | La clé est fausse ou révoquée. Vérifie `AGENTMAIL_API_KEY`.              |
   | `429 rate_limit_exceeded`   | Trop d’envois en peu de temps. Attends quelques secondes, puis réessaie. |
   | `429 daily_quota_exceeded`  | Le quota du jour est atteint. Inutile de réessayer avant le lendemain.   |
   | `500 internal_server_error` | Erreur de notre côté. Réessaie avec la même clé d’idempotence.           |

   Le client ne réessaie seul un envoi que si tu lui fournis une clé d’idempotence. Sans elle, un nouvel essai pourrait doubler le message. [Envoyer sans doublon](/docs/guides/envoyer-sans-doublon/) décrit la boucle de réessai complète.

5. **Vérifie dans l'application**

   Ouvre **E-mails**. Ton message est en tête de liste, avec son parcours : en attente, envoyé, arrivé, puis ouvert si le destinataire affiche les images. Les liens partent tels quels : les clics ne sont mesurés que pour les campagnes et les workflows. Les statuts sont expliqués dans [Statuts des e-mails](/docs/reference/statuts-des-e-mails/).

> **Info**
>
> Tant que le compte d’envoi n’est pas activé, le bandeau **Mode test** s’affiche : les envois sont simulés et rien ne part vraiment. Le code reste le même, seul le résultat change.

## Si ça ne marche pas

- **`403 invalid_api_key`** : la clé est mal copiée, ou elle a été révoquée. Crée-en une nouvelle dans **Clés d’API** et remplace la valeur dans `.env`.
- **`422 validation_error` sur `from`** : l’adresse n’appartient pas à un domaine vérifié de ton espace, ou son domaine n’est pas encore **Prêt**.
- **La variable `AGENTMAIL_API_KEY` est vide** : ton script ne lit pas le fichier `.env`. Lance-le avec `node --env-file=.env` ou charge `.env` avant l’import.

## Et ensuite

[Référence de l'API](/docs/reference/api/)

[Les routes, les champs, les réponses et les en-têtes, au même endroit.](/docs/reference/api/)

[API : e-mails](/docs/reference/api-emails/)

[Envoi seul, envoi par lot, et lecture du statut d’un e-mail.](/docs/reference/api-emails/)

[Envoyer sans doublon](/docs/guides/envoyer-sans-doublon/)

[Relancer un envoi après une coupure sans que le destinataire reçoive deux fois le message.](/docs/guides/envoyer-sans-doublon/)

[Erreurs](/docs/reference/erreurs/)

[Chaque code d’erreur, sa cause et la réaction attendue.](/docs/reference/erreurs/)
