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

# SDK Node.js

> SMS, OTP, e-mail, WhatsApp, push, contacts et campagnes depuis votre serveur, typé de bout en bout.

`@dexnotify/node` couvre toute l’API publique : chaque corps et chaque filtre est typé d’après la spécification de l’API, chaque réponse d’après les types du serveur. Sans dépendance, ESM et CommonJS. Il tourne sur Node 20+, Bun, Deno et Cloudflare Workers.

> [!WARNING]
>
> Une clé API serveur ne va **jamais** dans un navigateur ni dans une application mobile. Côté client, utilisez le [SDK web](https://docs.dexnotify.com/sdk/web.md) ou le [SDK React Native](https://docs.dexnotify.com/sdk/react-native.md) avec une clé SDK.

## Installation

```bash npm theme={null}
npm install @dexnotify/node
```

```bash pnpm theme={null}
pnpm add @dexnotify/node
```

```bash yarn theme={null}
yarn add @dexnotify/node
```

```bash bun theme={null}
bun add @dexnotify/node
```

## Initialiser

```ts theme={null}
import { DexNotify } from "@dexnotify/node";

const dexnotify = new DexNotify({ apiKey: process.env.DEXNOTIFY_API_KEY });
```

Sans `apiKey`, le client lit `DEXNOTIFY_API_KEY`. La clé porte son projet et son environnement : une clé de staging n’atteint que le staging (voir [Environnements](https://docs.dexnotify.com/environnements.md)).

| Option | Défaut | Rôle |
| - | - | - |
| `apiKey` | `DEXNOTIFY_API_KEY` | clé API du projet |
| `baseUrl` | `https://api.dexnotify.com/api` | ou `DEXNOTIFY_BASE_URL` |
| `timeoutMs` | `30000` | délai d’une tentative |
| `maxRetries` | `2` | reprises sur coupure, 408, 429 et 5xx |
| `fetch` | `globalThis.fetch` | pour un proxy ou des tests |

## Envoyer

```ts SMS theme={null}
const message = await dexnotify.sms.send({
  type: "single",
  sender: "DEXCHANGE",
  to: "+221771234567",
  content: "Votre commande est prête.",
});
console.log(message.id, message.status);
```

```ts SMS groupé theme={null}
await dexnotify.sms.send({
  type: "bulk",
  sender: "DEXCHANGE",
  content: "Bonjour {{prenom}}, -20 % ce week-end.",
  groupIds: ["66f1c0a2e4b0a1b2c3d4e5f6"],
  scheduledAt: "2026-11-15T09:00:00",
  timezone: "Africa/Dakar",
});
```

```ts OTP theme={null}
await dexnotify.otp.send({ to: "+221771234567", purpose: "connexion" });

// Un code faux ou expiré lève une DexNotifyError.
await dexnotify.otp.verify({ to: "+221771234567", purpose: "connexion", code: "482913" });
```

```ts E-mail theme={null}
await dexnotify.email.send({
  from: "Boutique <commandes@boutique.sn>",
  to: ["client@example.com"],
  subject: "Votre reçu",
  html: "<p>Merci pour votre achat.</p>",
});
```

```ts Push theme={null}
await dexnotify.notifications.send({
  applicationId: "SHOP-482913",
  target: { externalUserId: "client-42" },
  content: { title: "Colis livré", body: "Il vous attend au point relais." },
});
```

## Ressources

| Propriété | Ce qu’elle couvre |
| - | - |
| `sms`, `sms.templates` | envois simples et groupés, programmés, rapports, exports CSV, solde |
| `otp` | codes à usage unique |
| `email`, `email.suppressions` | e-mails transactionnels, journal, adresses bloquées |
| `whatsapp` | messages WhatsApp |
| `contacts`, `contactGroups` | base de contacts, listes, imports CSV et XLSX |
| `campaigns`, `emailTemplates`, `automations`, `media` | campagnes marketing e-mail et SMS |
| `notifications`, `pushCampaigns`, `pushTemplates`, `messages` | notifications push |
| `inAppMessages`, `liveActivities` | messages in-app, Live Activities iOS |
| `users`, `devices`, `segments`, `events`, `outcomes`, `analytics` | audience et mesure |

Une route que le SDK n’expose pas encore reste joignable : `dexnotify.request("GET", "/v1/…")`.

## Fichiers

```ts theme={null}
import { readFile } from "node:fs/promises";

// Import de contacts : l'import se poursuit en arrière-plan.
const job = await dexnotify.contacts.imports.create(
  { file: await readFile("clients.csv"), filename: "clients.csv" },
  { phone: "Téléphone", fields: { email: "E-mail" }, defaultCountry: "SN" },
);

// Une image pour vos e-mails, en un appel.
const asset = await dexnotify.media.upload({
  data: await readFile("logo.png"),
  name: "logo.png",
  contentType: "image/png",
});
```

## Fiabilité

* **Reprises** : coupure réseau, délai, 408, 429 et 5xx sont repris, en respectant `Retry-After`.
* **Idempotence** : chaque `POST` porte une `Idempotency-Key`, la même pour toutes ses tentatives. Une reprise n’envoie jamais deux messages. Passez la vôtre pour rejouer un envoi d’un processus à l’autre (voir [Idempotence](https://docs.dexnotify.com/idempotence.md)) :

```ts theme={null}
await dexnotify.sms.send(params, { idempotencyKey: `commande-${order.id}` });
```

## Erreurs

Toute erreur est une `DexNotifyError` : `code` (voir [Erreurs](https://docs.dexnotify.com/erreurs.md)), `status`, `details` champ par champ, et `requestId` à citer au support.

```ts theme={null}
import { DexNotifyError } from "@dexnotify/node";

try {
  await dexnotify.sms.send(params);
} catch (error) {
  if (error instanceof DexNotifyError && error.code === "INSUFFICIENT_BALANCE") {
    await alerterLaFinance();
  }
  throw error;
}
```

## Pagination

```ts theme={null}
import { iterate } from "@dexnotify/node";

for await (const contact of iterate((page) => dexnotify.contacts.list({ page, limit: 100 }))) {
  console.log(contact.phone);
}
```

## Webhooks

`constructWebhookEvent` vérifie la signature HMAC — sur le corps **brut** — puis rend l’événement. Il lève si la signature est fausse ou date de plus de cinq minutes. Voir [Webhooks](https://docs.dexnotify.com/webhooks.md).

```ts Express theme={null}
import express from "express";
import { constructWebhookEvent } from "@dexnotify/node";

app.post("/webhooks/dexnotify", express.raw({ type: "application/json" }), async (req, res) => {
  const event = await constructWebhookEvent(
    req.body,
    req.header("DexNotify-Signature"),
    process.env.DEXNOTIFY_WEBHOOK_SECRET!,
  ).catch(() => null);
  if (!event) return res.sendStatus(401);

  res.sendStatus(200);
  // Dédoublonnez sur event.id, puis traitez event.event et event.data.
});
```

`verifyWebhookSignature` rend seulement un booléen. Les deux reposent sur Web Crypto et fonctionnent aussi dans un Worker ou une route Next.js.


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