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.

The Admin API is the control plane of the MELIKA platform. It exposes a unified set of endpoints that let administrators monitor live statistics, manage user accounts, oversee appointments, build doctor schedules (individually or in bulk), and maintain the specialty and medication catalogs. Every endpoint in this group is protected by JWT verification and an admin-role guard — no operation can be performed by a patient or a doctor token.
Admin tokens grant full platform access including the ability to deactivate users, cancel appointments, and modify the shared catalog. Store them in secrets managers, rotate them regularly, and never expose them in client-side code or public repositories.
All /admin routes require an Authorization: Bearer <token> header where the JWT payload contains rol = 'admin'. Requests without a valid token return 401 Unauthorized; requests with a non-admin token return 403 Forbidden.

Statistics

Get Platform Statistics

Retrieve a real-time snapshot of the entire platform: aggregate counts of active records, appointment-state breakdown, the five most recent appointments, and the five most-requested doctors. GET /admin/stats No query parameters or request body required.
curl -X GET http://localhost:3000/admin/stats \
  -H "Authorization: Bearer <admin_token>"
Response 200 OK
totales
object
Aggregate counts across the platform.
citasPorEstado
array
Appointment counts grouped by status across all appointments.
ultimasCitas
array
The five most recently created appointments across all doctors and patients.
medicosMasSolicitados
array
The five doctors with the highest number of non-cancelled appointments.

User Management

Administrators can list all users with flexible filtering and toggle any non-admin account between active and inactive states.

List Users

GET /admin/usuarios
rol
string
Filter by user role. Accepted values: paciente, medico, admin.
buscar
string
Case-insensitive substring search (ILIKE) applied to nombre, primer_apellido, and email.
activo
string
Filter by account status. Accepted values: true, false.
Results are ordered by created_at descending (newest accounts first).
curl -X GET "http://localhost:3000/admin/usuarios?rol=medico&activo=true" \
  -H "Authorization: Bearer <admin_token>"
Response 200 OK — array of user objects.
[]
array

Toggle User Status

PATCH /admin/usuarios/:id/estado Toggles the activo field of the specified user. If the user is currently active they will be deactivated, and vice versa.
id
integer
required
ID of the user to toggle.
Admin accounts cannot be deactivated through this endpoint. Attempting to do so returns 400 Bad Request.
curl -X PATCH http://localhost:3000/admin/usuarios/42/estado \
  -H "Authorization: Bearer <admin_token>"
Response 200 OK
mensaje
string
Human-readable confirmation: "Usuario activado." or "Usuario desactivado.".
Error responses
StatusCondition
400Attempted to deactivate an admin account.
404No user found with the given ID.

Appointment Management

Administrators have a global view of every appointment and can update any appointment’s status, including releasing the associated time slot when a cancellation occurs.

List Appointments

GET /admin/citas
estado
string
Filter by appointment status. Accepted values: pendiente, completada, cancelada, no_asistio.
fecha_desde
string
Lower date bound (inclusive), format YYYY-MM-DD.
fecha_hasta
string
Upper date bound (inclusive), format YYYY-MM-DD.
buscar
string
Case-insensitive substring search (ILIKE) on patient and doctor names.
Results are ordered by fecha DESC, hora_inicio DESC.
curl -X GET "http://localhost:3000/admin/citas?fecha_desde=2025-01-01&fecha_hasta=2025-01-31&estado=pendiente" \
  -H "Authorization: Bearer <admin_token>"
Response 200 OK — array of full appointment objects including patient name, doctor name, specialty, and time-slot end time (hora_fin).

Update Appointment Status

PATCH /admin/citas/:id/estado
id
integer
required
ID of the appointment to update.
estado
string
required
New status. Accepted values: pendiente, completada, cancelada, no_asistio.
razon_cancelacion
string
Optional cancellation reason. Recommended when estado is cancelada.
When estado is set to cancelada, the linked time slot (franja_horaria) is automatically released by setting disponible = TRUE, making it bookable again by other patients.
curl -X PATCH http://localhost:3000/admin/citas/88/estado \
  -H "Authorization: Bearer <admin_token>" \
  -H "Content-Type: application/json" \
  -d '{"estado": "cancelada", "razon_cancelacion": "Doctor unavailable"}'
