Oui, même si le client ne vous a pas écrit : template UTILITY avec montant et échéance en variables, et un bouton « Payer » dont le lien est propre à chaque facture.
Astuce
Oui, même si le client ne vous a pas écrit : template UTILITY avec montant et échéance en variables, et un bouton « Payer » dont le lien est propre à chaque facture.
Une facture n'est pas réglée trois jours après l'échéance. Votre logiciel envoie un rappel WhatsApp avec le montant, la date, et un bouton qui ouvre la page de paiement de cette facture.
Vous : Bonjour Paul, la facture F-2026-118 de 45 000 FCFA était due le 27/10.
Vous pouvez la régler en ligne en un clic.
[ Payer la facture ] → https://pay.exemple.com/f/F-2026-118
Client : (touche le bouton, paie sur votre page)
Créez le template une fois. Le lien du bouton se termine par {{1}}, avec un exemple complet :
curl
curl -X POST "https://wa-api.geskap.com/v1/templates" \
-H "Authorization: Bearer $GESKAP_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "relance_facture",
"language": "fr",
"category": "UTILITY",
"body_text": "Bonjour {{1}}, la facture {{2}} de {{3}} était due le {{4}}. Vous pouvez la régler en ligne avec le bouton ci-dessous.",
"example_values": ["Paul", "F-2026-118", "45 000 FCFA", "27/10/2026"],
"buttons": [
{
"kind": "url",
"text": "Payer la facture",
"url": "https://pay.exemple.com/f/{{1}}",
"url_example": "https://pay.exemple.com/f/F-2026-118"
}
]
}'
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": "relance_facture",
"language": "fr",
"category": "UTILITY",
"body_text": "Bonjour {{1}}, la facture {{2}} de {{3}} était due le {{4}}. Vous pouvez la régler en ligne avec le bouton ci-dessous.",
"example_values": ["Paul", "F-2026-118", "45 000 FCFA", "27/10/2026"],
"buttons": [
{
"kind": "url",
"text": "Payer la facture",
"url": "https://pay.exemple.com/f/{{1}}",
"url_example": "https://pay.exemple.com/f/F-2026-118"
}
]
}),
});
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" => "relance_facture",
"language" => "fr",
"category" => "UTILITY",
"body_text" => "Bonjour {{1}}, la facture {{2}} de {{3}} était due le {{4}}. Vous pouvez la régler en ligne avec le bouton ci-dessous.",
"example_values" => ["Paul", "F-2026-118", "45 000 FCFA", "27/10/2026"],
"buttons" => [
[
"kind" => "url",
"text" => "Payer la facture",
"url" => "https://pay.exemple.com/f/{{1}}",
"url_example" => "https://pay.exemple.com/f/F-2026-118",
],
],
]),
]);
$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": "relance_facture",
"language": "fr",
"category": "UTILITY",
"body_text": "Bonjour {{1}}, la facture {{2}} de {{3}} était due le {{4}}. Vous pouvez la régler en ligne avec le bouton ci-dessous.",
"example_values": ["Paul", "F-2026-118", "45 000 FCFA", "27/10/2026"],
"buttons": [
{
"kind": "url",
"text": "Payer la facture",
"url": "https://pay.exemple.com/f/{{1}}",
"url_example": "https://pay.exemple.com/f/F-2026-118",
},
],
},
timeout=15,
)
print(res.status_code, res.json())
Une fois le template APPROVED, envoyez-le pour chaque facture. button_url_param porte la fin du lien :
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": "relance_facture",
"language": "fr",
"variables": ["Paul", "F-2026-118", "45 000 FCFA", "27/10/2026"],
"button_url_param": "F-2026-118"
},
"idempotency_key": "relance-F-2026-118-1"
}'
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": "relance_facture",
"language": "fr",
"variables": ["Paul", "F-2026-118", "45 000 FCFA", "27/10/2026"],
"button_url_param": "F-2026-118"
},
"idempotency_key": "relance-F-2026-118-1"
}),
});
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" => "relance_facture",
"language" => "fr",
"variables" => ["Paul", "F-2026-118", "45 000 FCFA", "27/10/2026"],
"button_url_param" => "F-2026-118",
],
"idempotency_key" => "relance-F-2026-118-1",
]),
]);
$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": "relance_facture",
"language": "fr",
"variables": ["Paul", "F-2026-118", "45 000 FCFA", "27/10/2026"],
"button_url_param": "F-2026-118",
},
"idempotency_key": "relance-F-2026-118-1",
},
timeout=15,
)
print(res.status_code, res.json())
Attention
Piège : catégorie UTILITY, ton factuel : une relance qui ressemble à une promotion est reclassée MARKETING par Meta, et l'envoi marketing est bloqué par défaut sur votre compte. Pas de menace ni de majuscules.
Attention
Piège : button_url_param est la fin du lien (F-2026-118), jamais l'adresse complète : un domaine différent est refusé. Voir Un lien unique dans un bouton.
Pour joindre la facture elle-même, utilisez un template à en-tête document : Envoyer un PDF. Pour qu'un relancé n'en reçoive pas deux, passez un idempotency_key par facture et par relance : Idempotence.
Preuve — vérifié dans le code de l'API : api_schemas.py, api_send.py.