Je suis une banque ou une microfinance

Oui : reçu instantané après une collecte terrain (PDF possible), échéance de remboursement, solde derrière lien + PIN et code de vérification, avec l'API.

Je suis une banque ou une microfinance

Astuce
Oui : reçu instantané après une collecte terrain (PDF possible), échéance de remboursement, solde derrière lien + PIN et code de vérification, avec l'API.

Ce que vous pouvez automatiser

BesoinCommentRecette
Reçu après une collecte terrainDans les 24 h : texte libre. Sinon : template recu_collecte avec le reçu en PDF en en-tête.PDF en en-tête · Répondre en texte libre
Échéance de remboursementTemplate echeance_remboursement quelques jours avant la date ; relance en cas de retard avec un autre template.Relance d'impayé · Boutons de template
Solde et opérationsLe client le demande donc il est dans les 24 h : message avec lien personnel + code PIN. Le solde n'est jamais écrit dans WhatsApp.Données sensibles : lien et PIN · Reconnaître le client par son numéro
Ouverture de compte accueillieTemplate compte_ouvert avec le nom de l'agent collecteur.Écrire le premier message
Code de vérification (OTP)En texte libre dans les 24 h, ou par lien unique ; le template OTP natif n'est pas encore utilisable par l'API.Code OTP

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.

Les templates à créer

NomCatégorieTexteBoutons
recu_collecteUTILITYBonjour {{1}}, nous avons bien reçu votre versement de {{2}} le {{3}} (référence {{4}}). Votre reçu est joint à ce message en PDF. Merci de votre confiance.en-tête PDF
echeance_remboursementUTILITYBonjour {{1}}, votre échéance de {{2}} est prévue le {{3}}. Vous pouvez régler auprès de votre agent collecteur ou en agence. Si vous avez déjà payé, merci d'ignorer ce message.réponse rapide : « Parler à un conseiller »
compte_ouvertUTILITYBonjour {{1}}, votre compte n° {{2}} est ouvert chez Microfinance Exemple. Votre agent collecteur est {{3}}. Votre code PIN vous est remis par l'agent, jamais par message.—

Exemple complet

Reçu de collecte, avec le PDF du reçu en en-tête. Création, une seule fois : le PDF d'exemple est envoyé en base64 avec son type MIME.

curl

curl -X POST "https://wa-api.geskap.com/v1/templates" \
  -H "Authorization: Bearer $GESKAP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "recu_collecte",
  "language": "fr",
  "category": "UTILITY",
  "body_text": "Bonjour {{1}}, nous avons bien reçu votre versement de {{2}} le {{3}} (référence {{4}}). Votre reçu est joint à ce message en PDF. Merci de votre confiance.",
  "example_values": ["Awa", "5 000 F", "30 octobre", "COL-2087"],
  "header_image_mime": "application/pdf",
  "header_image_base64": "JVBERi0xLjQK…"
}'

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": "recu_collecte",
    "language": "fr",
    "category": "UTILITY",
    "body_text": "Bonjour {{1}}, nous avons bien reçu votre versement de {{2}} le {{3}} (référence {{4}}). Votre reçu est joint à ce message en PDF. Merci de votre confiance.",
    "example_values": ["Awa", "5 000 F", "30 octobre", "COL-2087"],
    "header_image_mime": "application/pdf",
    "header_image_base64": "JVBERi0xLjQK…"
  }),
});
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" => "recu_collecte",
    "language" => "fr",
    "category" => "UTILITY",
    "body_text" => "Bonjour {{1}}, nous avons bien reçu votre versement de {{2}} le {{3}} (référence {{4}}). Votre reçu est joint à ce message en PDF. Merci de votre confiance.",
    "example_values" => ["Awa", "5 000 F", "30 octobre", "COL-2087"],
    "header_image_mime" => "application/pdf",
    "header_image_base64" => "JVBERi0xLjQK…",
  ]),
]);
$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": "recu_collecte",
        "language": "fr",
        "category": "UTILITY",
        "body_text": "Bonjour {{1}}, nous avons bien reçu votre versement de {{2}} le {{3}} (référence {{4}}). Votre reçu est joint à ce message en PDF. Merci de votre confiance.",
        "example_values": ["Awa", "5 000 F", "30 octobre", "COL-2087"],
        "header_image_mime": "application/pdf",
        "header_image_base64": "JVBERi0xLjQK…",
    },
    timeout=15,
)
print(res.status_code, res.json())

Envoi juste après chaque versement. header_document_url est l'adresse publique du PDF du jour, header_document_filename le nom affiché dans la bulle.

curl

curl -X POST "https://wa-api.geskap.com/v1/messages" \
  -H "Authorization: Bearer $GESKAP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "to": "+237690000016",
  "template": {
    "name": "recu_collecte",
    "language": "fr",
    "variables": ["Awa", "5 000 F", "30 octobre", "COL-2087"],
    "header_document_url": "https://exemple-microfinance.test/recus/COL-2087.pdf",
    "header_document_filename": "recu-COL-2087.pdf"
  }
}'

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": "+237690000016",
    "template": {
      "name": "recu_collecte",
      "language": "fr",
      "variables": ["Awa", "5 000 F", "30 octobre", "COL-2087"],
      "header_document_url": "https://exemple-microfinance.test/recus/COL-2087.pdf",
      "header_document_filename": "recu-COL-2087.pdf"
    }
  }),
});
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" => "+237690000016",
    "template" => [
      "name" => "recu_collecte",
      "language" => "fr",
      "variables" => ["Awa", "5 000 F", "30 octobre", "COL-2087"],
      "header_document_url" => "https://exemple-microfinance.test/recus/COL-2087.pdf",
      "header_document_filename" => "recu-COL-2087.pdf",
    ],
  ]),
]);
$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": "+237690000016",
        "template": {
            "name": "recu_collecte",
            "language": "fr",
            "variables": ["Awa", "5 000 F", "30 octobre", "COL-2087"],
            "header_document_url": "https://exemple-microfinance.test/recus/COL-2087.pdf",
            "header_document_filename": "recu-COL-2087.pdf",
        },
    },
    timeout=15,
)
print(res.status_code, res.json())

Conversation

Client  : Bonjour, quel est mon solde ?
Banque  : Pour votre sécurité, confirmez votre identité avec votre code PIN.
          Le lien est personnel et expire dans 10 minutes. Nous ne vous demanderons jamais votre PIN ici.
          https://exemple-microfinance.test/connexion/ab12cd
Client  : (ouvre le lien, saisit son PIN sur la page : le solde s'affiche là-bas)
Client  : Merci
Banque  : Avec plaisir, Awa.  [ Mes opérations ]  [ Menu ]
Webhook : message.inbound  type=text  text="Mes opérations"  button_id="operations"  (quand il touche un bouton)

Le principe est détaillé dans Données sensibles : lien et PIN ; le numéro identifie le client grâce à Reconnaître le client par son numéro.

Attention
Piège : Un solde, un numéro de compte complet ou un historique d'opérations ne s'écrivent jamais dans WhatsApp : lien personnel + code PIN saisi sur votre page, jamais dans la conversation. Si vous montrez un numéro de compte, masquez-le (••••4821).
Attention
Piège : n'envoyez pas de code de vérification dans un template UTILITY : Meta le requalifie ou le refuse. Voir Code OTP pour ce qui marche.

Preuve — vérifié dans le code de l'API : api_schemas.py ; appliqué par la démo WhatsApp : banque, engine.