Response 200 OK
mensaje
string
Human-readable confirmation of the status change.
Error responses
StatusCondition
400Invalid estado value supplied.
404No appointment found with the given ID.

Schedule Management

Administrators can create, update, and delete individual time slots (franjas_horarias) for any doctor, or generate an entire day’s schedule in a single bulk request. All slots are exactly 40 minutes long (DURACION_FRANJA_MIN = 40).

Get Schedules (FullCalendar format)

GET /admin/horarios Returns schedule events formatted for FullCalendar. Each event represents one franja_horaria and is color-coded by availability/appointment status.
inicio
string
Start date of the range to fetch, format YYYY-MM-DD.
fin
string
End date of the range to fetch, format YYYY-MM-DD.
id_medico
integer
Filter events to a specific doctor.
curl -X GET "http://localhost:3000/admin/horarios?inicio=2025-06-01&fin=2025-06-07&id_medico=5" \
  -H "Authorization: Bearer <admin_token>"
Response 200 OK — array of FullCalendar event objects.
[]
array

Create a Single Slot

POST /admin/horarios Creates one time slot for a doctor. The slot duration is not validated server-side on this route — use POST /admin/horarios/masivo to guarantee 40-minute alignment.
id_medico
integer
required
ID of the doctor this slot belongs to.
fecha
string
required
Date of the slot, format YYYY-MM-DD.
hora_inicio
string
required
Start time of the slot, format HH:MM.
hora_fin
string
required
End time of the slot, format HH:MM. Should be exactly 40 minutes after hora_inicio.
curl -X POST http://localhost:3000/admin/horarios \
  -H "Authorization: Bearer <admin_token>" \
  -H "Content-Type: application/json" \
  -d '{
    "id_medico": 5,
    "fecha": "2025-06-10",
    "hora_inicio": "09:00",
    "hora_fin": "09:40"
  }'
Response 201 Created
mensaje
string
"Franja creada."
franja
object
The newly created slot.
Error responses
StatusCondition
404Doctor not found or inactive.
409A slot with the same doctor, date, and time already exists (unique constraint).

Bulk Generate Slots

POST /admin/horarios/masivo Automatically generates all 40-minute slots that fit within a workday window, optionally skipping a break period. This is the recommended way to populate a full day’s schedule.
Slot duration is fixed at 40 minutes (DURACION_FRANJA_MIN = 40). The generator advances the cursor by 40 minutes at a time from hora_inicio until there is no room for another full slot before hora_fin. Any window that overlaps with inicio_descansofin_descanso is skipped entirely.
id_medico
integer
required
ID of the doctor for whom slots are generated.
fecha
string
required
Date for the generated slots, format YYYY-MM-DD.
hora_inicio
string
required
Workday start time, format HH:MM.
hora_fin
string
required
Workday end time, format HH:MM. The range must accommodate at least one 40-minute slot.
inicio_descanso
string
Break start time, format HH:MM. Optional. Must fall strictly within the workday window.
fin_descanso
string
Break end time, format HH:MM. Optional. Must fall strictly within the workday window and be after inicio_descanso.
Full workday example — 08:00 to 17:00 with a lunch break from 12:00 to 13:00 The generator produces the following slots (each 40 minutes long), automatically skipping the break window:
Morning block:   08:00–08:40 · 08:40–09:20 · 09:20–10:00
                 10:00–10:40 · 10:40–11:20 · 11:20–12:00

[break:          12:00–13:00  — skipped]

Afternoon block: 13:00–13:40 · 13:40–14:20 · 14:20–15:00
                 15:00–15:40 · 15:40–16:20 · 16:20–17:00
Total: 12 slots generated.
curl -X POST http://localhost:3000/admin/horarios/masivo \
  -H "Authorization: Bearer <admin_token>" \
  -H "Content-Type: application/json" \
  -d '{
    "id_medico": 5,
    "fecha": "2025-06-10",
    "hora_inicio": "08:00",
    "hora_fin": "17:00",
    "inicio_descanso": "12:00",
    "fin_descanso": "13:00"
  }'
