Saltar a contenido

API Contract: Bookings


Proposito

Contrato de la API de reservas de turnos: busqueda de disponibilidad, reserva, cancelacion, y consulta de turnos.


Metadata

Campo Valor
Recurso Bookings / Availability
Base URL /api/v1/bookings, /api/v1/doctors
Autor Carlos Ramirez
Fecha 2025-03-25
Estado Agreed
Spec relacionada feature-booking-system.spec.md

Convenciones Generales

Autenticacion

Bearer token JWT. Todos los endpoints requieren autenticacion.

Paginacion

Cursor-based: ?cursor=<lastId>&limit=20

Fechas y horas

  • Fechas en formato YYYY-MM-DD.
  • Horas en formato HH:mm.
  • Timestamps en ISO 8601 UTC (2025-03-20T10:30:00Z).
  • Los horarios de slots se muestran en la zona horaria de la clinica.

Endpoints

GET /api/v1/doctors

Descripcion: Lista medicos con filtros de especialidad y clinica.

Autorizacion: Cualquier usuario autenticado.

Query params: | Param | Tipo | Requerido | Default | Descripcion | |-------|------|-----------|---------|-------------| | specialtyId | UUID | No | - | Filtrar por especialidad | | clinicId | UUID | No | - | Filtrar por clinica | | name | string | No | - | Buscar por nombre (parcial) | | cursor | UUID | No | - | ID del ultimo resultado | | limit | integer | No | 20 | Max resultados (1-50) |

Response exitosa:

Status: 200 OK

{
  "data": [
    {
      "id": "d1a2b3c4-...",
      "firstName": "Ana",
      "lastName": "Garcia",
      "licenseNumber": "MN-12345",
      "specialties": [
        {
          "id": "s1a2b3c4-...",
          "name": "Cardiologia"
        }
      ],
      "clinics": [
        {
          "id": "c1a2b3c4-...",
          "name": "Clinica San Martin",
          "address": "Av. Corrientes 1234, CABA"
        }
      ],
      "nextAvailableSlot": "2025-03-22T09:00:00-03:00"
    }
  ],
  "pagination": {
    "nextCursor": "d1a2b3c4-...",
    "hasMore": true
  }
}

GET /api/v1/doctors/:doctorId/availability

Descripcion: Retorna los slots disponibles de un medico en un rango de fechas.

Autorizacion: Cualquier usuario autenticado.

Path params: | Param | Tipo | Requerido | Descripcion | |-------|------|-----------|-------------| | doctorId | UUID | Si | ID del medico |

Query params: | Param | Tipo | Requerido | Default | Descripcion | |-------|------|-----------|---------|-------------| | dateFrom | date | Si | - | Fecha inicio (YYYY-MM-DD) | | dateTo | date | Si | - | Fecha fin (YYYY-MM-DD) | | clinicId | UUID | No | - | Filtrar por clinica | | specialtyId | UUID | No | - | Filtrar por especialidad |

Response exitosa:

Status: 200 OK

{
  "data": {
    "doctor": {
      "id": "d1a2b3c4-...",
      "firstName": "Ana",
      "lastName": "Garcia"
    },
    "slots": [
      {
        "date": "2025-03-22",
        "startTime": "09:00",
        "endTime": "09:30",
        "clinicId": "c1a2b3c4-...",
        "clinicName": "Clinica San Martin",
        "timezone": "America/Argentina/Buenos_Aires"
      },
      {
        "date": "2025-03-22",
        "startTime": "09:30",
        "endTime": "10:00",
        "clinicId": "c1a2b3c4-...",
        "clinicName": "Clinica San Martin",
        "timezone": "America/Argentina/Buenos_Aires"
      }
    ]
  }
}

Responses de error:

Status Code Cuando
400 INVALID_DATE_RANGE dateFrom > dateTo o rango > 30 dias
404 DOCTOR_NOT_FOUND El medico no existe

POST /api/v1/bookings

Descripcion: Crea una nueva reserva de turno.

Autorizacion: PATIENT.

Request:

Body:

{
  "doctorId": "d1a2b3c4-...",
  "clinicId": "c1a2b3c4-...",
  "specialtyId": "s1a2b3c4-...",
  "date": "2025-03-22",
  "startTime": "09:00"
}

Campo Tipo Requerido Descripcion
doctorId UUID Si ID del medico
clinicId UUID Si ID de la clinica
specialtyId UUID Si ID de la especialidad
date date Si Fecha del turno (YYYY-MM-DD)
startTime time Si Hora de inicio (HH:mm)

Response exitosa:

Status: 201 Created

{
  "data": {
    "id": "b1a2b3c4-...",
    "patientId": "p1a2b3c4-...",
    "doctor": {
      "id": "d1a2b3c4-...",
      "firstName": "Ana",
      "lastName": "Garcia"
    },
    "clinic": {
      "id": "c1a2b3c4-...",
      "name": "Clinica San Martin",
      "address": "Av. Corrientes 1234, CABA"
    },
    "specialty": {
      "id": "s1a2b3c4-...",
      "name": "Cardiologia"
    },
    "date": "2025-03-22",
    "startTime": "09:00",
    "endTime": "09:30",
    "status": "CONFIRMED",
    "createdAt": "2025-03-20T15:30:00Z"
  },
  "message": "Turno reservado exitosamente."
}

