Webhooks : envoyer vos réservations vers Airtable
Un webhook envoie automatiquement chaque réservation, déplacement ou annulation de vos pages Calenoo vers un autre outil : une base Airtable, ou tout outil capable de recevoir un webhook HTTPS (Zapier, Make, n8n…). Cette page explique comment le régler, ce que Calenoo envoie et ce qui se passe en cas de panne.
Dernière mise à jour :
À quoi servent les webhooks
Un webhook envoie automatiquement à l'adresse web de votre choix les informations de chaque réservation, de chaque déplacement et de chaque annulation, dès qu'ils ont lieu.
L'outil qui les reçoit peut les ranger dans un tableau, prévenir quelqu'un ou lancer d'autres actions. Calenoo se limite à l'envoi : la suite se règle dans cet outil.
Le réglage se fait une seule fois, dans vos Réglages, et vaut pour toutes vos pages de réservation. Vous pouvez enregistrer 3 adresses au plus.
Il suffit d'un compte Calenoo connecté : la rubrique « Webhooks » se trouve dans vos Réglages, à côté des pages de réservation.
Les webhooks se combinent avec la validation des demandes et les séances de groupe, deux autres fonctions avancées des pages de réservation. Voir le guide des fonctions avancées.
Pas à pas : Airtable
Ces étapes suivent la documentation d'Airtable sur le déclencheur « When webhook received » (source, lue le 2 novembre 2026). Si l'écran d'Airtable diffère de ce qui est décrit ici, sa page d'aide fait foi.
- Dans votre base Airtable, ouvrez « Automations » et créez une automatisation.
- Ajoutez un déclencheur et choisissez « When webhook received ». Airtable affiche une adresse web unique : copiez-la.
- Dans Calenoo, ouvrez Réglages › Webhooks, collez l'adresse dans « Adresse de réception » et cliquez sur « Ajouter ».
- Laissez la case « Signer les envois » décochée : Airtable ne sait pas vérifier une signature.
- Cliquez sur « Envoyer un test ». Calenoo envoie un exemple de réservation complet, sans champ vide, et affiche « Test reçu » quand Airtable accepte l'envoi.
- Dans Airtable, lancez le test du déclencheur (bouton « Run test »). Airtable utilise l'envoi de test comme exemple pour les étapes suivantes.
- Ajoutez les actions qui utiliseront ces données et associez-y les champs reçus. Pour retrouver un rendez-vous déplacé ou annulé, utilisez
booking.idcomme identifiant. - Testez chaque étape, puis activez l'automatisation (de OFF à ON). Dès lors, chaque réservation de vos pages part vers Airtable.
Ce que dit Airtable de ce déclencheur
Relevé sur la page d'aide d'Airtable le 2 novembre 2026. Ces limites sont celles d'Airtable et peuvent changer.
- Seules les requêtes POST sont acceptées, avec un en-tête
Content-Typeàapplication/jsonpour du JSON. C'est ce que Calenoo envoie. - Un envoi ne doit pas dépasser 100 kb, et le déclencheur accepte au plus cinq requêtes par seconde.
- Chaque envoi qui lance une automatisation compte dans les limites d'exécutions de votre plan Airtable. Le déclencheur est proposé dans tous les types de plan, avec des limites qui varient.
- Airtable ne gère pas la vérification de signature : gardez la signature de Calenoo désactivée pour Airtable.
- Toute personne qui connaît l'adresse du déclencheur peut lancer votre automatisation. Ne la partagez pas.
Les événements envoyés
Calenoo envoie tous les événements du tableau, sans sélection possible : votre outil lit le champ event et garde ceux qui l'intéressent.
| Événement | Quand il est envoyé |
|---|---|
booking.created | Un invité réserve sur une page sans validation. |
booking.requested | Un invité envoie une demande sur une page « sur validation » (status vaut pending, request_expires_at donne l'échéance). |
booking.accepted | Vous acceptez la demande (status passe à confirmed, previous_status vaut pending ; le lien de visioconférence est ajouté s'il y en a un). |
booking.declined | Vous refusez la demande (status vaut declined). |
booking.expired | La demande n'a pas reçu de réponse avant l'échéance (status vaut expired). |
booking.rescheduled | L'invité déplace son rendez-vous ou sa demande (previous_start donne l'ancien début ; une demande reste pending). |
booking.cancelled | L'invité annule son rendez-vous ou retire sa demande, ou vous annulez depuis Calenoo (previous_status donne l'état d'avant). |
Chaque envoi concerne un seul rendez-vous. Pour une page de groupe (plusieurs places par créneau), chaque participant fait l'objet d'un envoi distinct, avec son propre booking.id et le booking.session_id de sa séance, le même pour tous ses participants.
Le format des données
Chaque envoi est une requête POST dont le corps est du JSON (version 1). Voici un exemple. Le bouton « Envoyer un test » envoie le même format, avec test à true et tous les champs remplis.
{
"version": 1,
"event": "booking.created",
"event_id": "5d0c6b0e-6b0a-4a52-9d5c-2f1d3c9a7e11",
"occurred_at": "2026-11-02T18:00:00Z",
"test": false,
"booking": {
"id": "b3f1c2a4-8d7e-4c6b-9a10-5e2f4d8c1a77",
"status": "confirmed",
"previous_status": null,
"start": "2026-11-07T09:00:00Z",
"end": "2026-11-07T10:00:00Z",
"start_local": "2026-11-07T10:00:00+01:00",
"end_local": "2026-11-07T11:00:00+01:00",
"timezone": "Europe/Zurich",
"duration_minutes": 60,
"previous_start": null,
"location": "Bern",
"meeting_url": null,
"language": "de",
"request_expires_at": null,
"seats": null,
"session_id": null,
"invitee": {
"name": "Jeanne Fit",
"email": "jeanne@example.ch",
"note": "Looking forward to it"
}
},
"page": {
"id": "9a4e7d52-3c1b-4f08-8e66-0b7d2a5c9f33",
"slug": "personal-training",
"title": "Personal Training"
}
}Les champs principaux
event: l'événement (voir le tableau ci-dessus).event_id: un identifiant commun à toutes les adresses qui reçoivent le même événement.occurred_at: l'heure de l'événement, en heure universelle (UTC).booking.id: l'identifiant du rendez-vous. C'est la clé à utiliser pour le retrouver.booking.statusetbooking.previous_status: l'état du rendez-vous et son état précédent (nulls'il n'y en a pas).booking.startetbooking.end: début et fin en heure universelle (UTC).booking.start_localetbooking.end_local: les mêmes, avec l'heure et le décalage du fuseau de la page (booking.timezone).booking.duration_minutes: la durée en minutes.booking.previous_start: l'ancien début, pour un déplacement ;nullsinon.booking.location,booking.languageetbooking.meeting_url: le lieu de la page, la langue de la réservation et le lien de visioconférence (nulls'il n'y en a pas). Une demande en attente n'a pas encore de lien : il arrive avecbooking.accepted.booking.request_expires_at: l'échéance d'une demande à valider (48 heures au plus, jamais après le début du rendez-vous),nullsinon. Elle reste renseignée après la décision.booking.seats: le nombre de places par créneau d'une page de groupe,nullpour un rendez-vous individuel.booking.session_id: l'identifiant de la séance d'une page de groupe, le même pour tous ses participants,nullpour un rendez-vous individuel. Il reste renseigné après une annulation ; un déplacement donne celui de la nouvelle séance.booking.invitee: le nom, l'adresse e-mail et le message (note,nulls'il n'y en a pas) de l'invité.page: l'identifiant, l'adresse courte (slug) et le titre de la page de réservation.
Les en-têtes
Content-Type: application/jsonUser-Agent: Calenoo-Webhook/1Calenoo-Event: l'événement, par exemplebooking.created.Calenoo-Delivery: l'identifiant de l'envoi. Il reste identique à chaque nouvel essai : servez-vous-en pour ignorer un doublon.Calenoo-Signature: présent seulement si la signature est activée (voir ci-dessous).
La structure de la version 1 ne change pas : toute modification passerait par une version 2.
Vérifier la signature
Cette étape est facultative. Si vous cochez « Signer les envois », Calenoo ajoute l'en-tête Calenoo-Signature à chaque envoi : votre outil peut ainsi vérifier que l'envoi vient bien de Calenoo et qu'il n'a pas été modifié.
L'en-tête a la forme t=<secondes>,v1=<signature>. t est l'heure d'envoi en secondes (heure Unix). v1 est un HMAC-SHA256 en hexadécimal, calculé avec votre secret sur le texte t.corps : t, un point, puis le corps de la requête tel qu'il a été reçu.
Le secret commence par whsec_ : utilisez-le en entier, préfixe compris. Calenoo ne l'affiche qu'une seule fois, à sa création : copiez-le aussitôt. Si vous le perdez, créez-en un autre avec « Nouveau secret ».
Voici un exemple en JavaScript (Node.js). Calculez toujours la signature sur le texte brut reçu, avant tout JSON.parse. Refusez aussi un envoi dont t est trop ancien : ici, plus de 5 minutes.
import crypto from "node:crypto";
function isValidSignature(rawBody, header, secret) {
const parts = Object.fromEntries(header.split(",").map((part) => part.split("=")));
const expected = crypto
.createHmac("sha256", secret)
.update(`${parts.t}.${rawBody}`)
.digest("hex");
const received = Buffer.from(parts.v1 ?? "", "hex");
const computed = Buffer.from(expected, "hex");
const fresh = Math.abs(Date.now() / 1000 - Number(parts.t)) < 300;
return fresh && received.length === computed.length && crypto.timingSafeEqual(received, computed);
}Node.js met les noms d'en-têtes en minuscules : l'en-tête se lit avec req.headers['calenoo-signature'].
En cas de panne
Un envoi réussit quand votre outil répond par un code 2xx en moins de 10 secondes. Calenoo ne lit jamais le contenu de la réponse et ne suit aucune redirection : une réponse 3xx compte comme un échec.
- Réponse 408, 425, 429 ou 5xx, délai dépassé ou coupure réseau : Calenoo réessaie, 8 essais au plus (le premier compris), après 1, 2, 5, 15 et 30 minutes, puis 1 heure et 2 heures. Si la réponse contient un en-tête
Retry-After(en secondes) plus long que cette attente, Calenoo l'attend, jusqu'à 6 heures au plus. - Toute autre réponse 4xx (404 ou 401, par exemple) : échec définitif, sans nouvel essai.
- Les envois d'une même adresse partent dans l'ordre : un envoi en attente d'un nouvel essai retient les suivants.
- Après 5 envois de suite en échec définitif, Calenoo désactive l'adresse et vous envoie un e-mail. Un envoi réussi remet le compteur à zéro.
- Les envois manqués ne sont pas renvoyés quand vous réactivez l'adresse. Une fois le problème réglé, cliquez sur « Réactiver » dans Réglages › Webhooks.
Un même envoi peut arriver deux fois, par exemple si votre outil l'a bien reçu mais que sa réponse s'est perdue. Comme Calenoo-Delivery est identique à chaque essai, votre outil peut ignorer un doublon.
Le journal « Derniers envois » de Réglages › Webhooks montre l'événement, le code de réponse et l'état de chaque envoi. Il est conservé 30 jours, sans le contenu des envois.
Sécurité et données personnelles
- Calenoo envoie uniquement en
https, sur le port 443. Une adresse avec identifiant ou mot de passe, ou sur un autre port, est refusée. - Les adresses privées ou locales (réseau interne,
localhost…) sont refusées à l'enregistrement, puis revérifiées avant chaque envoi. - Jamais dans les envois : les liens et jetons pour gérer le rendez-vous, l'empreinte IP, votre adresse e-mail et les références de votre agenda.
- Le contenu de chaque envoi est effacé dès que l'envoi est terminé.
- Vous gardez la main : vous pouvez mettre une adresse en pause, la signer, changer son secret ou la supprimer à tout moment.
Chaque envoi contient des données personnelles : le nom, l'adresse e-mail et le message de l'invité, avec l'horaire du rendez-vous. Elles vont à l'outil que vous avez choisi, qui les traite sous sa propre responsabilité et selon ses propres conditions. Voir la politique de confidentialité.
Questions fréquentes
- Faut-il un plan Airtable payant ?
- Airtable indique que le déclencheur « When webhook received » est proposé dans tous les types de plan, avec des limites qui varient. Chaque envoi qui lance une automatisation compte dans les limites d'exécutions de votre plan : vérifiez-les dans votre compte Airtable (source).
- Mon outil est en panne : perd-on des réservations ?
- Non, les réservations restent dans Calenoo. Seul l'envoi vers votre outil est concerné : Calenoo réessaie jusqu'à 8 fois, avec des attentes de 1 minute à 2 heures. Après 5 envois de suite en échec définitif, l'adresse est désactivée et les envois manqués ne sont pas renvoyés.
- Puis-je recevoir seulement certains événements ?
- Non : Calenoo envoie tous les événements. Votre outil lit le champ
event(ou l'en-têteCalenoo-Event) et garde ceux qu'il veut traiter. - Comment éviter les doublons dans mon tableau ?
- Utilisez
booking.idcomme clé : un déplacement ou une annulation concerne le même rendez-vous et peut donc mettre à jour la même ligne. L'en-têteCalenoo-Deliveryidentifie chaque envoi et reste identique à chaque nouvel essai. - Puis-je envoyer vers un serveur de mon réseau interne ou sur un autre port ?
- Non. Calenoo envoie seulement en HTTPS, sur le port 443, vers une adresse publique.