{"openapi":"3.1.0","info":{"title":"Citeri API","description":"API para gestionar citas, clientes y servicios de tu negocio con Citeri","version":"1.0.0"},"servers":[{"url":"https://citeri.es"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"API key generada en Citeri › Developer › Claves de API (formato ctk_...)"}},"schemas":{"Appointment":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"org_id":{"type":"string","format":"uuid"},"client_id":{"type":"string","format":"uuid"},"service_id":{"type":"string","format":"uuid"},"employee_id":{"type":"string","format":"uuid"},"start_at":{"type":"string","format":"date-time"},"end_at":{"type":"string","format":"date-time"},"status":{"type":"string","enum":["booked","confirmed","done","cancelled","no_show","rescheduled"]},"notes":{"type":"string"}}},"Client":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"email":{"type":"string","format":"email"},"phone":{"type":"string"},"notes":{"type":"string"}}},"Service":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"price_cents":{"type":"integer","description":"Precio en céntimos (ej: 2500 = 25,00 €)"},"duration_min":{"type":"integer","description":"Duración en minutos"},"active":{"type":"boolean"}}},"Reservation":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["booked","pending","confirmed","done","cancelled","no_show"]},"start_at":{"type":"string","format":"date-time"},"end_at":{"type":"string","format":"date-time"},"actions":{"type":"object","properties":{"can_confirm":{"type":"boolean"},"can_cancel":{"type":"boolean"},"can_reschedule":{"type":"boolean"}}}}}}},"paths":{"/api/appointments":{"get":{"operationId":"listAppointments","summary":"Lista citas del negocio","description":"Devuelve las citas de la organización. Filtra por fecha o estado.","parameters":[{"name":"org_id","in":"query","required":true,"schema":{"type":"string"},"description":"ID de la organización"},{"name":"date","in":"query","schema":{"type":"string","format":"date"},"description":"Filtrar por fecha exacta (YYYY-MM-DD)"},{"name":"from","in":"query","schema":{"type":"string","format":"date"},"description":"Fecha de inicio del rango (YYYY-MM-DD)"},{"name":"to","in":"query","schema":{"type":"string","format":"date"},"description":"Fecha de fin del rango (YYYY-MM-DD)"},{"name":"status","in":"query","schema":{"type":"string","enum":["booked","confirmed","done","cancelled","no_show"]},"description":"Filtrar por estado"},{"name":"employee_id","in":"query","schema":{"type":"string"},"description":"Filtrar por empleado"}],"responses":{"200":{"description":"Lista de citas","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Appointment"}}}}},"401":{"description":"No autenticado — falta o es inválida la API key"}}},"post":{"operationId":"createAppointment","summary":"Crear una nueva cita","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["org_id","client_id","service_id","employee_id","start_at"],"properties":{"org_id":{"type":"string","description":"ID de la organización"},"client_id":{"type":"string","description":"ID del cliente"},"service_id":{"type":"string","description":"ID del servicio"},"employee_id":{"type":"string","description":"ID del empleado/profesional"},"start_at":{"type":"string","format":"date-time","description":"Inicio de la cita (ISO 8601)"},"notes":{"type":"string","description":"Notas internas"}}}}}},"responses":{"201":{"description":"Cita creada correctamente"},"401":{"description":"No autenticado"}}}},"/api/appointments/{id}/status":{"patch":{"operationId":"updateAppointmentStatus","summary":"Actualizar estado de una cita","description":"Cambia el estado de una cita existente. Si el cliente tiene email, puede enviarse notificación automática.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"ID de la cita"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["status"],"properties":{"status":{"type":"string","enum":["confirmed","done","cancelled","no_show"],"description":"Nuevo estado"},"notify":{"type":"boolean","description":"Enviar email al cliente (por defecto true)"}}}}}},"responses":{"200":{"description":"Estado actualizado"},"403":{"description":"No tienes acceso a esta cita"},"404":{"description":"Cita no encontrada"}}}},"/api/appointments/{id}/reschedule":{"patch":{"operationId":"rescheduleAppointment","summary":"Reprogramar una cita a otro horario","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"ID de la cita"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["start_at","end_at"],"properties":{"start_at":{"type":"string","format":"date-time","description":"Nueva fecha/hora de inicio"},"end_at":{"type":"string","format":"date-time","description":"Nueva fecha/hora de fin"},"notify":{"type":"boolean","description":"Enviar email al cliente (por defecto true)"}}}}}},"responses":{"200":{"description":"Cita reprogramada"},"409":{"description":"El hueco ya está ocupado"}}}},"/api/clients":{"get":{"operationId":"listClients","summary":"Lista clientes del negocio","parameters":[{"name":"org_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"q","in":"query","schema":{"type":"string"},"description":"Buscar por nombre, email o teléfono"}],"responses":{"200":{"description":"Lista de clientes","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Client"}}}}}}},"post":{"operationId":"createClient","summary":"Crear un nuevo cliente","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["org_id","name"],"properties":{"org_id":{"type":"string"},"name":{"type":"string"},"email":{"type":"string","format":"email"},"phone":{"type":"string"},"notes":{"type":"string"}}}}}},"responses":{"201":{"description":"Cliente creado"}}}},"/api/services":{"get":{"operationId":"listServices","summary":"Lista los servicios disponibles del negocio","parameters":[{"name":"org_id","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Lista de servicios","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Service"}}}}}}}},"/api/stats/{org_id}":{"get":{"operationId":"getStats","summary":"Estadísticas del negocio","description":"Devuelve un resumen con citas de hoy, esta semana, ingresos del mes y estado de la agenda.","parameters":[{"name":"org_id","in":"path","required":true,"schema":{"type":"string"},"description":"ID de la organización"},{"name":"from","in":"query","schema":{"type":"string","format":"date"},"description":"Inicio del rango de fechas"},{"name":"to","in":"query","schema":{"type":"string","format":"date"},"description":"Fin del rango de fechas"}],"responses":{"200":{"description":"Estadísticas del negocio"},"403":{"description":"Acceso denegado"}}}},"/api/reservations/{id}":{"get":{"operationId":"getPublicReservation","summary":"Consultar una cita con su enlace firmado","security":[],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"token","in":"query","required":false,"schema":{"type":"string"},"description":"Token incluido en el enlace enviado al cliente"}],"responses":{"200":{"description":"Reserva y acciones disponibles"},"404":{"description":"Reserva no encontrada"}}}},"/api/reservations/{id}/confirm":{"post":{"operationId":"confirmPublicReservation","summary":"Confirmar una cita desde el enlace del cliente","security":[],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["token"],"properties":{"token":{"type":"string"}}}}}},"responses":{"200":{"description":"Cita confirmada"},"403":{"description":"Token inválido"},"409":{"description":"La cita no admite confirmación"}}}},"/api/reservations/{id}/cancel":{"post":{"operationId":"cancelPublicReservation","summary":"Cancelar una cita desde el enlace del cliente","security":[],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["token"],"properties":{"token":{"type":"string"}}}}}},"responses":{"200":{"description":"Cita cancelada"},"403":{"description":"Token inválido"},"409":{"description":"La cita no admite cancelación"}}}},"/api/reservations/{id}/reschedule":{"post":{"operationId":"reschedulePublicReservation","summary":"Reprogramar una cita desde el enlace del cliente","security":[],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["token","date","time"],"properties":{"token":{"type":"string"},"date":{"type":"string","format":"date"},"time":{"type":"string","example":"10:30"}}}}}},"responses":{"200":{"description":"Cita reprogramada"},"403":{"description":"Token inválido"},"409":{"description":"Horario no disponible"}}}}}}