Skip to main content
POST
/
appointments
Create Appointment
curl --request POST \
  --url https://api.example.com/appointments \
  --header 'Content-Type: application/json' \
  --data '
{
  "patientID": 123,
  "professionalID": 123,
  "date": "<string>",
  "time": "<string>",
  "description": "<string>"
}
'
{
  "appointment": {
    "id": 123,
    "patientID": 123,
    "professionalID": 123,
    "date": "<string>",
    "time": "<string>",
    "description": "<string>",
    "state": "<string>",
    "createdAt": "<string>",
    "updatedAt": "<string>"
  }
}

Overview

This endpoint creates a new appointment in the system. It performs extensive validation to ensure:
  • Patient and professional exist in the system
  • The selected time slot is available for both patient and professional
  • The professional works during the requested date/time
  • The appointment time is within the professional’s work schedule
This endpoint requires admin role. Regular users cannot create appointments.

Authentication

Requires a valid JWT token with admin privileges.
Authorization: Bearer <jwt_token>

Request Body

patientID
number
required
The ID of the patient for this appointment. Must correspond to an existing patient’s DNI in the system.Validation:
  • Patient with this DNI must exist
  • Patient must not have another appointment at the same date/time
Example: 45
professionalID
number
required
The ID of the professional who will conduct the appointment. Must correspond to an existing professional’s DNI.Validation:
  • Professional with this DNI must exist
  • Professional must not have another appointment at the same date/time
  • Professional must work on the selected day of the week
  • Time must be within professional’s work schedule
Example: 12
date
string
required
The date for the appointment in ISO 8601 format (YYYY-MM-DD).Validation:
  • Must be a valid date format
  • Patient must be available at this date/time
  • Professional must work on this day of the week
Example: "2026-03-15"
time
string
required
The time for the appointment in 24-hour format (HH:mm).Validation:
  • Must be within professional’s work schedule for that day
  • Must not conflict with existing appointments for patient or professional
  • Format: HH:mm (e.g., “09:30”, “14:00”)
Example: "10:30"
description
string
required
The reason for the appointment or notes about what will be addressed.Example: "Control mensual de diabetes"

Complex Validations

This endpoint runs several complex validation checks:

1. Patient Availability (checkPatientAvailability)

Verifies the patient doesn’t have another appointment at the same date/time. Error message: "El paciente ya tiene un turno el {date} a las {time}"

2. Appointment Availability (checkAppointmentAvailability)

Ensures the professional doesn’t have another appointment at the same date/time. Error message: "El profesional ya tiene un turno ocupado el {date} a las {time}"

3. Professional Schedule (checkProfessionalSchedule)

Validates the appointment time against the professional’s work schedule:
  • Checks if professional works on the selected day of the week
  • Verifies time falls within professional’s start/end time for that day
Error messages:
  • "El profesional no trabaja en la fecha seleccionada."
  • "El horario {time} está fuera de la jornada laboral ({startTime} a {endTime})"
  • "Formato de fecha u hora inválido"

Response

Returns the newly created appointment object:
appointment
object

Examples

Create a New Appointment

curl -X POST "https://api.clinicavitalis.com/appointments" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
  -H "Content-Type: application/json" \
  -d '{
    "patientID": 45,
    "professionalID": 12,
    "date": "2026-03-15",
    "time": "10:30",
    "description": "Control mensual de diabetes"
  }'

Success Response

Status Code: 201 Created
{
  "appointment": {
    "id": 123,
    "patientID": 45,
    "professionalID": 12,
    "date": "2026-03-15",
    "time": "10:30:00",
    "description": "Control mensual de diabetes",
    "state": "Pendiente",
    "createdAt": "2026-03-11T15:30:00.000Z",
    "updatedAt": "2026-03-11T15:30:00.000Z"
  }
}

Error Responses

400 Bad Request - Validation Errors

