Oui : livreur en route avec lien de suivi, colis livré, créneau de livraison à confirmer et photo de preuve, avec l'API.
Astuce
Oui : livreur en route avec lien de suivi, colis livré, créneau de livraison à confirmer et photo de preuve, avec l'API.
| Besoin | Comment | Recette |
|---|---|---|
| Livreur en route, avec lien de suivi | Template livreur_en_route avec un bouton à lien variable vers votre page de suivi. L'API n'envoie pas de position en direct. | Lien variable dans un bouton · Statut de livraison |
| Colis livré | Template colis_livre ; si le destinataire vous a écrit il y a moins de 24 h, texte libre. | Écrire le premier message · Répondre en texte libre |
| Créneau de livraison à confirmer | Template creneau_livraison avec deux boutons ; ensuite, dans les 24 h, liste d'autres créneaux. | Créneaux et places restantes · Confirmer, annuler, modifier |
| Photo de preuve de livraison | Template preuve_livraison_photo avec la photo en en-tête. À l'inverse, la photo envoyée par le client (colis abîmé) arrive sur votre webhook. | Image en en-tête · Recevoir photo et document |
| Suivre l'état de chaque message | Le webhook de statut dit si le message est distribué ou lu. | Statut de livraison |
Hors des 24 h qui suivent le dernier message du client, seul un template approuvé par Meta peut partir. Dans les 24 h, vous composez librement : boutons (3 de 20 caractères au plus), liste (10 lignes de 24 caractères au plus) ou texte libre.
| Nom | Catégorie | Texte | Boutons |
|---|---|---|---|
| livreur_en_route | UTILITY | Bonjour {{1}}, votre livreur {{2}} est en route avec votre colis {{3}}. Arrivée estimée : {{4}}. Suivez sa progression avec le bouton ci-dessous. | lien variable : « Suivre mon livreur » |
| colis_livre | UTILITY | Bonjour {{1}}, votre colis {{2}} a été livré le {{3}} à {{4}}. Si vous n'êtes pas à l'origine de cette réception, répondez à ce message. | — |
| creneau_livraison | UTILITY | Bonjour {{1}}, nous livrons votre colis {{2}} le {{3}} entre {{4}} et {{5}}. Ce créneau vous convient-il ? | réponse rapide : « Oui, ça me convient », « Proposer un autre » |
| preuve_livraison_photo | UTILITY | Bonjour {{1}}, voici la photo de preuve de livraison de votre colis {{2}}, prise le {{3}} à {{4}} par {{5}}. En cas de problème, répondez à ce message. | en-tête image |
Livreur en route : le bouton ouvre votre page de suivi, la fin du lien (le numéro de livraison) change à chaque colis. Création, une seule fois.
curl
curl -X POST "https://wa-api.geskap.com/v1/templates" \
-H "Authorization: Bearer $GESKAP_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "livreur_en_route",
"language": "fr",
"category": "UTILITY",
"body_text": "Bonjour {{1}}, votre livreur {{2}} est en route avec votre colis {{3}}. Arrivée estimée : {{4}}. Suivez sa progression avec le bouton ci-dessous.",
"example_values": ["Awa", "Paul", "LIV-3051", "15h30"],
"buttons": [
{
"kind": "url",
"text": "Suivre mon livreur",
"url": "https://livraison-exemple.test/suivi/{{1}}",
"url_example": "https://livraison-exemple.test/suivi/LIV3051"
}
]
}'
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": "livreur_en_route",
"language": "fr",
"category": "UTILITY",
"body_text": "Bonjour {{1}}, votre livreur {{2}} est en route avec votre colis {{3}}. Arrivée estimée : {{4}}. Suivez sa progression avec le bouton ci-dessous.",
"example_values": ["Awa", "Paul", "LIV-3051", "15h30"],
"buttons": [
{
"kind": "url",
"text": "Suivre mon livreur",
"url": "https://livraison-exemple.test/suivi/{{1}}",
"url_example": "https://livraison-exemple.test/suivi/LIV3051"
}
]
}),
});
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" => "livreur_en_route",
"language" => "fr",
"category" => "UTILITY",
"body_text" => "Bonjour {{1}}, votre livreur {{2}} est en route avec votre colis {{3}}. Arrivée estimée : {{4}}. Suivez sa progression avec le bouton ci-dessous.",
"example_values" => ["Awa", "Paul", "LIV-3051", "15h30"],
"buttons" => [
[
"kind" => "url",
"text" => "Suivre mon livreur",
"url" => "https://livraison-exemple.test/suivi/{{1}}",
"url_example" => "https://livraison-exemple.test/suivi/LIV3051",
],
],
]),
]);
$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": "livreur_en_route",
"language": "fr",
"category": "UTILITY",
"body_text": "Bonjour {{1}}, votre livreur {{2}} est en route avec votre colis {{3}}. Arrivée estimée : {{4}}. Suivez sa progression avec le bouton ci-dessous.",
"example_values": ["Awa", "Paul", "LIV-3051", "15h30"],
"buttons": [
{
"kind": "url",
"text": "Suivre mon livreur",
"url": "https://livraison-exemple.test/suivi/{{1}}",
"url_example": "https://livraison-exemple.test/suivi/LIV3051",
},
],
},
timeout=15,
)
print(res.status_code, res.json())
Envoi quand le livreur démarre sa tournée. Le destinataire n'a pas besoin de vous avoir écrit.
curl
curl -X POST "https://wa-api.geskap.com/v1/messages" \
-H "Authorization: Bearer $GESKAP_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"to": "+237690000018",
"template": {
"name": "livreur_en_route",
"language": "fr",
"variables": ["Awa", "Paul", "LIV-3051", "15h30"],
"button_url_param": "LIV3051"
}
}'
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": "+237690000018",
"template": {
"name": "livreur_en_route",
"language": "fr",
"variables": ["Awa", "Paul", "LIV-3051", "15h30"],
"button_url_param": "LIV3051"
}
}),
});
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" => "+237690000018",
"template" => [
"name" => "livreur_en_route",
"language" => "fr",
"variables" => ["Awa", "Paul", "LIV-3051", "15h30"],
"button_url_param" => "LIV3051",
],
]),
]);
$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": "+237690000018",
"template": {
"name": "livreur_en_route",
"language": "fr",
"variables": ["Awa", "Paul", "LIV-3051", "15h30"],
"button_url_param": "LIV3051",
},
},
timeout=15,
)
print(res.status_code, res.json())
Livraison: Bonjour Awa, nous livrons votre colis LIV-3051 demain entre 14h et 16h. Ce créneau vous convient-il ?
[ Oui, ça me convient ] [ Proposer un autre ]
Client : (touche « Proposer un autre »)
Webhook : message.inbound type=text text="Proposer un autre" button_id="Proposer un autre"
Livraison : Quel créneau préférez-vous ? (liste : Demain 9h-11h, Demain 14h-16h, Après-demain 9h-11h…)
Client : (choisit « Demain 9h-11h »)
Livraison : Créneau modifié : demain entre 9h et 11h. [ Suivre mon colis ] [ Un conseiller ]
Le choix du créneau suit Créneaux et places restantes ; la décision se lit avec Récupérer le clic et se confirme avec Confirmer, annuler, modifier.
Attention
Piège : Il n'y a ni partage de position en direct ni carte dans l'API : le suivi passe par un lien vers VOTRE page de suivi, dans un bouton à lien variable. Un template n'accepte qu'un seul bouton de ce type, et jamais mélangé avec un bouton de réponse rapide.
Attention
Piège : L'image de preuve est fixée à l'envoi par header_image_url : une adresse HTTPS publique, en JPEG ou PNG. Un seul en-tête média par envoi : image OU document, jamais les deux.
Preuve — vérifié dans le code de l'API : api_schemas.py.