Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Imjuanisss/proyecto-melika/llms.txt

Use this file to discover all available pages before exploring further.

MELIKA’s appointment system covers the full journey from initial booking through completion or cancellation. Every appointment is anchored to a time slot (franja_horaria), a specific doctor, and a specialty — ensuring consistent scheduling across both in-person and teleconsultation modalities. The platform enforces concurrency-safe booking, automatic slot liberation on cancellation, and real-time calendar rendering for patients.

Appointment Lifecycle

Each appointment moves through a set of well-defined states. The flow begins at pendiente when a patient books a slot, then resolves to one of three terminal states once the appointment date has passed or an action is taken.
StateColorHexMeaning
pendienteAmber#B45309Appointment has been booked and is awaiting the scheduled date
completadaGreen#1A7A52The appointment was attended and the doctor has filed the clinical record
no_asistioGray#6B7280The patient did not show up for the scheduled appointment
canceladaExplicitly cancelled before taking place; excluded from calendar events
pendiente, completada, and no_asistio map directly to backgroundColor/borderColor values returned by GET /citas/calendario. Cancelled appointments are excluded from the calendar response (estado != 'cancelada') and only appear in the list view.
The server-side color map for calendar events is:
StatebackgroundColorborderColor
pendiente#B45309#92400E
completada#1A7A52#145C3E
no_asistio#6B7280#4B5563

Consultation Types

When booking, patients choose between two consultation modalities via the tipo_consulta field:

Presencial

In-person visit at the clinic or doctor’s office. Selected by passing tipo_consulta: "presencial" in the booking request.

Teleconsulta

Remote video consultation. Selected by passing tipo_consulta: "teleconsulta" in the booking request. Doctor availability for this modality is exposed via acepta_teleconsulta on the specialty-doctor listing.

How Booking Works

1

Browse Available Specialties

Fetch the active specialties catalog. Only specialties with activa = TRUE are returned.
GET /especialidades
Returns an array of specialty objects including id, nombre, descripcion, precio_base, and imagen_url.
2

Pick a Doctor

List all active doctors for a chosen specialty. The response includes profile details such as foto_url, tarifa, calificacion, acepta_teleconsulta, acepta_presencial, biografia, and anos_experiencia.
GET /especialidades/:id/medicos
3

Check Slot Availability

Query available franjas_horarias for a specific doctor on a given date.
GET /especialidades/disponibilidad?medico_id=3&fecha=2025-08-15
To query across a date range and receive FullCalendar-ready event objects, use the range endpoint instead:
GET /especialidades/disponibilidad-rango?medico_id=3&inicio=2025-08-01&fin=2025-08-31
4

Book the Appointment

Submit the booking with the required fields. tipo_consulta defaults to "presencial" if omitted; motivo is fully optional.
POST /citas
Content-Type: application/json

{
  "id_medico": 3,
  "id_especialidad": 2,
  "id_franja": 14,
  "fecha": "2025-08-15",
  "hora_inicio": "09:00",
  "tipo_consulta": "presencial",
  "motivo": "Revisión anual de tensión arterial"
}
On success (201 Created), the full cita object is returned with initial state pendiente.

Booking Request Parameters

Required Fields

  • id_medico — ID of the selected doctor
  • id_especialidad — ID of the specialty
  • id_franja — ID of the time slot from franjas_horarias
  • fecha — Date of appointment (YYYY-MM-DD)
  • hora_inicio — Start time of the slot (HH:MM:SS)

Optional Fields

  • tipo_consulta"presencial" or "teleconsulta" (defaults to "presencial")
  • motivo — Free-text reason for the visit (max 300 chars in the UI)

Viewing Appointments

Returns all appointments for the authenticated patient, ordered by date descending. The response includes the doctor’s name fields separately, the specialty name, and hora_fin joined from franjas_horarias.
GET /citas/mis-citas
Example response item:
{
  "id": 42,
  "fecha": "2025-08-15",
  "hora_inicio": "09:00:00",
  "hora_fin": "09:40:00",
  "estado": "pendiente",
  "tipo_consulta": "presencial",
  "motivo": "Revisión anual de tensión arterial",
  "tarifa_cobrada": "120.00",
  "razon_cancelacion": null,
  "created_at": "2025-07-20T14:32:00.000Z",
  "medico_nombre": "Andrés",
  "medico_apellido": "Ramírez",
  "especialidad": "Cardiología"
}

Cancellation Rules

To cancel a pendiente appointment, send a PATCH request with a mandatory cancellation reason. Attempting to cancel a completada appointment or one already in cancelada state returns a 400 error.
PATCH /citas/:id
Content-Type: application/json

{
  "razon_cancelacion": "El paciente no puede asistir por motivos de viaje"
}
The razon_cancelacion field is required. An empty or missing value returns 400 BAD_REQUEST and the appointment is not cancelled.
When an appointment is successfully cancelled, the associated franja_horaria is automatically freed via a database trigger, making it immediately available for other patients to book.

Deleting an Appointment

Only appointments with estado = 'cancelada' may be permanently deleted by the owning patient. Attempting to delete an appointment in any other state returns a 400 error.
DELETE /citas/:id
Deletion is a hard delete. If you need to retain a cancellation record for auditing purposes, keep the appointment in cancelada state rather than deleting it.

Concurrency Protection

MELIKA uses database-level concurrency control to prevent double-booking. If two patients attempt to book the same slot simultaneously, only one request succeeds. The other receives a structured error response.
Error Codeerror valueDescription
45002CONCURRENCY_CONFLICTAnother user booked the same slot between your availability check and your booking request. Prompt the user to select a different slot.
45001INVALID_SLOTThe selected franja_horaria does not exist or is not available for the requested doctor and date combination.
{
  "error": "CONCURRENCY_CONFLICT",
  "mensaje": "Esta franja ya fue reservada simultáneamente. Por favor elige otro horario."
}
When a CONCURRENCY_CONFLICT error occurs, refresh the availability query (GET /especialidades/disponibilidad) to retrieve the updated list of free slots before allowing the user to rebook.

Build docs developers (and LLMs) love