# API WhatsApp

Votre application peut envoyer des messages WhatsApp aux acheteurs d'une boutique grâce à quatre endpoints. Les messages utilisent les modèles de commande que DZBuild a fait approuver par Meta, et chacun est payé par le solde WhatsApp de la boutique, exactement comme les messages que l'addon WhatsApp Sender envoie de lui-même. Vous ne pouvez pas envoyer de texte libre ni vos propres modèles.

La référence complète des requêtes et réponses se trouve dans la description OpenAPI, accessible depuis la page [Référence de l'API](https://dzbuild.dev/fr/fr/api-reference.md). Cette page explique comment les éléments s'articulent.

## Scopes[​](#scopes "Lien direct vers Scopes")

| Scope           | Autorise                                                                              |
| --------------- | ------------------------------------------------------------------------------------- |
| `whatsapp:read` | `GET /v1/whatsapp/templates`, `GET /v1/whatsapp/balance`, `GET /v1/whatsapp/messages` |
| `whatsapp:send` | `POST /v1/orders/{id}/whatsapp`                                                       |

Ne demandez dans l'URL d'autorisation que les scopes dont vous avez besoin. Un appel sans le scope répond `403` avec le code `forbidden` et le message `Missing scope: whatsapp:send` (ou `whatsapp:read`). Voir [Scopes](https://dzbuild.dev/fr/fr/scopes.md).

## Modèles[​](#modèles "Lien direct vers Modèles")

`GET /v1/whatsapp/templates` liste les six modèles. Il lit le statut d'approbation que DZBuild conserve et n'appelle jamais Meta.

| Clé               | Envoyé pour                                           |
| ----------------- | ----------------------------------------------------- |
| `received`        | La commande a été reçue.                              |
| `confirmed`       | La commande a été confirmée.                          |
| `shipped_home`    | Le colis est en route vers l'adresse de l'acheteur.   |
| `shipped_desk`    | Le colis est en route vers un bureau du transporteur. |
| `delivery_failed` | La tentative de livraison a échoué.                   |
| `desk_ready`      | Le colis est prêt à être retiré.                      |

Chaque élément contient `key`, `name` (le nom du modèle chez Meta, par exemple `dz_order_confirmed`), `toggle` (l'interrupteur correspondant du marchand dans l'addon) et `languages`. `languages.ar` et `languages.fr` contiennent chacun le `body` avec ses variables, un `example` et le `status`. Un modèle ne peut être envoyé que dans une langue dont le statut est `APPROVED`. `UNKNOWN` signifie que DZBuild n'a encore aucun statut enregistré.

## Solde[​](#solde "Lien direct vers Solde")

`GET /v1/whatsapp/balance` renvoie :

| Champ          | Signification                                                                                                                                                     |
| -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `balance`      | Messages restants dans le solde de la boutique. Un message coûte un crédit.                                                                                       |
| `low_balance`  | `true` quand il reste moins de 50 messages.                                                                                                                       |
| `addon_active` | Indique si le marchand a activé l'addon WhatsApp Sender.                                                                                                          |
| `stats`        | Nombre de messages des 30 derniers jours par statut (`sent`, `delivered`, `read`, `failed`) et `used_month`, les crédits utilisés depuis le premier jour du mois. |

Le marchand recharge son solde dans le tableau de bord DZBuild. Votre application ne peut pas ajouter de crédit.

## Envoyer un message[​](#envoyer-un-message "Lien direct vers Envoyer un message")

`POST /v1/orders/{id}/whatsapp` met en file un modèle pour une commande de la boutique. C'est une écriture, elle exige donc un en-tête `Idempotency-Key` (voir [Limites de requêtes](https://dzbuild.dev/fr/fr/rate-limits.md)).

```
POST /v1/orders/98765/whatsapp HTTP/1.1

Host: api.dzbuild.app

Authorization: Bearer dzpk_live_xxxxxxxx

Idempotency-Key: wa-98765-confirmed

Content-Type: application/json



{"template": "confirmed", "language": "fr"}
```

| Champ du corps | Obligatoire | Signification                                                                                                                                                                                                                        |
| -------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `template`     | Oui         | L'une des six clés, ou `shipped`. `shipped` choisit le bon modèle selon le type de livraison de la commande : `shipped_home` pour la livraison à domicile, `shipped_desk` pour un bureau, `desk_ready` pour le retrait.              |
| `language`     | Non         | `ar` ou `fr`. Sans ce champ, la langue réglée dans l'addon WhatsApp Sender de la boutique est utilisée, ou la langue de la boutique si l'addon n'en a pas. Si cette langue de repli n'est ni `ar` ni `fr`, le message part en arabe. |

Un envoi manuel ignore les interrupteurs d'envoi automatique du marchand dans l'addon. L'addon doit cependant être actif sur la boutique.

L'appel répond `202` quand le message est en file et le crédit débité :

```
{

  "data": { "message_id": 4411, "status": "queued", "template": "confirmed", "language": "fr" },

  "meta": { "request_id": "8f2c1a9d4b7e6035", "api_version": "v1" }

}
```

DZBuild envoie les messages en file en arrière-plan. Suivez le résultat avec `GET /v1/whatsapp/messages`.

## Réponses et codes d'erreur[​](#réponses-et-codes-derreur "Lien direct vers Réponses et codes d'erreur")

| Statut | Code                    | Signification                                                                                                      |
| ------ | ----------------------- | ------------------------------------------------------------------------------------------------------------------ |
| `202`  |                         | En file, un crédit débité.                                                                                         |
| `400`  | `bad_request`           | L'identifiant de commande n'est pas numérique, ou le corps n'est pas un JSON valide.                               |
| `402`  | `no_credit`             | Le solde WhatsApp de la boutique est vide. Rien n'a été mis en file ni débité.                                     |
| `403`  | `addon_not_active`      | Le marchand n'a pas activé l'addon WhatsApp Sender.                                                                |
| `403`  | `forbidden`             | Le jeton n'a pas `whatsapp:send`.                                                                                  |
| `404`  | `not_found`             | Aucune commande avec cet identifiant sur cette boutique.                                                           |
| `409`  | `already_sent`          | Ce modèle a déjà été envoyé pour cette commande. L'objet d'erreur porte l'`id` et le `status` du message existant. |
| `422`  | `unknown_template`      | `template` ne fait pas partie des clés acceptées.                                                                  |
| `422`  | `invalid_language`      | `language` n'est ni `ar` ni `fr`.                                                                                  |
| `422`  | `invalid_number`        | Le téléphone de l'acheteur n'est pas un numéro mobile algérien valide.                                             |
| `422`  | `suppressed`            | Le numéro de l'acheteur est bloqué pour les messages WhatsApp sur la plateforme.                                   |
| `422`  | `template_not_approved` | Le modèle n'est pas approuvé dans cette langue.                                                                    |
| `422`  | `empty_param`           | Une valeur exigée par le modèle est vide sur la commande.                                                          |
| `500`  | `send_failed`           | Le message n'a pas pu être mis en file. Réessayez plus tard.                                                       |

Chaque modèle peut être envoyé une fois par commande via l'API. Un appel ultérieur pour le même modèle et la même commande répond `409`, même si le premier message a échoué. Les réponses `422` de `invalid_number` à `empty_param` sont différentes : rien n'a été débité, et l'appel suivant pour ce modèle et cette commande réessaie. Corrigez la cause (par exemple le numéro de téléphone de la commande), puis rappelez avec un nouvel `Idempotency-Key`.

## Journal des messages[​](#journal-des-messages "Lien direct vers Journal des messages")

`GET /v1/whatsapp/messages` liste les messages de la boutique, du plus récent au plus ancien. Paramètres de requête : `order_id` pour filtrer une commande, `limit` (50 par défaut, 200 au maximum) et `cursor` (le `next_cursor` de la page précédente). Le numéro de téléphone de l'acheteur n'est jamais renvoyé.

| Champ           | Signification                                                                                                                                                                         |
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`            | L'identifiant du message, le même que `message_id` dans la réponse d'envoi.                                                                                                           |
| `order_id`      | La commande.                                                                                                                                                                          |
| `event`         | La clé du modèle pour les messages envoyés via l'API, ou l'événement de l'addon (`received`, `confirmed`, `shipped`, `delivery_failed`, `desk_ready`) pour les messages automatiques. |
| `source`        | `api` pour les messages envoyés via l'API, `auto` pour les messages automatiques de l'addon.                                                                                          |
| `status`        | `queued`, `sending`, `sent`, `delivered`, `read`, `failed` ou `skipped`.                                                                                                              |
| `language`      | `ar` ou `fr`.                                                                                                                                                                         |
| `template_name` | Le nom du modèle chez Meta.                                                                                                                                                           |
| `error_title`   | La raison de l'échec ou du saut du message, ou `null`.                                                                                                                                |
| `refunded`      | `true` quand le crédit a été rendu.                                                                                                                                                   |
| `billing`       | `charged` une fois le message facturé par WhatsApp, `free` une fois le crédit rendu, `null` tant que WhatsApp n'a pas signalé le résultat.                                            |
| `created_at`    | La date de mise en file du message.                                                                                                                                                   |

Un message qui échoue, qui n'est pas délivré après 30 jours, ou qui est délivré sans facturation par WhatsApp récupère son crédit une fois : `refunded` passe à `true` et `billing` devient `free`. Un message facturé par WhatsApp est fixé à `charged`.
