Oui : deux boutons quick_reply au maximum dans un template approuvé par Meta ; le clic revient en message.inbound avec le libellé touché, et rouvre la fenêtre de 24 h.
Astuce
Oui : deux boutons quick_reply au maximum dans un template approuvé par Meta ; le clic revient en message.inbound avec le libellé touché, et rouvre la fenêtre de 24 h.
Vous notifiez un client hors des 24 h (livraison prévue demain, offre, enquête) et vous voulez qu'il réponde d'un clic : « Oui » ou « Non », au lieu de taper.
Oui, un template peut porter des boutons de réponse rapide. C'est la version « hors 24 h » des boutons sans template, avec deux différences : le template doit être approuvé par Meta avant l'envoi, et il y a 2 boutons au maximum (3 sans template).
Vous : POST /v1/messages to=+237690000001 variables=["Awa", "demain entre 14 h et 16 h"]
Awa : « Bonjour Awa, votre livraison est prévue demain entre 14 h et 16 h. Serez-vous présente ? »
[ Oui ] [ Non, reporter ]
Awa : (touche « Non, reporter »)
Webhook : message.inbound type=text text="Non, reporter"
curl
curl -X POST "https://wa-api.geskap.com/v1/templates" \
-H "Authorization: Bearer $GESKAP_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "livraison_demain_presence",
"language": "fr",
"category": "UTILITY",
"body_text": "Bonjour {{1}}, votre livraison est prévue {{2}}. Serez-vous présente ?",
"example_values": ["Awa", "demain entre 14 h et 16 h"],
"buttons": [
{ "kind": "quick_reply", "text": "Oui" },
{ "kind": "quick_reply", "text": "Non, reporter" }
]
}'
Node.js
const res = await fetch("https://wa-api.geskap.com/v1/templates", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.GESKAP_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"name": "livraison_demain_presence",
"language": "fr",
"category": "UTILITY",
"body_text": "Bonjour {{1}}, votre livraison est prévue {{2}}. Serez-vous présente ?",
"example_values": ["Awa", "demain entre 14 h et 16 h"],
"buttons": [
{ "kind": "quick_reply", "text": "Oui" },
{ "kind": "quick_reply", "text": "Non, reporter" }
]
}),
});
console.log(res.status, await res.json());
PHP
$ch = curl_init("https://wa-api.geskap.com/v1/templates");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("GESKAP_API_KEY"),
"Content-Type: application/json",
],
CURLOPT_POSTFIELDS => json_encode([
"name" => "livraison_demain_presence",
"language" => "fr",
"category" => "UTILITY",
"body_text" => "Bonjour {{1}}, votre livraison est prévue {{2}}. Serez-vous présente ?",
"example_values" => ["Awa", "demain entre 14 h et 16 h"],
"buttons" => [
["kind" => "quick_reply", "text" => "Oui"],
["kind" => "quick_reply", "text" => "Non, reporter"],
],
]),
]);
$res = curl_exec($ch);
echo curl_getinfo($ch, CURLINFO_HTTP_CODE), " ", $res;
Python
import os, requests
res = requests.request(
"POST",
"https://wa-api.geskap.com/v1/templates",
headers={"Authorization": f"Bearer {os.environ['GESKAP_API_KEY']}"},
json={
"name": "livraison_demain_presence",
"language": "fr",
"category": "UTILITY",
"body_text": "Bonjour {{1}}, votre livraison est prévue {{2}}. Serez-vous présente ?",
"example_values": ["Awa", "demain entre 14 h et 16 h"],
"buttons": [
{"kind": "quick_reply", "text": "Oui"},
{"kind": "quick_reply", "text": "Non, reporter"},
],
},
timeout=15,
)
print(res.status_code, res.json())
curl
curl -X POST "https://wa-api.geskap.com/v1/messages" \
-H "Authorization: Bearer $GESKAP_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"to": "+237690000001",
"template": {
"name": "livraison_demain_presence",
"language": "fr",
"variables": ["Awa", "demain entre 14 h et 16 h"]
},
"idempotency_key": "livraison-CMD-1042"
}'
Node.js
const res = await fetch("https://wa-api.geskap.com/v1/messages", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.GESKAP_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"to": "+237690000001",
"template": {
"name": "livraison_demain_presence",
"language": "fr",
"variables": ["Awa", "demain entre 14 h et 16 h"]
},
"idempotency_key": "livraison-CMD-1042"
}),
});
console.log(res.status, await res.json());
PHP
$ch = curl_init("https://wa-api.geskap.com/v1/messages");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("GESKAP_API_KEY"),
"Content-Type: application/json",
],
CURLOPT_POSTFIELDS => json_encode([
"to" => "+237690000001",
"template" => [
"name" => "livraison_demain_presence",
"language" => "fr",
"variables" => ["Awa", "demain entre 14 h et 16 h"],
],
"idempotency_key" => "livraison-CMD-1042",
]),
]);
$res = curl_exec($ch);
echo curl_getinfo($ch, CURLINFO_HTTP_CODE), " ", $res;
Python
import os, requests
res = requests.request(
"POST",
"https://wa-api.geskap.com/v1/messages",
headers={"Authorization": f"Bearer {os.environ['GESKAP_API_KEY']}"},
json={
"to": "+237690000001",
"template": {
"name": "livraison_demain_presence",
"language": "fr",
"variables": ["Awa", "demain entre 14 h et 16 h"],
},
"idempotency_key": "livraison-CMD-1042",
},
timeout=15,
)
print(res.status_code, res.json())
| Élément | Règle |
|---|---|
| Nombre de boutons | 2 au maximum par template |
| Libellé (text) | 25 caractères au plus |
| Type | quick_reply : pas de lien (url est ignoré) |
| Mélange | ne mélangez pas boutons quick_reply et boutons url dans un même template |
Le clic est un message entrant type: "text" ; son text est le libellé touché. Voir Savoir quel bouton le client a touché.
Attention
Piège : contrairement aux boutons sans template, vous ne choisissez pas d'id : l'envoi par l'API ne transmet aucun identifiant personnalisé. Aiguillez sur le libellé (text) et rattachez la réponse au dernier envoi fait à ce numéro from. Deux libellés identiques dans deux templates ne se distinguent pas par leur text : donnez-leur des libellés différents.
Attention
Piège : le libellé fait partie du template approuvé. Pour le changer, il faut soumettre une nouvelle version à Meta. Choisissez des libellés courts et stables (« Oui », « Non, reporter »).
Attention
Piège : après le clic, le client vous a écrit : la fenêtre de 24 h est ouverte, vous pouvez répondre en texte libre ou avec des boutons sans template. Pour le parcours complet d'un rappel de rendez-vous : Rappel la veille.
Un bouton qui ouvre une page web est un autre type de bouton, qui peut même porter un lien différent par client : voir Lien variable dans un bouton. Premier envoi, statuts et erreurs : Écrire à un client qui ne vous a jamais écrit.
Preuve — vérifié dans le code de l'API : api_schemas.py, templates.py, meta_webhooks.py, README.md.