Citas y reservas
Citas es el producto de reservas de Recurrente: citas con tu equipo, clases con cupo, estadías por noche, tarjetas de regalo y contratos. Todo lo que un negocio hace con Citas en el panel también se puede hacer con la API, el CLI recurrente y el servidor MCP.
A diferencia de la mayoría de APIs de reservas, el dinero está en la cita: cuánto cuesta, cuánto pagó el cliente, cuánto falta y el checkout donde paga. No tienes que conciliar una cita con un pago por tu cuenta.
Citas está en toda cuenta de negocio. Una cuenta personal no lo tiene: todos sus endpoints le responden 403 con code: bookings_not_enabled.
Conceptos
Un servicio tiene un kind: appointment (un cliente, un profesional), class (varios clientes en una sesión) o lodging (noches en vez de minutos).
Reservar en tres llamadas
1. Consulta los horarios libres. GET /availability responde los mismos horarios que muestra la página pública de citas: resta lo ya reservado, el tiempo extra después de cada cita, la anticipación mínima y el límite diario de la cuenta.
Una fecha sin hora (2026-10-07) es la medianoche en la zona horaria del negocio. Hasta 31 días por consulta.
2. Reserva uno. Envía el starts_at que te ofrecieron e identifica al cliente con customer_id, o con customer[phone] y customer[name] para crearlo. Usa un Idempotency-Key distinto por cita.
3. Escucha el resultado. La política de pago del servicio decide qué pasa:
Una cita pending aparta la hora hasta hold_expires_at. Si nadie paga, la cancela system. Suscríbete a booking.confirm en vez de consultar una y otra vez.
Si alguien tomó la hora antes, la respuesta es 422 con code: slot_taken; vuelve a consultar los horarios.
El dinero de una cita
Cambiar una cita
Cada cambio responde la cita como queda, y todos son idempotentes con un Idempotency-Key.
Las operaciones que mueven dinero necesitan una llave con movimiento de dinero habilitado; si no, responden 403 con code: money_movement_not_enabled.
Encontrar una cita por el cliente
GET /bookings filtra por status, un rango from/to sobre la hora de inicio, staff_member_id, customer_id, class_session_id y q, palabras del nombre, correo o teléfono del cliente:
Citas que se repiten
POST /booking_series reserva al mismo cliente, servicio y profesional cada interval frequency (day, week, month, year, o back_to_back el mismo día), occurrences veces o hasta ends_on. Una hora ocupada o cerrada se salta y aparece en skipped_starts_at en vez de detener la serie. Cada visita se cobra el día de la cita.
Configura tus servicios y tu equipo
Un servicio es un producto con un objeto booking. Envíalo al crear o actualizar el producto (POST /products, PATCH /products/{id}) con los mismos ajustes del formulario del panel: kind, duration_minutes, buffer_after_minutes, payment_policy (y el anticipo o el cargo por inasistencia en centavos), staff_member_ids, resource_ids, extras y, para habitaciones, tarifas por noche. GET /services lista todos los productos que se reservan con el service_id que piden los demás endpoints.
Todo lo que cambias aquí lo lee GET /availability de inmediato. Conectar el Google Calendar de un profesional es un permiso de OAuth y se queda en el panel.
Clases
Una clase es un servicio con kind: class y un capacity. POST /class_sessions escribe sus sesiones con una regla semanal (“martes y jueves a las 5:45 pm, del 6 de octubre al 15 de diciembre”): service_id, staff_member_id, weekdays (0 es domingo), time y el rango de fechas. Es todo o nada: si el instructor o el salón ya están ocupados en alguna de esas horas, no escribe ninguna (busy).
Un lugar es una cita: POST /bookings con class_session_id. Si la clase está llena, la respuesta es 422 con code: full. GET /class_sessions y GET /class_sessions/{id} muestran los lugares tomados y libres.
POST /class_sessions/{class_session_id}/cancellation cancela una sesión: cada lugar se cancela como el negocio y se devuelve (una sesión de paquete vuelve a su paquete), y cada cliente recibe el aviso. Mueve dinero.
Lista de espera
POST /waitlist_entries pone a un cliente en la lista de espera de un servicio para hasta cinco días, cada uno entero o una parte (morning, afternoon, evening), como el “Avísame” de la página pública. Cuando se cancela o se mueve una cita que le sirve, recibe un WhatsApp con el link para reservarla. GET /waitlist_entries lista quién espera; DELETE /waitlist_entries/{id} quita a alguien.
Alojamiento
Un tipo de habitación es un servicio con kind: lodging; cada habitación física es un recurso. Las estadías también son citas, con un objeto stay (tipo, habitación, fechas de llegada y salida, noches, huéspedes, la cuenta abierta y el registro de huéspedes).
GET /lodging/availability?check_in_on=…&check_out_on=…&guests=2responde cada tipo de habitación con sus habitaciones libres y el precio de la estadía noche por noche, como lo calcula la página pública (temporadas, descuento por estadía larga, huéspedes extra, impuesto de hospedaje).POST /staysla reserva conroom_type_id, las fechas y el huésped. La política de pago funciona igual que en las citas.- El día de la llegada:
POST /stays/{stay_id}/check_in(abre una cuenta para los extras),…/guest_registration(el registro de huéspedes),…/date_change,…/unit_assignment, yPOST /stays/{stay_id}/check_out. El check-out cierra la cuenta segúnchannel:payment_link(por defecto),pos, osaved_card, que cobra la tarjeta y mueve dinero.
Las operaciones de citas de arriba (link del saldo, pagado afuera, inasistencia, cargo por inasistencia, cancelar, devolver) también funcionan con estadías. GET /bookings?kind=stay las lista, POST/DELETE /maintenance_blocks saca una habitación de venta unas noches y GET /lodging/occupancy da la ocupación y los ingresos del mes.
Tarjetas de regalo
El código funciona como efectivo: quien lo tiene lo gasta. Mantenlo fuera de tus logs. Los clientes canjean códigos en su propio checkout; eso se queda en el checkout.
Contratos
La firma siempre ocurre en la página del cliente.
Configuración, paquetes y notas
Una forma de vender desactivada no recibe nada nuevo, tampoco por la API: con Citas desactivado, los horarios por servicio y toda cita, serie o lugar en la lista de espera nuevos responden 403 con code: bookings_off; con Alojamiento desactivado, una estadía nueva responde code: lodging_off. Lo ya reservado sigue funcionando: moverlo, cancelarlo, cobrarlo y la recepción.
Un PATCH cambia solo los campos que envías, con las validaciones del panel; si no se puede, responde 422 con code: invalid_booking_settings y los mismos mensajes del panel.
Webhooks
Cada evento lleva el objeto como estaba en el momento del evento.
Sandbox
Las citas son nativas en un Sandbox: la misma agenda, links de pago que se pagan con la tarjeta de prueba y eventos que salen solo a los webhooks del Sandbox. El cargo por inasistencia, las devoluciones, cancelar una clase y el check-out corren sobre los pagos de prueba del Sandbox y nunca llegan a un procesador real. Ningún WhatsApp ni correo le llega a una persona real desde un Sandbox: un contrato enviado desde uno se comparte con su signing_url. El calendario externo de una habitación se guarda, pero nunca se descarga.
Agentes: CLI y MCP
Todas las operaciones de esta guía están en el catálogo de agentes, así que el CLI recurrente y el servidor MCP las corren sin código adicional. “Mueve la cita de Ana de las 3 al jueves” son tres llamadas:
Las operaciones que mueven dinero necesitan que una persona confirme: --yes en el CLI, el permiso money en una conexión MCP.

