Citas
Las citas representan las consultas medicas programadas entre pacientes y doctores del club. Esta API permite gestionar el ciclo de vida completo de una cita, desde la solicitud hasta su finalizacion.
El sistema incluye deteccion automatica de conflictos de horario. Al crear o actualizar una cita, se valida que no existan solapamientos con citas confirmadas del mismo doctor o paciente.
El modelo de Cita
- Name
id- Type
- string
- Description
Identificador unico de la cita.
- Name
patientId- Type
- string
- Description
ID del paciente asociado.
- Name
patientName- Type
- string
- Description
Nombre completo del paciente.
- Name
doctorId- Type
- string
- Description
ID del doctor asignado.
- Name
date- Type
- string
- Description
Fecha de la cita (formato ISO 8601).
- Name
time- Type
- string
- Description
Hora de la cita (formato HH:mm).
- Name
duration- Type
- number
- Description
Duracion en minutos (default: 30).
- Name
type- Type
- AppointmentType
- Description
Tipo de cita.
- Name
status- Type
- AppointmentStatus
- Description
Estado actual de la cita.
- Name
notes- Type
- string
- Description
Notas adicionales sobre la cita.
- Name
createdAt- Type
- timestamp
- Description
Fecha de creacion.
- Name
updatedAt- Type
- timestamp
- Description
Fecha de ultima actualizacion.
Ejemplo de cita
{
"id": "apt_01HQ8XYZ123",
"patientId": "usr_01HQ8ABC456",
"patientName": "Maria Gonzalez",
"doctorId": "doc_01HQ8DEF789",
"date": "2026-05-15",
"time": "10:30",
"duration": 30,
"type": "consultation",
"status": "confirmed",
"notes": "Primera consulta. Paciente refiere ansiedad cronica.",
"createdAt": "2026-05-09T14:00:00Z",
"updatedAt": "2026-05-09T15:30:00Z"
}
Tipos de Cita (AppointmentType)
| Tipo | Descripcion |
|---|---|
consultation | Consulta medica general |
follow_up | Seguimiento de tratamiento |
prescription_renewal | Renovacion de receta o prescripcion |
emergency | Consulta de emergencia |
Estados de Cita (AppointmentStatus)
| Estado | Descripcion |
|---|---|
pending | Cita solicitada, pendiente de confirmacion |
confirmed | Confirmada por el doctor o administrador |
rejected | Rechazada |
cancelled | Cancelada por el paciente o administrador |
completed | Consulta finalizada |
Listar citas
Retorna una lista de citas con filtros opcionales. Los miembros con rol member solo pueden ver sus propias citas (auto-scoped por patientId).
Parametros de Consulta
- Name
patientId- Type
- string
- Description
Filtrar por paciente.
- Name
doctorId- Type
- string
- Description
Filtrar por doctor.
- Name
status- Type
- AppointmentStatus
- Description
Filtrar por estado.
- Name
date- Type
- string
- Description
Filtrar por fecha exacta (YYYY-MM-DD).
- Name
fromDate- Type
- string
- Description
Fecha de inicio del rango (ISO 8601).
- Name
toDate- Type
- string
- Description
Fecha de fin del rango (ISO 8601).
El endpoint incluye deteccion de conflictos: si una cita se solapa con otra confirmada del mismo doctor o paciente, se marca con un flag hasConflict en la respuesta.
Request
curl -G https://api.cannahub.tech/api/appointments \
-H "Authorization: Bearer {token}" \
-d status=pending \
-d fromDate=2026-05-01 \
-d toDate=2026-05-31
Response
{
"appointments": [
{
"id": "apt_01HQ8XYZ123",
"patientId": "usr_01HQ8ABC456",
"patientName": "Maria Gonzalez",
"doctorId": "doc_01HQ8DEF789",
"date": "2026-05-15",
"time": "10:30",
"duration": 30,
"type": "consultation",
"status": "pending",
"createdAt": "2026-05-09T14:00:00Z"
}
],
"count": 1
}
Crear cita
Crea una nueva cita medica. El sistema valida automaticamente que no existan conflictos de horario con citas confirmadas del mismo doctor o paciente.
Los miembros con rol member solo pueden crear citas asociadas a su propio registro de paciente.
Campos Requeridos
- Name
patientId- Type
- string
- Description
ID del paciente.
Campos Opcionales
- Name
doctorId- Type
- string
- Description
ID del doctor a asignar.
- Name
date- Type
- string
- Description
Fecha de la cita (YYYY-MM-DD).
- Name
time- Type
- string
- Description
Hora de la cita (HH:mm).
- Name
duration- Type
- number
- Description
Duracion en minutos (default: 30).
- Name
type- Type
- AppointmentType
- Description
Tipo de cita (default:
consultation).
- Name
notes- Type
- string
- Description
Notas adicionales.
Request
curl -X POST https://api.cannahub.tech/api/appointments \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"patientId": "usr_01HQ8ABC456",
"doctorId": "doc_01HQ8DEF789",
"date": "2026-05-20",
"time": "14:00",
"duration": 45,
"type": "follow_up",
"notes": "Seguimiento de tratamiento con CBD"
}'
Response (201)
{
"appointment": {
"id": "apt_01HQ8XYZ456",
"patientId": "usr_01HQ8ABC456",
"patientName": "Maria Gonzalez",
"doctorId": "doc_01HQ8DEF789",
"date": "2026-05-20",
"time": "14:00",
"duration": 45,
"type": "follow_up",
"status": "pending",
"notes": "Seguimiento de tratamiento con CBD",
"createdAt": "2026-05-09T16:00:00Z",
"updatedAt": "2026-05-09T16:00:00Z"
}
}
Error: conflicto de horario (409)
{
"error": "APPOINTMENT_CONFLICT",
"message": "El doctor ya tiene una cita confirmada en ese horario.",
"conflictWith": {
"id": "apt_01HQ8XYZ999",
"date": "2026-05-20",
"time": "13:45",
"duration": 30
}
}
Obtener cita
Retorna los detalles completos de una cita especifica.
Request
curl https://api.cannahub.tech/api/appointments/apt_01HQ8XYZ123 \
-H "Authorization: Bearer {token}"
Response
{
"appointment": {
"id": "apt_01HQ8XYZ123",
"patientId": "usr_01HQ8ABC456",
"patientName": "Maria Gonzalez",
"doctorId": "doc_01HQ8DEF789",
"date": "2026-05-15",
"time": "10:30",
"duration": 30,
"type": "consultation",
"status": "confirmed",
"notes": "Primera consulta. Paciente refiere ansiedad cronica.",
"createdAt": "2026-05-09T14:00:00Z",
"updatedAt": "2026-05-09T15:30:00Z"
}
}
Actualizar cita
Actualiza las propiedades de una cita existente. Solo se actualizan los campos enviados en el body.
Si se cambia date, time o duration, el sistema vuelve a validar conflictos de horario.
Campos Actualizables
- Name
date- Type
- string
- Description
Nueva fecha (YYYY-MM-DD).
- Name
time- Type
- string
- Description
Nueva hora (HH:mm).
- Name
duration- Type
- number
- Description
Nueva duracion en minutos.
- Name
type- Type
- AppointmentType
- Description
Nuevo tipo de cita.
- Name
status- Type
- AppointmentStatus
- Description
Nuevo estado.
- Name
notes- Type
- string
- Description
Notas actualizadas.
Request
curl -X PATCH https://api.cannahub.tech/api/appointments/apt_01HQ8XYZ123 \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"status": "confirmed",
"notes": "Confirmada por el Dr. Lopez"
}'
Response
{
"appointment": {
"id": "apt_01HQ8XYZ123",
"patientId": "usr_01HQ8ABC456",
"patientName": "Maria Gonzalez",
"doctorId": "doc_01HQ8DEF789",
"date": "2026-05-15",
"time": "10:30",
"duration": 30,
"type": "consultation",
"status": "confirmed",
"notes": "Confirmada por el Dr. Lopez",
"createdAt": "2026-05-09T14:00:00Z",
"updatedAt": "2026-05-09T18:00:00Z"
}
}
Eliminar cita
Elimina una cita del sistema.
Solo se pueden eliminar citas en estado pending, rejected o cancelled. Las citas confirmed deben cancelarse primero.
Request
curl -X DELETE https://api.cannahub.tech/api/appointments/apt_01HQ8XYZ123 \
-H "Authorization: Bearer {token}"
Response
{
"success": true
}
React Query Hooks
Uso de hooks
import {
useAppointmentsQuery,
useAppointmentQuery,
useCreateAppointmentMutation,
useUpdateAppointmentMutation,
useDeleteAppointmentMutation
} from '@/features/Club/Appointments/hooks'
// Listar citas con filtros
const { data: appointments, isLoading } = useAppointmentsQuery({
status: 'pending',
fromDate: '2026-05-01',
toDate: '2026-05-31'
})
// Obtener una cita
const { data: appointment } = useAppointmentQuery('apt_01HQ8XYZ123')
// Crear cita
const createMutation = useCreateAppointmentMutation()
await createMutation.mutateAsync({
patientId: 'usr_01HQ8ABC456',
doctorId: 'doc_01HQ8DEF789',
date: '2026-05-20',
time: '14:00',
duration: 45,
type: 'follow_up'
})
// Actualizar cita
const updateMutation = useUpdateAppointmentMutation()
await updateMutation.mutateAsync({
id: 'apt_01HQ8XYZ123',
data: { status: 'confirmed' }
})
// Eliminar cita
const deleteMutation = useDeleteAppointmentMutation()
await deleteMutation.mutateAsync('apt_01HQ8XYZ123')
Query Keys
appointmentKeys = {
all: ['appointments'],
lists: () => ['appointments', 'list'],
list: (filters) => ['appointments', 'list', filters],
details: () => ['appointments', 'detail'],
detail: (id) => ['appointments', 'detail', id]
}