API de calendario para operadores
Conecta tu channel manager o tu sistema de reservas con la guía: mantén la disponibilidad al día, bloquea las fechas que vendes por otros canales y recibe cada reserva al instante.
Acceso
El dueño del negocio crea un token en Panel › API y conexiones con los permisos que necesita: disponibilidad:leer, disponibilidad:escribir y reservas:leer. El token se muestra una sola vez y se envía en cada solicitud:
curl -L https://embalsetopocoro.com/api/v1/servicios/ \ -H "Authorization: Bearer tpc_live_…"
- Fechas
YYYY-MM-DDen hora de Colombia (America/Bogota). En estadías y bloqueos, la fecha final es la de salida (exclusiva). - Hasta 120 solicitudes por minuto por token; rangos de hasta 366 días.
- Errores en JSON:
{ "error": { "codigo", "mensaje" } }. - Las rutas terminan en «/»; sigue las redirecciones si tu cliente no la pone.
Rutas
| Método | Ruta | Qué hace |
|---|---|---|
| GET | /api/v1/servicios/ | Tus servicios |
| GET | /api/v1/servicios/{id}/disponibilidad/ | Estado, cupo, cupo libre y precio por día |
| PUT | /api/v1/servicios/{id}/disponibilidad/ | Cambiar estado, cupo o precio por día (hasta 366 días) |
| GET | /api/v1/servicios/{id}/bloqueos/ | Fechas ocupadas fuera de la guía (API, iCal y manuales) |
| PUT | /api/v1/servicios/{id}/bloqueos/{uid}/ | Crear o reemplazar un bloqueo (idempotente) |
| DELETE | /api/v1/servicios/{id}/bloqueos/{uid}/ | Borrar un bloqueo creado por la API |
| GET | /api/v1/reservas/ | Tus reservas por fecha de entrada (máx. 500) |
| GET | /api/v1/reservas/{codigo}/ | Una reserva |
La API nunca permite sobrevender una reserva de la guía: un cupo o un bloqueo que la dejaría sin lugar responde 409 con las fechas. Por diseño no entrega datos de contacto del turista: la atención pasa siempre por el equipo de la guía.
Webhooks firmados
Registra una URL https:// en el panel y elige los eventos: reserva.nueva, reserva.confirmada, reserva.cancelada y reserva.completada. Cada aviso es un POST con { id, evento, creado, datos } y la cabecera X-Topocoro-Firma: t=<unix>,v1=<hex>, un HMAC-SHA256 con tu secreto sobre <t>.<cuerpo>.
const [t, v1] = firma.split(",").map((p) => p.split("=")[1]);
const esperado = createHmac("sha256", SECRETO)
.update(`${t}.${cuerpoCrudo}`).digest("hex");
// compara con timingSafeEqual y rechaza t con más de 5 minResponde 2xx en menos de 5 segundos. Si no, reintentamos durante unas 20 horas; usa id para no procesar un aviso dos veces.