Response 201 Created
mensaje
string
Human-readable summary (e.g. "Se crearon 12 franjas (0 ya existían).").
insertadas
integer
Number of new slots successfully inserted into the database.
duplicadas
integer
Number of slots skipped because they already existed (unique constraint).
total
integer
Total slots attempted (insertadas + duplicadas).
Error responses
StatusCondition
400Missing required fields (id_medico, fecha, hora_inicio, hora_fin).
400Time range is too short to fit a single 40-minute slot.
400Break window falls outside the workday boundaries or inicio_descanso >= fin_descanso.
404Doctor not found or inactive.

Update a Slot

PUT /admin/horarios/:id Updates the date and/or times of an existing free slot. The updated slot must be exactly 40 minutes long and must not overlap with any other slot for the same doctor on the same date.
id
integer
required
ID of the slot to update.
fecha
string
required
New date for the slot, format YYYY-MM-DD.
hora_inicio
string
required
New start time, format HH:MM.
hora_fin
string
required
New end time, format HH:MM. Must be exactly 40 minutes after hora_inicio.
A slot linked to an active appointment (disponible = FALSE) cannot be edited. Attempting to do so returns 400 Bad Request.
curl -X PUT http://localhost:3000/admin/horarios/101 \
  -H "Authorization: Bearer <admin_token>" \
  -H "Content-Type: application/json" \
  -d '{
    "fecha": "2025-06-10",
    "hora_inicio": "10:00",
    "hora_fin": "10:40"
  }'
Response 200 OK
mensaje
string
"Franja actualizada correctamente."
franja
object
The updated slot object with the same shape as the franja returned by POST /admin/horarios.
Error responses
StatusCondition
400Slot has an active appointment (disponible = FALSE) and cannot be modified.
400Duration is not exactly 40 minutes.
400hora_inicio >= hora_fin.
404Slot not found.
409The new time window overlaps with an existing slot for the same doctor on the same date.

Delete a Slot

DELETE /admin/horarios/:id Permanently removes a time slot from the database.
id
integer
required
ID of the slot to delete.
A slot linked to an active appointment (disponible = FALSE) cannot be deleted. Attempting to do so returns 400 Bad Request.
curl -X DELETE http://localhost:3000/admin/horarios/101 \
  -H "Authorization: Bearer <admin_token>"
Response 200 OK
mensaje
string
"Franja eliminada."
Error responses
StatusCondition
400Slot has an active appointment and cannot be deleted.
404Slot not found.

Specialty Management

Administrators control the specialty catalog that doctors are associated with and patients browse when booking appointments.

Create a Specialty

POST /admin/especialidades
nombre
string
required
Unique name of the specialty (e.g. "Cardiología"). Duplicate names return 409.
descripcion
string
Short description shown to patients.
precio_base
number
required
Base consultation price for this specialty.
imagen_url
string
URL or path of the specialty’s image. Stored as imagen_url in the database.
curl -X POST http://localhost:3000/admin/especialidades \
  -H "Authorization: Bearer <admin_token>" \
  -H "Content-Type: application/json" \
  -d '{
    "nombre": "Cardiología",
    "descripcion": "Diagnóstico y tratamiento de enfermedades del corazón.",
    "precio_base": 120.00,
    "imagen_url": "https://cdn.example.com/icons/cardiology.svg"
  }'
Response 201 Created
mensaje
string
Confirmation message.
especialidad
object
The newly created specialty record.
Error responses
StatusCondition
409A specialty with the same nombre already exists.

Update a Specialty

PUT /admin/especialidades/:id
id
integer
required
ID of the specialty to update.
nombre
string
New name for the specialty.
descripcion
string
Updated description.
precio_base
number
Updated base price.
imagen_url
string
Updated image URL. Stored as imagen_url in the database.
activa
boolean
Active status of the specialty. Defaults to true if omitted.
curl -X PUT http://localhost:3000/admin/especialidades/3 \
  -H "Authorization: Bearer <admin_token>" \
  -H "Content-Type: application/json" \
  -d '{
    "nombre": "Cardiología Intervencionista",
    "precio_base": 150.00
  }'
