---
title: "Recevoir les messages WhatsApp via webhook Kanal"
description: "Recevez en temps réel les messages entrants WhatsApp sur votre serveur grâce aux webhooks Kanal."
url: https://help.getkanal.com/fr-fr/articles/96-recevoir-les-messages-whatsapp-via-webhook-kanal
collection: "API"
updated: 2026-10-27
language: fr-fr
alternates: [en]
---

# Recevoir les messages WhatsApp via webhook Kanal

Recevez en temps réel les messages entrants WhatsApp sur votre serveur grâce aux webhooks Kanal.

Le webhook Kanal vous notifie en temps réel quand un de vos contacts envoie un message WhatsApp à votre numéro. Idéal pour brancher un bot, alimenter un CRM, ou déclencher des traitements côté serveur.

## Configurer un webhook

1.  Cliquez sur le nom de votre équipe, puis sur **Paramètres**.
    
2.  Ouvrez **Développeurs** > **Webhooks**.
    
3.  Ajoutez l'URL publique de votre serveur. Nous recommandons une URL en HTTPS.
    

Kanal envoie une requête `POST` à cette URL à chaque message entrant, avec le corps JSON décrit ci-dessous.

> **Warning:** **Un seul envoi, sans renvoi automatique.** Kanal envoie chaque event une seule fois et attend la réponse 5 secondes au maximum. Si votre serveur ne répond pas à temps ou renvoie une erreur, l'event n'est pas renvoyé. Répondez avec un code 2xx le plus vite possible : Kanal n'attend pas de contenu particulier dans la réponse.

> **Info:** **Aucune signature.** Les requêtes envoyées par Kanal ne portent ni signature ni en-tête d'authentification. Pour protéger votre endpoint, utilisez une URL difficile à deviner, par exemple avec un jeton secret dans le chemin, et vérifiez ce jeton côté serveur.

## Format de l'event

Chaque webhook envoyé suit la même enveloppe :

```json
{
  "id": "evt_01HRXYZ...",
  "type": "message.received",
  "api_version": "2026-05-13",
  "created_at": "2026-05-13T10:00:00+00:00",
  "phone_number_id": 123,
  "data": {
    "contact": { ... },
    "message": { ... }
  }
}
```

<table style="min-width: 50px;"><colgroup><col style="min-width: 25px;"><col style="min-width: 25px;"></colgroup><tbody><tr><th colspan="1" rowspan="1"><p><strong>Champ</strong></p></th><th colspan="1" rowspan="1"><p><strong>Description</strong></p></th></tr><tr><td colspan="1" rowspan="1"><p><code>id</code></p></td><td colspan="1" rowspan="1"><p>Identifiant unique de l'event.</p></td></tr><tr><td colspan="1" rowspan="1"><p><code>type</code></p></td><td colspan="1" rowspan="1"><p>Type d'event. Pour l'instant : <code>message.received</code>.</p></td></tr><tr><td colspan="1" rowspan="1"><p><code>api_version</code></p></td><td colspan="1" rowspan="1"><p>Version du contrat webhook. Permet de gérer les évolutions sans casse.</p></td></tr><tr><td colspan="1" rowspan="1"><p><code>created_at</code></p></td><td colspan="1" rowspan="1"><p>Date d'émission de l'event au format ISO 8601.</p></td></tr><tr><td colspan="1" rowspan="1"><p><code>phone_number_id</code></p></td><td colspan="1" rowspan="1"><p>ID du numéro WhatsApp Kanal qui a reçu le message.</p></td></tr><tr><td colspan="1" rowspan="1"><p><code>data</code></p></td><td colspan="1" rowspan="1"><p>Objet contenant le contact et le message reçu.</p></td></tr></tbody></table>

## Contenu du data

L'objet `data` contient toujours deux sous-objets : `contact` et `message`.

### data.contact

```json
{
  "id": 6789,
  "phone_number": "33612345678",
  "name": "Jean Dupont",
  "country_code": "FR"
}
```

### data.message

```json
{
  "id": 98765,
  "wamid": "wamid.HBgL...",
  "type": "text",
  "content": "Bonjour, j'ai une question",
  "media": null
}
```

Le champ `content` contient le texte exploitable du message (corps texte, légende d'un média, libellé d'un bouton cliqué). Le champ `media` est rempli uniquement pour les médias (image, vidéo, audio, document). Pour les clics sur bouton et les sélections dans une liste, un objet dédié (`button` ou `list_option`) fournit en plus l'identifiant technique de l'option choisie.

## Exemples par type de message

### Texte

```json
{
  "id": "evt_01HRXYZ...",
  "type": "message.received",
  "api_version": "2026-05-13",
  "created_at": "2026-05-13T10:00:00+00:00",
  "phone_number_id": 123,
  "data": {
    "contact": {
      "id": 6789,
      "phone_number": "33612345678",
      "name": "Jean Dupont",
      "country_code": "FR"
    },
    "message": {
      "id": 98765,
      "wamid": "wamid.HBgL...",
      "type": "text",
      "content": "Bonjour, j'ai une question",
      "media": null
    }
  }
}
```

