Je suis une clinique ou un hôpital

Oui : rappel de rendez-vous la veille, arrivée du patient avec son rang en salle d'attente, « résultats disponibles » avec lien + PIN (jamais les valeurs) et prise de rendez-vous avec créneaux libres, avec l'API.

Je suis une clinique ou un hôpital

Astuce
Oui : rappel de rendez-vous la veille, arrivée du patient avec son rang en salle d'attente, « résultats disponibles » avec lien + PIN (jamais les valeurs) et prise de rendez-vous avec créneaux libres, avec l'API.

Ce que vous pouvez automatiser

BesoinCommentRecette
Rappel de rendez-vous la veilleHors 24 h : template rappel_rdv_veille avec deux boutons Confirmer / Annuler. Dans les 24 h : boutons libres.Rappel de rendez-vous la veille · Boutons de template
Patient arrivé en salle d'attente, avec son rangDans les 24 h : texte libre « vous êtes le patient n° 3 ». Sinon : template patient_salle_attente.Notification d'arrivée sur place · Répondre en texte libre
Résultats d'examens disponiblesTemplate resultats_disponibles avec un bouton à lien variable vers votre page protégée par PIN. Jamais les valeurs dans WhatsApp.Données sensibles : lien et PIN · Lien variable dans un bouton
Prise de rendez-vous avec créneaux libresDans les 24 h : liste des spécialités, puis liste des créneaux libres (10 lignes), puis confirmation par boutons.Menu en liste · Créneaux et places restantes · Formulaire pas à pas
Reconnaître le patient dès son premier messageLe numéro identifie la fiche patient ; le webhook le fournit.Reconnaître le client par son numéro

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
rappel_rdv_veilleUTILITYBonjour {{1}}, nous vous rappelons votre rendez-vous de {{2}} avec {{3}} demain à {{4}} à la Clinique Exemple. Merci d'arriver 15 minutes avant, avec votre carnet de santé.réponse rapide : « Je confirme », « Je dois annuler »
patient_salle_attenteUTILITYBonjour {{1}}, votre arrivée est bien enregistrée. Vous êtes le patient n° {{2}} pour {{3}}. Nous vous appellerons dans quelques instants.—
resultats_disponiblesUTILITYBonjour {{1}}, votre résultat d'examen du {{2}} est disponible. Pour des raisons de confidentialité, il n'est pas envoyé dans cette conversation : ouvrez-le avec votre code PIN en touchant le bouton ci-dessous.lien variable : « Consulter »
confirmation_rdvUTILITYBonjour {{1}}, votre rendez-vous de {{2}} est confirmé le {{3}} à {{4}} (référence {{5}}). Pour le déplacer ou l'annuler, touchez un bouton ci-dessous.réponse rapide : « Déplacer mon RDV », « Annuler mon RDV »

Exemple complet

