Boutons de réponse WhatsApp
Les boutons de réponse placent jusqu'à trois choix cliquables sous un message WhatsApp, pour que le destinataire réponde d'un tap au lieu de saisir du texte libre. Utilisez-les pour une décision rapide, comme confirmer ou annuler une réservation. Pour plus de trois choix, utilisez plutôt les menus à liste.
Envoyer des boutons de réponse
Définissez interactive.type sur button, avec un body_text et un à trois buttons, chacun un quick_reply :
const msg = await bird.whatsapp.send({
to: "+16505551234",
from: "+13124495648",
interactive: {
type: "button",
body_text: "Your gardening workshop is scheduled for 9am tomorrow.",
buttons: [{ type: "quick_reply", quick_reply: { slug: "change-booking", text: "Change" } }],
},
});
console.log(msg.id, msg.status);msg = client.whatsapp.send(
to="+16505551234",
from_="+13124495648",
interactive={
"type": "button",
"body_text": "Your gardening workshop is scheduled for 9am tomorrow.",
"buttons": [{"type": "quick_reply", "quick_reply": {"slug": "change-booking", "text": "Change"}}],
},
)
print(msg.id, msg.status)package main
import (
"context"
"fmt"
"log"
"os"
bird "github.com/messagebird/bird-sdk-go"
"github.com/messagebird/bird-sdk-go/option"
)
func main() {
client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
if err != nil {
log.Fatal(err)
}
msg, err := client.Whatsapp.Send(context.Background(), bird.WhatsappSendParams{
To: "+16505551234",
From: "+13124495648",
Interactive: &bird.WhatsAppInteractiveSend{
Type: "button",
BodyText: "Your gardening workshop is scheduled for 9am tomorrow.",
Buttons: &[]bird.WhatsAppInteractiveButtonSend{
{Type: "quick_reply", QuickReply: &bird.WhatsAppInteractiveQuickReplyButtonSend{Slug: "change-booking", Text: "Change"}},
},
},
})
if err != nil {
log.Fatal(err)
}
fmt.Println(msg.Id, *msg.Status)
}$interactive = (new WhatsAppMessageSendRequestInteractive())
->setType('button')
->setBodyText('Your gardening workshop is scheduled for 9am tomorrow.')
->setButtons([
(new WhatsAppInteractiveButtonSend())
->setType('quick_reply')
->setQuickReply((new WhatsAppInteractiveButtonSendQuickReply())->setSlug('change-booking')->setText('Change')),
]);
$message = $bird->whatsapp->send(
to: '+16505551234',
from: '+13124495648',
interactive: $interactive,
);
echo $message->getId(), ' ', $message->getStatus();bird whatsapp send \
--from +13124495648 \
--interactive '{"body_text":"Your gardening workshop is scheduled for 9am tomorrow.","buttons":[{"quick_reply":{"slug":"change-booking","text":"Change"},"type":"quick_reply"}],"type":"button"}' \
--to +16505551234{
"name": "whatsapp_send",
"arguments": {
"from": "+13124495648",
"interactive": {
"body_text": "Your gardening workshop is scheduled for 9am tomorrow.",
"buttons": [
{
"quick_reply": {
"slug": "change-booking",
"text": "Change"
},
"type": "quick_reply"
}
],
"type": "button"
},
"to": "+16505551234"
}
}curl -X POST "https://{region}.platform.bird.com/v1/whatsapp/messages" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"to": "+16505551234",
"from": "+13124495648",
"interactive": {
"type": "button",
"body_text": "Your gardening workshop is scheduled for 9am tomorrow.",
"buttons": [
{ "type": "quick_reply", "quick_reply": { "slug": "change-booking", "text": "Change" } }
]
}
}'from est requis sur chaque message de service : un numéro que votre espace de travail possède, pas un numéro géré par Bird. La forme complète ajoute un en-tête optionnel, un pied de page, une citation d'un message précédent et un second bouton :
Exemple de code
{
"to": "+16505551234",
"from": "+13124495648",
"in_reply_to_message_id": "wam_01kya19eknftrs2s6p82asmvnh",
"interactive": {
"type": "button",
"header": {
"type": "image",
"url": "https://cdn.example.com/banners/workshop.png"
},
"body_text": "Your gardening workshop is scheduled for 9am tomorrow.",
"footer_text": "Lucky Shrub, your gateway to succulents",
"buttons": [
{ "type": "quick_reply", "quick_reply": { "slug": "change-booking", "text": "Change" } },
{ "type": "quick_reply", "quick_reply": { "slug": "cancel-booking", "text": "Cancel" } }
]
},
"tags": [{ "name": "category", "value": "booking" }],
"metadata": { "order_id": "A-1" }
}in_reply_to_message_id cite un message précédent dans la même conversation. Consultez la section citer un message pour corréler une réponse du hub pour le fonctionnement de la résolution et ses limites.
Ce type n'envoie que des boutons quick_reply. Un bouton cta_url appartient à un interactive.type distinct et ne peut pas apparaître aux côtés de buttons ; consultez la section boutons du hub pour la forme de bouton partagée.
En-têtes et pieds de page
L'en-tête est optionnel et prend l'une de quatre formes :
Exemple de code
"header": { "type": "text", "text": "New workshop dates" }
"header": { "type": "image", "url": "https://cdn.example.com/a.png" }
"header": { "type": "video", "url": "https://cdn.example.com/a.mp4" }
"header": { "type": "document", "url": "https://cdn.example.com/a.pdf" }Un en-tête média (image, video ou document) transporte son fichier sous forme d'URL https publique que WhatsApp récupère au moment de l'envoi, au lieu d'un identifiant média téléchargé. footer_text est optionnel et ajoute une ligne sous les boutons.
Limites
| Champ | Contrainte |
|---|---|
| buttons | 1 à 3 entrées, chacune un quick_reply |
| quick_reply.slug | requis, 1 à 256 caractères |
| quick_reply.text (label) | requis, 1 à 20 caractères, unique dans le message |
| body_text | requis, 1 à 1 024 caractères |
| footer_text | optionnel, 1 à 60 caractères |
| header.text | 1 à 60 caractères |
Bird vérifie que les labels des boutons (quick_reply.text) sont uniques, mais ne vérifie pas que les valeurs slug sont uniques, même si chaque slug est censé identifier un bouton. Deux boutons partageant un slug sont tous deux envoyés et distribués, et leurs réponses reviennent indifférenciables.
Lire la réponse
Un appui arrive comme son propre message entrant, portant interactive_reply :
Exemple de code
{
"id": "wam_01kyb2m4xq7whs0d8n3prv6tez",
"direction": "inbound",
"from": { "phone_number": "+16505551234" },
"to": { "phone_number": "+13124495648" },
"status": "received",
"in_reply_to_message_id": "wam_01kya19eknftrs2s6p82asmvnh",
"interactive_reply": {
"type": "button",
"button": {
"slug": "cancel-booking",
"text": "Cancel"
}
},
"created_at": "2026-08-25T09:04:11Z"
}Le slug que vous avez défini à l'envoi revient tel quel, vous pouvez donc brancher directement dessus sans table de correspondance. Vous voyez cette réponse via la liste des messages ou GET /v1/whatsapp/messages/{id} ; consultez la section lire une réponse du hub pour le parcours complet.
Limites et cas particuliers
- La fenêtre de service client doit être ouverte. Les boutons de réponse sont un message de service, distribuable uniquement dans une fenêtre ouverte ; consultez la section fenêtre de service client du hub. La vérification de la fenêtre échoue en mode ouvert, donc un 202 ne prouve pas que la fenêtre était réellement ouverte au moment de l'envoi.
- from doit être un numéro que votre espace de travail possède. L'omettre, ou nommer un numéro qui n'est pas un expéditeur connecté, est rejeté avant la création de l'envoi.
- Les labels doivent être uniques, sinon l'envoi est refusé. Deux boutons avec le même quick_reply.text échouent avec 422 E15056 WhatsAppInteractiveDuplicateLabel, car Meta rejetterait sinon le doublon après que l'envoi a déjà été accepté et facturé.
- Le label est ce que le destinataire voit ; le slug ne l'est jamais. Mettre du texte destiné à l'utilisateur dans slug est un no-op silencieux, car seul text s'affiche dans le chat.
- Une URL d'en-tête média que WhatsApp ne peut pas récupérer échoue après l'acceptation de l'envoi. Bird ne valide pas l'en-tête url de la même manière qu'il valide l'URL d'un message média, donc une URL http:// ou une URL qui retourne une erreur passe la requête puis échoue de manière asynchrone, avec media_rejected sur le last_error du message.
- Envoyer les propres noms de champs de Meta fait échouer la requête. Ce type rejette les propriétés inconnues directement, donc du JSON copié depuis la référence Cloud API de Meta, comme un objet body ou un wrapper action.buttons, doit être restructuré dans les champs plats de Bird au préalable.
Une citation qui ne se résout pas fait échouer la requête avant que quoi que ce soit ne soit créé ou facturé : 404 E15071 quand l'id ne désigne aucun message détenu par cet espace de travail, 422 E15072 quand il désigne un message qui ne peut pas être cité. Pour les erreurs que tout envoi WhatsApp peut rencontrer, une fenêtre fermée, un expéditeur manquant ou invalide, ou un destinataire invalide, consultez les sections erreurs et Envoyer des messages WhatsApp du hub.
Étapes suivantes
- Messages interactifs WhatsApp : ce que les six types interactifs ont en commun
- Menus à liste : pour plus de trois choix
- Envoyer des messages WhatsApp : l'enveloppe de requête, le modèle 202 et les réessais sûrs
Ressources associées
Poursuivez avec la documentation, les guides et les exemples sur ce sujet. Les ressources sont en anglais.
Regarder le guideConnecting WhatsApp to Bird: from buying a number to a live channelComprendre le conceptWhat is the 24-hour customer service window on WhatsApp?Utiliser l'outilWhatsApp message builderExplorer la fonctionnalitéWhatsApp
Essayez la pratique et obtenez un guide d'implémentation