View Categories

Utiliser les webhooks Apenday

Les webhooks Apenday envoient à votre système une notification à chaque étape de la vie d’un rendez-vous : prise, modification, annulation, clôture et enquête de satisfaction.

Les types d’événements #

ÉvénementEnvoyé quand
meeting_confirmedUn rendez-vous est pris
meeting_updatedLe client modifie son rendez-vous, ou un conseiller ou un administrateur le déplace ou le réaffecte. Également envoyé quand les données personnelles du rendez-vous sont anonymisées
meeting_cancelledLe client annule son rendez-vous
meeting_cancelled_by_consultantUn conseiller ou un administrateur annule le rendez-vous, dans Apenday ou par l’API
meeting_terminatedLe conseiller marque le rendez-vous comme terminé, dans Apenday ou par l’API
meeting_missedLe conseiller marque le rendez-vous comme manqué, dans Apenday ou par l’API
meeting_ratedLe client renseigne l’enquête de satisfaction

Un webhook porte sur un seul événement : souscrivez un webhook par événement à suivre. Chaque notification indique son événement dans l’en-tête X-Apenday-Event, une même URL peut donc recevoir plusieurs événements.

Souscrire à un webhook #

Souscrivez depuis le back-office, comme décrit dans Gérer vos webhooks depuis le back-office, ou par l’API REST (documentation de la ressource Hooks).

Par l’API, envoyez une requête POST sur https://app.apenday.com/api/public/hooks, authentifiée par votre clé d’API (voir Utiliser l’API Apenday) :

POST /api/public/hooks
Content-Type: application/json
X-AUTH-TOKEN: votre-cle-api

{
    "url": "https://mydomain.com/url-a-notifier", // URL qui recevra les notifications
    "event": "meeting_confirmed" // Événement à suivre
}

L’URL doit commencer par https:// et être accessible depuis Internet. Une URL en http:// ou pointant vers une adresse privée est refusée avec un code 422.

Exemple de réponse :

{
    "@context": "/api/contexts/Hooks",
    "@id": "/api/public/hooks/03a84931-3bb6-47b5-8323-336c236a6b93",
    "@type": "Hooks",
    "event": "meeting_confirmed",
    "url": "https://mydomain.com/url-a-notifier",
    "enabled": true, // false une fois le webhook désactivé
    "signed": true, // Les notifications de ce webhook sont signées
    "secret": "9f2c8a...4e71" // Secret de signature, renvoyé uniquement ici
}

Pour vous désabonner, envoyez une requête DELETE sur l’adresse donnée par la propriété @id de la réponse.

Le secret de signature #

Le champ secret de la réponse ci-dessus n’est renvoyé qu’une seule fois, par la requête qui vient de créer l’abonnement. Il n’apparaît dans aucune autre réponse de l’API et n’est plus consultable ensuite. Enregistrez-le dans votre système au moment où vous le recevez.

Il vous sert à vérifier que les notifications reçues viennent bien d’Apenday et que leur contenu n’a pas été modifié en chemin. La marche à suivre, avec un exemple de vérification complet en PHP et un en JavaScript, est détaillée ici : Vérifier la signature des notifications de rendez-vous.

Le format des notifications #

Chaque notification est une requête POST vers l’URL du webhook, avec les en-têtes suivants :

En-têteContenu
Content-Typeapplication/json
X-Apenday-EventL’événement, parmi les valeurs du tableau ci-dessus. Exemple : meeting_confirmed
X-Apenday-Event-IdIdentifiant unique de l’événement, identique pour toutes les tentatives d’envoi et pour tous les webhooks qui reçoivent cet événement. Exemple : 3f6c1a2e-8d4b-4c7e-9a51-0b2e7d9c4f10
X-Apenday-Event-TimestampMoment de l’événement, en secondes écoulées depuis le 1er janvier 1970, en UTC. Identique pour toutes les tentatives d’envoi. Exemple : 1789479700

Un webhook signé ajoute les en-têtes X-Apenday-Timestamp et X-Apenday-Signature, décrits dans Vérifier la signature des notifications de rendez-vous.

Le corps porte l’état complet du rendez-vous au moment de l’envoi, et non les seuls champs modifiés. Son format est le même pour tous les événements :