Responses de error:

Status Code Cuando
400 VALIDATION_ERROR Datos invalidos o faltantes
400 SLOT_TOO_SOON Menos de 2h de anticipacion
403 PATIENT_BLOCKED Paciente bloqueado por penalizaciones
409 SLOT_ALREADY_BOOKED El slot ya fue reservado por otro paciente
409 DUPLICATE_BOOKING El paciente ya tiene turno con ese medico hoy

GET /api/v1/bookings

Descripcion: Lista los turnos del usuario autenticado.

Autorizacion: PATIENT (ve sus turnos), DOCTOR (ve su agenda), ADMIN (ve todos).

Query params: | Param | Tipo | Requerido | Default | Descripcion | |-------|------|-----------|---------|-------------| | status | string | No | - | Filtrar por status (CONFIRMED, CANCELLED, etc.) | | dateFrom | date | No | hoy | Fecha inicio | | dateTo | date | No | +30 dias | Fecha fin | | cursor | UUID | No | - | Paginacion | | limit | integer | No | 20 | Max resultados |

Response exitosa:

Status: 200 OK

{
  "data": [
    {
      "id": "b1a2b3c4-...",
      "doctor": {
        "id": "d1a2b3c4-...",
        "firstName": "Ana",
        "lastName": "Garcia"
      },
      "clinic": {
        "id": "c1a2b3c4-...",
        "name": "Clinica San Martin"
      },
      "specialty": {
        "name": "Cardiologia"
      },
      "date": "2025-03-22",
      "startTime": "09:00",
      "endTime": "09:30",
      "status": "CONFIRMED",
      "createdAt": "2025-03-20T15:30:00Z"
    }
  ],
  "pagination": {
    "nextCursor": "b1a2b3c4-...",
    "hasMore": false
  }
}

GET /api/v1/bookings/:bookingId

Descripcion: Retorna el detalle de un turno especifico.

Autorizacion: El paciente dueno, el medico asignado, o un admin.

Response exitosa:

Status: 200 OK

{
  "data": {
    "id": "b1a2b3c4-...",
    "patientId": "p1a2b3c4-...",
    "doctor": {
      "id": "d1a2b3c4-...",
      "firstName": "Ana",
      "lastName": "Garcia",
      "licenseNumber": "MN-12345"
    },
    "clinic": {
      "id": "c1a2b3c4-...",
      "name": "Clinica San Martin",
      "address": "Av. Corrientes 1234, CABA",
      "timezone": "America/Argentina/Buenos_Aires"
    },
    "specialty": {
      "id": "s1a2b3c4-...",
      "name": "Cardiologia"
    },
    "date": "2025-03-22",
    "startTime": "09:00",
    "endTime": "09:30",
    "status": "CONFIRMED",
    "cancellationPenalty": false,
    "createdAt": "2025-03-20T15:30:00Z"
  }
}

Responses de error:

Status Code Cuando
403 FORBIDDEN El usuario no tiene acceso a este booking
404 BOOKING_NOT_FOUND El booking no existe

PATCH /api/v1/bookings/:bookingId/cancel

Descripcion: Cancela un turno.

Autorizacion: El paciente dueno o el medico asignado.

Request:

Body:

{
  "reason": "No puedo asistir por motivos personales"
}

Campo Tipo Requerido Descripcion
reason string No Motivo de cancelacion

Response exitosa:

Status: 200 OK

{
  "data": {
    "id": "b1a2b3c4-...",
    "status": "CANCELLED",
    "cancelledAt": "2025-03-21T10:00:00Z",
    "cancellationPenalty": true,
    "penaltyCount": 1,
    "message": "Turno cancelado. Se aplico penalizacion por cancelacion tardia (menos de 24h)."
  }
}

Responses de error:

Status Code Cuando
400 BOOKING_NOT_CANCELLABLE El booking no esta en status CONFIRMED
403 FORBIDDEN El usuario no tiene permiso para cancelar
404 BOOKING_NOT_FOUND El booking no existe

Codigos de Error Especificos

Code HTTP Status Descripcion
SLOT_ALREADY_BOOKED 409 El slot fue reservado por otro paciente
SLOT_TOO_SOON 400 Menos de 2h de anticipacion
DUPLICATE_BOOKING 409 Ya tiene turno con ese medico hoy
PATIENT_BLOCKED 403 Paciente bloqueado por penalizaciones
BOOKING_NOT_CANCELLABLE 400 No se puede cancelar (ya completado/cancelado)
DOCTOR_NOT_FOUND 404 Medico no existe
BOOKING_NOT_FOUND 404 Booking no existe
INVALID_DATE_RANGE 400 Rango de fechas invalido

Checklist de Completitud

  • Todos los endpoints documentados
  • Request y response con ejemplos concretos
  • Errores documentados con codigos especificos
  • Autorizacion especificada por endpoint
  • Paginacion documentada
  • Revisada por frontend team
  • Revisada por otro ingeniero backend
  • Derivados generados (test plan / OpenAPI spec)

Archivos relacionados