Response 200 OK
mensaje
string
Confirmation message.
especialidad
object
The updated specialty record.

Toggle Specialty Status

PATCH /admin/especialidades/:id/estado Toggles the activa boolean of the specialty. Deactivating a specialty hides it from patient-facing catalog views without deleting it.
id
integer
required
ID of the specialty to toggle.
curl -X PATCH http://localhost:3000/admin/especialidades/3/estado \
  -H "Authorization: Bearer <admin_token>"
Response 200 OK
mensaje
string
"Especialidad activada." or "Especialidad desactivada.".

Medication Management

Administrators maintain the medication catalog used by doctors when creating prescriptions and clinical records. The admin medication routes use nombre_comercial, principio_activo, and presentaciones field names directly (unlike the public POST /medicamentos route which uses short aliases).

Create a Medication

POST /admin/medicamentos
nombre_comercial
string
required
Commercial name of the medication. Stored directly as nombre_comercial.
principio_activo
string
required
Active ingredient(s). Stored directly as principio_activo.
tipo
string
Medication class. Accepted values: OTC (over-the-counter), Rx (prescription-only). Defaults to OTC.
laboratorio
string
Name of the pharmaceutical laboratory.
categoria
string
Legacy text category label (optional).
descripcion
string
Free-text description of the medication.
indicaciones
string
Clinical indications.
contraindicaciones
string
Contraindications.
presentaciones
string
Physical form / presentations (e.g. "Tabletas 500 mg"). Stored directly as presentaciones.
registro_invima
string
INVIMA registration number. Must be unique when provided.
imagen_url
string
URL of the medication’s product image.
curl -X POST http://localhost:3000/admin/medicamentos \
  -H "Authorization: Bearer <admin_token>" \
  -H "Content-Type: application/json" \
  -d '{
    "nombre_comercial": "Ibuprofeno 400",
    "principio_activo": "Ibuprofeno",
    "tipo": "OTC",
    "descripcion": "Antiinflamatorio no esteroideo de uso general.",
    "presentaciones": "Tabletas 400 mg",
    "laboratorio": "Genfar"
  }'
Response 201 Created
mensaje
string
"Medicamento creado."
medicamento
object
The newly created medication record as stored in the database.
Error responses
StatusCondition
400nombre_comercial or principio_activo missing.
409The registro_invima value already exists in the database.

Update a Medication

PUT /admin/medicamentos/:id Accepts the same body fields as POST /admin/medicamentos and replaces the existing record.
id
integer
required
ID of the medication to update.
nombre_comercial
string
Updated commercial name.
principio_activo
string
Updated active ingredient.
tipo
string
Updated medication class: OTC or Rx.
laboratorio
string
Updated laboratory name.
descripcion
string
Updated description.
indicaciones
string
Updated clinical indications.
contraindicaciones
string
Updated contraindications.
presentaciones
string
Updated presentations.
registro_invima
string
Updated INVIMA number.
imagen_url
string
Updated product image URL.
activo
boolean
Active status of the medication. Defaults to true if omitted.
curl -X PUT http://localhost:3000/admin/medicamentos/12 \
  -H "Authorization: Bearer <admin_token>" \
  -H "Content-Type: application/json" \
  -d '{
    "nombre_comercial": "Ibuprofeno 600",
    "principio_activo": "Ibuprofeno",
    "presentaciones": "Tabletas 600 mg",
    "tipo": "Rx"
  }'
Response 200 OK
mensaje
string
Confirmation message.
medicamento
object
The updated medication record.
Error responses
StatusCondition
404No medication found with the given ID.

Toggle Medication Status

PATCH /admin/medicamentos/:id/estado Toggles the activo boolean of a medication. Deactivated medications remain in the database for historical prescription records but are hidden from active catalog views.
id
integer
required
ID of the medication to toggle.
curl -X PATCH http://localhost:3000/admin/medicamentos/12/estado \
  -H "Authorization: Bearer <admin_token>"
Response 200 OK
mensaje
string
"Medicamento activado." or "Medicamento desactivado.".
Error responses
StatusCondition
404No medication found with the given ID.

Build docs developers (and LLMs) love