Aller au contenu principal

Webhooks de bookings

Les webhooks de bookings livrent un POST signé à un endpoint HTTPS que vous contrôlez chaque fois qu'un booking transitionne dans votre workspace — créé, confirmé, annulé, replanifié, refusé, réassigné, ou signalé comme no-show. Cette page couvre la liste des événements, la charge utile, les en-têtes, la vérification de signature, et le contrat de livraison/retry. Pour l'API Bookings en lecture seule et une orientation rapide, commencez par l'introduction Bookings.

note

Les abonnements webhook sont configurés depuis les paramètres Bookings de l'app Copera par un administrateur du workspace — ils ne sont pas créés ni gérés via la Public API. Chaque abonnement a une URL de récepteur, un ensemble d'événements, et un secret de signature.

Événements

ÉvénementSe déclenche lorsque
booking.createdUn booking est créé (pending ou confirmed).
booking.confirmedUn booking est confirmé.
booking.cancelledUn booking est annulé.
booking.rescheduledUn booking est replanifié à une nouvelle heure.
booking.declinedUn booking en attente est refusé par l'hôte.
booking.reassignedL'hôte d'un booking est réassigné (round-robin).
booking.no_showUn no-show est enregistré pour l'hôte ou le booker.

Un abonnement ne reçoit que les événements qu'il inclut, et uniquement tant qu'il est actif.

Charge utile

Chaque livraison est un POST avec un corps JSON :

{
"event": "booking.confirmed",
"createdAt": "2026-07-06T09:00:00.000Z",
"data": {
"id": "665f…",
"status": "CONFIRMED",
"bookingTypeId": "665f…",
"bookingTypeTitle": "Intro Call",
"start": "2026-07-08T15:00:00.000Z",
"end": "2026-07-08T15:30:00.000Z",
"durationMinutes": 30,
"timezoneAtBooking": "America/Sao_Paulo",
"hosts": [{ "userId": "665f…", "role": "ORGANIZER" }],
"booker": {
"name": "Alice Booker",
"email": "[email protected]",
"phone": "+15551234567",
"timezone": "America/Sao_Paulo",
"locale": "en"
},
"guests": [],
"answers": [{ "questionId": "q1", "label": "Topic", "value": "Pricing" }],
"location": { "type": "MEETING_CHANNEL" }
}
}

Le bloc data contient les données de booking de votre propre workspace, donc les coordonnées du booker sont incluses. Les champs internes sensibles ne sont jamais envoyés.

Corréler un événement webhook avec la Public API

La charge utile du webhook porte data.id. Passez-le directement à GET /public/v1/bookings/{id} pour récupérer le détail complet du booking :

curl -H "Authorization: Bearer $TOKEN" \
"https://api.copera.ai/public/v1/bookings/${data.id}"

Utilisez la même valeur data.id avec une requête Bookings API authentifiée chaque fois que vous devez corréler des événements webhook avec le détail complet du booking.

En-têtes

En-têteValeur
X-Copera-EventLa chaîne d'événement (p. ex. booking.confirmed).
X-Copera-Signaturesha256=<hex> — HMAC-SHA256 du corps de requête brut en utilisant le secret de votre abonnement.
X-Copera-Webhook-VersionLa version du contrat de charge utile (actuellement 1).

Vérifier la signature

Calculez le HMAC-SHA256 du corps de requête brut (avant le parsing JSON) avec le secret de votre abonnement et comparez-le en temps constant à l'hex dans X-Copera-Signature :

import { createHmac, timingSafeEqual } from "node:crypto";

function isValidSignature(rawBody, header, secret) {
const expected =
"sha256=" + createHmac("sha256", secret).update(rawBody, "utf8").digest("hex");
const a = Buffer.from(header);
const b = Buffer.from(expected);
return a.length === b.length && timingSafeEqual(a, b);
}

Livraison et retries

  • Répondez avec un 2xx pour accuser réception.
  • Un 4xx est traité comme un rejet permanent — Copera ne réessaie pas.
  • Un 5xx, une erreur réseau ou un timeout est réessayé avec un backoff exponentiel (3 tentatives au total). Rendez votre récepteur idempotent — le même événement peut être livré plus d'une fois.
  • Les URLs de récepteur doivent être des endpoints HTTPS publics ; les adresses privées ou internes sont rejetées.

Référence