Notification « résultats disponibles » : le message ne contient aucune valeur, seulement un lien personnel dont la fin change à chaque patient. 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": "resultats_disponibles",
  "language": "fr",
  "category": "UTILITY",
  "body_text": "Bonjour {{1}}, votre résultat d'\''examen du {{2}} est disponible. Pour des raisons de confidentialité, il n'\''est pas envoyé dans cette conversation : ouvrez-le avec votre code PIN en touchant le bouton ci-dessous.",
  "example_values": ["Awa", "28 octobre"],
  "buttons": [
    {
      "kind": "url",
      "text": "Consulter",
      "url": "https://clinique-exemple.test/resultat/{{1}}",
      "url_example": "https://clinique-exemple.test/resultat/ab12cd"
    }
  ]
}'

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": "resultats_disponibles",
    "language": "fr",
    "category": "UTILITY",
    "body_text": "Bonjour {{1}}, votre résultat d'examen du {{2}} est disponible. Pour des raisons de confidentialité, il n'est pas envoyé dans cette conversation : ouvrez-le avec votre code PIN en touchant le bouton ci-dessous.",
    "example_values": ["Awa", "28 octobre"],
    "buttons": [
      {
        "kind": "url",
        "text": "Consulter",
        "url": "https://clinique-exemple.test/resultat/{{1}}",
        "url_example": "https://clinique-exemple.test/resultat/ab12cd"
      }
    ]
  }),
});
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" => "resultats_disponibles",
    "language" => "fr",
    "category" => "UTILITY",
    "body_text" => "Bonjour {{1}}, votre résultat d'examen du {{2}} est disponible. Pour des raisons de confidentialité, il n'est pas envoyé dans cette conversation : ouvrez-le avec votre code PIN en touchant le bouton ci-dessous.",
    "example_values" => ["Awa", "28 octobre"],
    "buttons" => [
      [
        "kind" => "url",
        "text" => "Consulter",
        "url" => "https://clinique-exemple.test/resultat/{{1}}",
        "url_example" => "https://clinique-exemple.test/resultat/ab12cd",
      ],
    ],
  ]),
]);
$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": "resultats_disponibles",
        "language": "fr",
        "category": "UTILITY",
        "body_text": "Bonjour {{1}}, votre résultat d'examen du {{2}} est disponible. Pour des raisons de confidentialité, il n'est pas envoyé dans cette conversation : ouvrez-le avec votre code PIN en touchant le bouton ci-dessous.",
        "example_values": ["Awa", "28 octobre"],
        "buttons": [
            {
                "kind": "url",
                "text": "Consulter",
                "url": "https://clinique-exemple.test/resultat/{{1}}",
                "url_example": "https://clinique-exemple.test/resultat/ab12cd",
            },
        ],
    },
    timeout=15,
)
print(res.status_code, res.json())

Une fois le template APPROVED, envoi à chaque résultat prêt. button_url_param est la fin du lien (jamais l'adresse complète).

curl

curl -X POST "https://wa-api.geskap.com/v1/messages" \
  -H "Authorization: Bearer $GESKAP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "to": "+237690000011",
  "template": {
    "name": "resultats_disponibles",
    "language": "fr",
    "variables": ["Awa", "28 octobre"],
    "button_url_param": "ab12cd"
  }
}'

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": "+237690000011",
    "template": {
      "name": "resultats_disponibles",
      "language": "fr",
      "variables": ["Awa", "28 octobre"],
      "button_url_param": "ab12cd"
    }
  }),
});
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" => "+237690000011",
    "template" => [
      "name" => "resultats_disponibles",
      "language" => "fr",
      "variables" => ["Awa", "28 octobre"],
      "button_url_param" => "ab12cd",
    ],
  ]),
]);
$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": "+237690000011",
        "template": {
            "name": "resultats_disponibles",
            "language": "fr",
            "variables": ["Awa", "28 octobre"],
            "button_url_param": "ab12cd",
        },
    },
    timeout=15,
)
print(res.status_code, res.json())

Conversation

Patient  : Bonjour
Clinique : Bonjour Awa ! Que souhaitez-vous faire ?
           [ Prendre RDV ]  [ Mes RDV ]  [ Mes résultats ]
Patient  : (touche « Prendre RDV »)
Clinique : Quelle spécialité ?  (liste : Médecine générale, Pédiatrie, Cardiologie…)
Patient  : (choisit « Cardiologie »)
Clinique : Créneaux libres demain ?  (liste : 08:30, 09:30, 10:30…)
Patient  : (choisit « 09:30 »)
Webhook  : message.inbound  type=text  text="09:30"  button_id="slot:2026-11-03T09:30"
Clinique : Rendez-vous confirmé (RDV-0042), cardiologie demain à 09:30.
           Vous recevrez un rappel la veille.
           [ Mes RDV ]  [ Menu ]

Les écrans viennent de Menu en liste et Boutons de réponse rapide ; le choix revient par Récupérer le clic.

Attention
Piège : Les résultats, diagnostics et ordonnances ne s'écrivent jamais en clair dans WhatsApp : message « disponible » + lien personnel + code PIN saisi sur votre page, jamais dans la conversation. Même un seul chiffre est une donnée de santé.
Attention
Piège : Un rappel qui dérive vers le conseil médical ou la promotion d'un service risque d'être reclassé MARKETING par Meta, bloqué par défaut sur votre compte. Restez informatif.

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