{
  "@context": "/api/contexts/Appointment",
  "@id": "/api/public/appointments/XXXXX", // Adresse du rendez-vous dans l'API publique
  "@type": "Appointment",
  "id": "Identifiant_du_rendez-vous",
  "meeting_id": "Identifiant_de_levenement",
  "meeting_name": "Nom de l'évènement",
  "meeting_technical_name": "Nom technique de l'évènement",
  "meeting_type": "default", // default, call, video ou other
  "status": "scheduled", // scheduled, cancelled, cancelled_by_consultant, terminated ou missed
  "date": "2025-06-11T16:30:00+02:00", // date et heure de début
  "end_date": "2025-06-11T17:15:00+02:00", // date et heure de fin
  "consultants": [
    {
      "name": "Nom du conseiller",
      "email": "Adresse email du conseiller",
      "external_id": null // Votre identifiant de conseiller, s'il est renseigné
    }
  ],
  "customer_firstname": "Prénom du client", // "unknown" si le formulaire ne demande pas ce champ
  "customer_lastname": "Nom du client",
  "customer_email": "email du client",
  "customer_phone_number": "numéro de téléphone",
  "other_form_values": {
    // ... autres valeurs du formulaire, puis :
    "createdAt": "2025-06-01T08:12:00+00:00", // Création du rendez-vous, en UTC
    "updatedAt": "2025-06-02T06:45:00+00:00" // Dernière mise à jour du rendez-vous, en UTC
  },
  "agency_name": "Nom de l'agence",
  "agency_id": null, // Identifiant Apenday de l'agence
  "agency_external_id": null, // Identifiant de l'agence dans votre système
  "agency_crm_id": null, // Identifiant de l'agence dans votre CRM
  "satisfaction_score": null, // Note de l'enquête de satisfaction
  "satisfaction_comment": null, // Commentaire de l'enquête de satisfaction
  "utm_campain": null, // Paramètres UTM
  "utm_source": null, // Paramètres UTM
  "utm_medium": null, // Paramètres UTM
  "tags": [], // Libellés des tags posés sur le rendez-vous
  "front_actions": {
    // URLs des pages publiques du rendez-vous, voir ci-dessous
  }
}

Le contenu de front_actions #

Ce bloc rassemble les URLs des pages publiques du rendez-vous. Les clés présentes varient selon l’état du rendez-vous et le type d’évènement : ne considérez aucune d’elles comme garantie, et testez sa présence avant de l’utiliser.

CléPrésente quand
cancelLe rendez-vous est encore annulable
updateLe rendez-vous est encore modifiable
surveyLe rendez-vous peut être évalué
download_icsLe rendez-vous est au statut scheduled
video_url_userLe rendez-vous est une visio au statut scheduled : lien de la visio pour le client
video_url_consultantLe rendez-vous est une visio au statut scheduled, selon le paramétrage de l’événement : lien de la visio pour le conseiller

Le bloc front_actions est entièrement absent de la charge quand aucune action n’est disponible, ce qui est notamment le cas d’un rendez-vous passé. Ne comptez donc pas non plus sur la présence de la clé elle-même.

Répondre à une notification #

Répondez par un code 2xx. Apenday attend la réponse 10 secondes au plus sans activité, et 15 secondes au total : enregistrez la notification, répondez, puis traitez-la.

Réponse de votre systèmeEffet
2xxNotification délivrée
410 GoneLe webhook est désactivé. Il reste visible dans le back-office, où il se réactive, et une nouvelle souscription du même compte au même événement sur la même URL le réactive aussi
5xx, 408, 429, ou aucune réponseNouvelle tentative 1 minute, puis 5 minutes, puis 25 minutes après l’échec précédent. Au-delà, la notification est abandonnée
Tout autre code, redirection 3xx compriseÉchec enregistré sur le webhook, sans nouvelle tentative. Les redirections ne sont pas suivies

Une notification peut arriver deux fois, par exemple si votre système la traite mais répond trop tard. Dédoublonnez sur X-Apenday-Event-Id, identique pour toutes les tentatives d’un même événement.

Les notifications ne sont pas garanties dans l’ordre. Pour un même rendez-vous, identifié par le champ id, ignorez une notification dont X-Apenday-Event-Timestamp est antérieur à celui de la dernière notification traitée. Cet horodatage est précis à la seconde : en cas d’égalité, relisez le rendez-vous par l’API publique, à l’adresse donnée par @id.

Une relance porte l’état courant du rendez-vous. Le corps est relu à chaque tentative et non figé au moment de l’événement. Une confirmation relancée après une annulation porte donc le statut cancelled, alors que X-Apenday-Event vaut meeting_confirmed.

Modifier l’URL ou l’événement d’un webhook abandonne les envois en attente. Si vous corrigez l’URL alors qu’une relance est programmée, cette relance n’a pas lieu. Vérifiez les rendez-vous de la période concernée par l’API publique si vous suspectez un manque.

Powered by BetterDocs