Saltar al contenido principal

Webhooks de reservas

Los webhooks de reservas entregan un POST firmado a un endpoint HTTPS que tú controlas cada vez que una reserva cambia de estado en tu workspace — creada, confirmada, cancelada, reprogramada, rechazada, reasignada o marcada como inasistencia (no-show). Esta página cubre la lista de eventos, el payload, los encabezados, la verificación de firma y el contrato de entrega/reintentos. Para conocer la API de Bookings de solo lectura y una orientación rápida, empieza por la introducción a Bookings.

nota

Las suscripciones a webhooks se configuran desde los ajustes de Bookings de la app de Copera por un administrador del workspace — no se crean ni se gestionan a través de la Public API. Cada suscripción tiene una URL receptora, un conjunto de eventos y un secreto de firma.

Eventos

EventoSe dispara cuando
booking.createdSe crea una reserva (pendiente o confirmada).
booking.confirmedUna reserva se confirma.
booking.cancelledUna reserva se cancela.
booking.rescheduledUna reserva se reprograma a una nueva hora.
booking.declinedUna reserva pendiente es rechazada por el host.
booking.reassignedEl host de una reserva se reasigna (round-robin).
booking.no_showSe registra una inasistencia para el host o el booker.

Una suscripción recibe solo los eventos que incluye, y solo mientras está activa.

Payload

Cada entrega es un POST con un cuerpo 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" }
}
}

El bloque data son los datos de reserva de tu propio workspace, por lo que se incluyen los datos de contacto del booker. Los identificadores internos (el token de gestión de la reserva, la clave de idempotencia, los internos de ICS) nunca se envían.

Encabezados

EncabezadoValor
X-Copera-EventLa cadena del evento (p. ej. booking.confirmed).
X-Copera-Signaturesha256=<hex> — HMAC-SHA256 del cuerpo de la solicitud sin procesar (raw) usando el secreto de tu suscripción.
X-Copera-Webhook-VersionLa versión del contrato del payload (actualmente 1).

Verificar la firma

Calcula el HMAC-SHA256 del cuerpo de la solicitud sin procesar (raw) (antes de parsear el JSON) con el secreto de tu suscripción y compáralo en tiempo constante con el hex de 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);
}

Entrega y reintentos

  • Responde con un 2xx para confirmar la recepción.
  • Un 4xx se trata como un rechazo permanente — Copera no reintenta.
  • Un 5xx, un error de red o un timeout se reintenta con backoff exponencial (3 intentos en total). Haz que tu receptor sea idempotente — el mismo evento puede entregarse más de una vez.
  • Las URLs receptoras deben ser endpoints HTTPS públicos; las direcciones privadas o internas se rechazan.

Referencia