Messaggi interattivi WhatsApp
Un messaggio interattivo è testo più un elemento che il destinatario può toccare: un pulsante WhatsApp, un menu, un link, una card o una richiesta di posizione o dati di contatto. Dove una risposta a un template richiede di analizzare testo libero, un menu WhatsApp o un set di pulsanti WhatsApp offre al destinatario un insieme fisso di scelte e restituisce a te un valore che hai definito. Questa pagina copre ciò che i sei tipi hanno in comune; la pagina di ciascun tipo descrive la sua struttura e i suoi limiti specifici.
I sei tipi
| Tipo | Bird interactive.type | Header | Footer | Body max |
|---|---|---|---|---|
| Pulsanti di risposta | button | testo, immagine, video, documento | sì | 1024 |
| Menu a lista | list | solo testo | sì | 4096 |
| Pulsanti con link | cta_url | testo, immagine, video, documento | sì | 1024 |
| Caroselli multimediali | carousel | nessuno sul messaggio; immagine o video per card | no | 1024 messaggio, 160 per card |
| Richieste di posizione | location_request_message | nessuno | no | 1024 |
| Richieste di contatto | request_contact_info | nessuno | no | 1024 |
Ogni tipo è free-form: inviabile solo all'interno di una finestra di assistenza clienti aperta, e mai soggetto a revisione da parte di Meta come accade per un template.
I messaggi interattivi sono contenuto free-form, quindi si applica la regola della finestra di assistenza clienti: consulta la finestra di assistenza clienti per capire cosa significa e cosa restituisce una finestra chiusa.
Ogni invio interattivo richiede anche from, un numero di proprietà del tuo spazio di lavoro. I numeri gestiti da Bird non lo supportano, quindi un invio interattivo richiede prima di tutto un numero tuo collegato.
Il campo di contenuto interattivo
interactive è uno dei campi di contenuto mutuamente esclusivi su POST /v1/whatsapp/messages, accanto a template, text, image e gli altri: esattamente uno può essere presente in un invio. All'interno di interactive, type indica quale delle sei varianti è, e il campo specifico di quella variante contiene il resto (buttons, list, cta_url o cards). Lo schema esclude il campo di ogni altra variante, quindi combinare due varianti in un singolo invio genera un errore di validazione prima di raggiungere un handler.
Per la request envelope, il modello di risposta 202 e i retry sicuri, consulta Invio di messaggi WhatsApp anziché ripeterli in questa pagina.
Ecco un messaggio interattivo minimale: due pulsanti WhatsApp su un invio reply-buttons, una lingua alla volta.
const msg = await bird.whatsapp.send({
to: "+15551234567",
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" } },
{ type: "quick_reply", quick_reply: { slug: "cancel-booking", text: "Cancel" } },
],
},
});
console.log(msg.id, msg.status);msg = client.whatsapp.send(
to="+15551234567",
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"}},
{"type": "quick_reply", "quick_reply": {"slug": "cancel-booking", "text": "Cancel"}},
],
},
)
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: "+15551234567",
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"}},
{Type: "quick_reply", QuickReply: &bird.WhatsAppInteractiveQuickReplyButtonSend{Slug: "cancel-booking", Text: "Cancel"}},
},
},
})
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')),
(new WhatsAppInteractiveButtonSend())
->setType('quick_reply')
->setQuickReply((new WhatsAppInteractiveButtonSendQuickReply())->setSlug('cancel-booking')->setText('Cancel')),
]);
$message = $bird->whatsapp->send(
to: '+15551234567',
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"},{"quick_reply":{"slug":"cancel-booking","text":"Cancel"},"type":"quick_reply"}],"type":"button"}' \
--to +15551234567{
"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"
},
{
"quick_reply": {
"slug": "cancel-booking",
"text": "Cancel"
},
"type": "quick_reply"
}
],
"type": "button"
},
"to": "+15551234567"
}
}curl -X POST "https://{region}.platform.bird.com/v1/whatsapp/messages" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"to": "+15551234567",
"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" } },
{ "type": "quick_reply", "quick_reply": { "slug": "cancel-booking", "text": "Cancel" } }
]
}
}'Pulsanti
Quattro dei sei tipi inseriscono un pulsante, e tutti si basano sulla stessa struttura: un oggetto discriminato il cui type è quick_reply o cta_url, ciascuno con il proprio campo annidato dello stesso nome. Un pulsante quick_reply contiene slug e text; un pulsante cta_url contiene text e url. Quali tipi accettano quale forma di pulsante:
- I pulsanti di risposta inviano solo pulsanti quick_reply, da 1 a 3.
- I pulsanti con link inviano esattamente un pulsante cta_url.
- I caroselli multimediali inseriscono pulsanti in ogni card: un pulsante cta_url oppure fino a tre pulsanti quick_reply, e ogni card nel carosello deve concordare.
- I menu a lista usano righe all'interno di sezioni anziché questo oggetto pulsante, trattate nella loro pagina dedicata.
Il campo slug di un pulsante quick_reply è il tuo handle per quel pulsante. Non viene mai mostrato al destinatario, che vede solo la label text, e il slug viene restituito verbatim nella risposta. Questo ciclo è ciò che rende una risposta correlabile al pulsante che l'ha generata, quindi vale la pena dirlo una volta qui anziché in ogni pagina specifica.
Leggere una risposta
Premere un pulsante o scegliere una riga del menu invia un proprio messaggio in entrata, contenente un oggetto interactive_reply. interactive_reply.type è button o list; in entrambi i casi l'oggetto annidato contiene il slug e il text che hai dichiarato, cioè la label toccata che il destinatario ha effettivamente visto. I due tipi di richiesta, richieste di posizione e richieste di contatto, rispondono diversamente: la risposta a una richiesta di posizione è un normale messaggio in entrata di tipo location, e la risposta a una richiesta di contatto è una scheda contatto in entrata, non un interactive_reply.
Una risposta ti arriva attraverso la lista messaggi e GET /v1/whatsapp/messages/{id}, allo stesso modo di qualsiasi messaggio WhatsApp in entrata. Per agire su una risposta appena arriva invece di fare polling, iscriviti al webhook whatsapp.received: il suo payload contiene interactive_reply, quindi indica già il pulsante o la riga toccata. Ricezione delle risposte interattive descrive la struttura in lettura di un tap, il payload del webhook e i tap che arrivano su un altro campo.
Citare un messaggio per correlare una risposta
in_reply_to_message_id in un invio cita un messaggio precedente della stessa conversazione, e ogni messaggio, inviato o ricevuto, lo restituisce in lettura. È un unico campo per entrambe le direzioni.
La correlazione che ottieni è asimmetrica. Un tap su un pulsante WhatsApp o una riga del menu porta il context di Meta, quindi in_reply_to_message_id si risolve nel messaggio che lo ha offerto. Una scheda contatto condivisa non porta alcun context, quindi non si risolve in nulla: correli la risposta a una richiesta di contatto tramite from e il timing, non tramite questo campo.
La risoluzione passa attraverso un message-context store, e un miss omette il campo invece di riportarne uno. Sul wire è indistinguibile da una risposta che non risponde a nulla. Un'integrazione che richiede correlazione affidabile non dovrebbe basarsi solo su questo campo: porta il tuo metadata nell'invio e fai il match su quello.
La finestra in cui un messaggio resta citabile è limitata a 15 giorni; oltre, l'invio fallisce con un 404 E15071, perché Bird non contiene più il provider id necessario per la citazione. Invio di messaggi WhatsApp gestisce il campo lato invio: la sua lunghezza, la sua risoluzione e la struttura della richiesta.
Errori
Tre codici di errore sono specifici del contenuto interattivo. Ciascuno si attiva solo sui tipi che hanno il campo controllato, quindi la quarta colonna indica quali tipi possono effettivamente generarlo.
| Codice | Status | Cosa lo genera | Si applica a |
|---|---|---|---|
| E15055 WhatsAppInteractiveLimitExceeded | 422 | Il messaggio supera un limite per il suo tipo; attualmente, più di 10 righe nelle sezioni di una lista. | Solo menu a lista |
| E15056 WhatsAppInteractiveDuplicateLabel | 422 | Due pulsanti o righe nello stesso messaggio condividono una label. | Qualsiasi tipo con pulsanti o righe con label: pulsanti di risposta, menu a lista, caroselli multimediali |
| E15059 WhatsAppInteractiveCarouselButtonsMismatch | 422 | Le card di un carosello non hanno tutte gli stessi pulsanti. | Solo caroselli multimediali |
Ogni invio interattivo può anche generare gli errori di qualsiasi invio WhatsApp: finestra di assistenza clienti chiusa, mittente mancante o non valido, destinatario non valido o contenuto ambiguo. Sono condivisi tra ogni tipo di contenuto WhatsApp, non specifici dei messaggi interattivi; consulta Invio di messaggi WhatsApp per quell'elenco anziché una copia qui.
Passi successivi
- Invio di messaggi WhatsApp: la request envelope, il modello 202 e i retry sicuri
- Eventi WhatsApp: segui la consegna per messaggio, tramite API o webhooks
- Template WhatsApp: i messaggi che puoi ancora inviare quando la finestra è chiusa
Risorse correlate
Prosegui con la documentazione, le guide e gli esempi per questo argomento. Le risorse sono in inglese.
Guarda la guidaConnecting WhatsApp to Bird: from buying a number to a live channelComprendi il concettoWhat is the 24-hour customer service window on WhatsApp?Usa lo strumentoWhatsApp message builderEsplora la funzionalitàWhatsApp
Prova l'esercitazione e ottieni un brief di implementazione