Returned when validation fails. The response includes an array of all validation errors:
{
  "errors": [
    {
      "msg": "El paciente es obligatorio",
      "param": "patientID",
      "location": "body"
    }
  ]
}

Common Validation Errors

Missing required fields:
{
  "errors": [
    { "msg": "El paciente es obligatorio", "param": "patientID" },
    { "msg": "El profesional es obligatorio", "param": "professionalID" },
    { "msg": "La fecha es obligatoria", "param": "date" },
    { "msg": "El horario es obligatorio", "param": "time" },
    { "msg": "La descripción es obligatoria", "param": "description" }
  ]
}
Patient doesn’t exist:
{
  "errors": [
    {
      "msg": "El DNI 12345678 ya está en uso por otro paciente",
      "param": "patientID"
    }
  ]
}
Professional doesn’t exist:
{
  "errors": [
    {
      "msg": "El DNI 98765432 ya está en uso por otro profesional",
      "param": "professionalID"
    }
  ]
}
Patient already has appointment at that time:
{
  "errors": [
    {
      "msg": "El paciente ya tiene un turno el 2026-03-15 a las 10:30",
      "param": "date"
    }
  ]
}
Professional already has appointment at that time:
{
  "errors": [
    {
      "msg": "El profesional ya tiene un turno ocupado el 2026-03-15 a las 10:30",
      "param": "_"
    }
  ]
}
Professional doesn’t work on that day:
{
  "errors": [
    {
      "msg": "El profesional no trabaja en la fecha seleccionada.",
      "param": "_"
    }
  ]
}
Time outside professional’s work schedule:
{
  "errors": [
    {
      "msg": "El horario 18:00 está fuera de la jornada laboral (08:00 a 16:00)",
      "param": "_"
    }
  ]
}

401 Unauthorized

Returned when the JWT token is missing or invalid:
{
  "msg": "Token inválido o no proporcionado"
}

403 Forbidden

Returned when the user doesn’t have admin privileges:
{
  "msg": "No tiene permisos de administrador"
}

500 Server Error

Returned when a server error occurs:
{
  "msg": "Error del servidor"
}

Appointment States

New appointments are created with state: "Pendiente". The appointment can transition through these states:

Pendiente (Pending)

Initial state when appointment is created. Indicates the appointment is scheduled and waiting.
The patient was seen and the appointment was completed successfully.
The appointment was cancelled by the patient or clinic.
The patient did not show up for the appointment. Automatically set by the system when a pending appointment’s date/time passes.

Date and Time Format Guidelines

Date Format

  • Required format: ISO 8601 date (YYYY-MM-DD)
  • Examples:
    • "2026-03-15"
    • "2026-3-5" ✗ (must be zero-padded)
    • "15/03/2026" ✗ (wrong format)

Time Format

  • Required format: 24-hour time (HH:mm)
  • Examples:
    • "09:30"
    • "14:00"
    • "9:30" ✗ (must be zero-padded)
    • "02:30 PM" ✗ (no AM/PM)

Workflow Example

  1. Patient requests appointment for March 15, 2026 at 10:30 AM
  2. Admin selects patient (ID: 45) and professional (ID: 12)
  3. System validates:
    • Patient 45 exists ✓
    • Professional 12 exists ✓
    • Patient 45 has no appointment on 2026-03-15 at 10:30 ✓
    • Professional 12 has no appointment on 2026-03-15 at 10:30 ✓
    • Professional 12 works on Saturdays ✓
    • 10:30 is within professional’s schedule (08:00-16:00) ✓
  4. Appointment created with state “Pendiente”
  5. ID assigned (e.g., 123) and returned in response

Best Practices

  • Always validate patient and professional IDs on the client side before submission
  • Check professional work schedules before offering time slots to users
  • Handle validation errors gracefully and display them to users
  • Store the returned appointment ID for future updates or cancellations
  • Consider timezone implications when working with date/time values

Build docs developers (and LLMs) love