### Image

```json
{
  "id": 98766,
  "wamid": "wamid.HBgL...",
  "type": "image",
  "content": "Voici la photo de mon produit",
  "media": {
    "type": "image",
    "url": "https://api.getkanal.com/api/media/messages/98766?signature=...",
    "caption": "Voici la photo de mon produit"
  }
}
```

L'URL du champ `media.url` est un lien signé permanent servi par Kanal : vous pouvez le stocker et télécharger à nouveau le média à tout moment.

### Vidéo

```json
{
  "id": 98767,
  "wamid": "wamid.HBgL...",
  "type": "video",
  "content": null,
  "media": {
    "type": "video",
    "url": "https://api.getkanal.com/api/media/messages/98767?signature=...",
    "caption": null
  }
}
```

### Audio

```json
{
  "id": 98768,
  "wamid": "wamid.HBgL...",
  "type": "audio",
  "content": null,
  "media": {
    "type": "audio",
    "url": "https://api.getkanal.com/api/media/messages/98768?signature=...",
    "caption": null
  }
}
```

### Document

Les documents reçus (PDF, etc.) envoient un event depuis le 09/08/2026, avec le même format que les autres médias. Le champ `media.filename` contient le nom du fichier envoyé par le contact.

```json
{
  "id": 98769,
  "wamid": "wamid.HBgL...",
  "type": "document",
  "content": null,
  "media": {
    "type": "document",
    "url": "https://api.getkanal.com/api/media/messages/98769?signature=...",
    "caption": null,
    "filename": "facture-10456.pdf"
  }
}
```

### Clic sur un bouton

```json
{
  "id": 98770,
  "wamid": "wamid.HBgL...",
  "type": "button_reply",
  "content": "Oui, je confirme",
  "media": null,
  "button": {
    "id": "4233be9add_button_1",
    "title": "Oui, je confirme"
  }
}
```

`content` contient le libellé du bouton cliqué. L'objet `button` fournit en plus son identifiant technique (`button.id`), utile pour router la réponse côté serveur sans dépendre du texte affiché. Ce format couvre aussi bien les boutons d'un message interactif que les boutons de réponse rapide d'un template.

### Sélection dans une liste

```json
{
  "id": 98771,
  "wamid": "wamid.HBgL...",
  "type": "list_reply",
  "content": "Suivi de commande",
  "media": null,
  "list_option": {
    "id": "cd593e96a1_row_2",
    "title": "Suivi de commande"
  }
}
```

Même principe : `content` contient le titre de la ligne choisie, et `list_option.id` son identifiant technique.

### Autres types

Les types de messages que Kanal ne gère pas arrivent avec `"type": "other"` et un `content` vide.

## Types d'events

Le seul event émis est `message.received` (message entrant d'un contact). Les clics sur les boutons de réponse rapide d'un template arrivent également en `message.received`, avec le type de message `button_reply`. Aucun event de statut de livraison ou de lecture n'est envoyé.

> **Info:** **Préparer votre intégration.** Filtrez toujours vos events sur le champ `type`. De nouveaux types pourront être ajoutés : votre intégration ne sera pas impactée si vous ignorez ceux que vous ne traitez pas.

## Déduplication

Le champ `id` (format `evt_...`) est unique pour chaque event. Kanal ne renvoie jamais un event, mais stocker cet identifiant vous protège des doublons que pourrait créer votre propre infrastructure (proxy, file d'attente).

Le champ `wamid` (identifiant WhatsApp du message) est également unique et stable : utile si vous voulez croiser plusieurs sources de données.

## Versions et compatibilité

Le champ `api_version` indique la version du contrat webhook. La version actuelle est `2026-05-13`.

-   Les ajouts non cassants (nouveaux champs, nouveaux types d'events) sont déployés sans changer la version.
    
-   Une nouvelle version sera publiée uniquement en cas de changement cassant, avec une période de transition.
    
-   Pour rester compatible, votre intégration doit ignorer les champs qu'elle ne connaît pas.
    

## Bonnes pratiques

-   Répondez `200 OK` en moins de 5 secondes et mettez en file le traitement lourd côté serveur.
    
-   Surveillez la disponibilité de votre endpoint : un event non reçu n'est pas renvoyé.
    
-   Filtrez les events par `type` pour ne traiter que ce qui vous intéresse.
    
-   Pour répondre au message reçu, utilisez `POST /api/v1/messages/send` avec le numéro du contact dans le champ `to`. Voir [API Messaging : envoyer des messages et déclencher des automatisations](https://help.getkanal.com/fr-fr/articles/81-api-messaging-envoyer-des-messages-et-declencher-des-automatisations.md).
    

## Champs legacy

Pour des raisons de compatibilité avec les anciens clients (notamment les notifications mobiles), les champs `title`, `body` et `text` sont également présents à la racine du payload. Ils contiennent des textes génériques en anglais : « New message on Kanal » et « <nom> just sent you a new message ». Ignorez-les pour une intégration moderne : toutes les informations utiles sont dans `data`.
