Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/JuanSerna14/Final-lenguaje-Avanzado/llms.txt

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

The /api/reservas endpoints manage bookings (reservas) against sports courts. Both routes are protected by the verifyToken middleware and require a valid JWT Bearer token. The POST endpoint includes server-side overlap detection — before inserting a new reservation it calls reservasRepository.existeSolapamiento(), which uses PostgreSQL’s OVERLAPS operator to detect time-range conflicts on the same court and date. If a conflict is found, the API returns 409 rather than allowing a double-booking.

GET /api/reservas

Returns all reservations ordered by date and start time (ORDER BY r.fecha ASC, r.hora_inicio ASC). The query uses a JOIN on the canchas table, so each reservation object includes cancha_nombre alongside the foreign key cancha_id.

Authentication

Requires Authorization: Bearer <accessToken>.

Example request

curl http://localhost:8000/api/reservas \
  -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIs...'

Response — 200 OK

{
  "ok": true,
  "data": [
    {
      "id": 1,
      "cancha_id": 1,
      "cancha_nombre": "Sintética Central",
      "fecha": "2025-06-15",
      "hora_inicio": "09:00:00",
      "hora_fin": "11:00:00",
      "nombre_cliente": "Juan Pérez",
      "telefono": "3001234567",
      "estado": "pendiente",
      "origen": "interfaz",
      "created_at": "2025-06-01T00:00:00.000Z"
    }
  ]
}
ok
boolean
Always true on a successful response.
data
Reserva[]

Error codes

CodeMeaning
401Missing or invalid Bearer token
500Internal server error — { ok: false, mensaje: "Error al obtener las reservas" }

POST /api/reservas

Creates a new court reservation. The request body is validated with the Zod schema CrearReservaSchema from reservas.types.ts. After validation the service checks that the referenced court exists, then verifies there are no overlapping non-cancelled reservations before inserting.

Authentication

Requires Authorization: Bearer <accessToken>.

Request body

cancha_id
integer
required
The ID of the court to book. Must be a positive integer. The API will return 404 if no court with this ID exists.
fecha
string
required
Reservation date in YYYY-MM-DD format (e.g. "2025-06-15"). Validated with the regex /^\d{4}-\d{2}-\d{2}$/.
hora_inicio
string
required
Start time in HH:MM format (e.g. "09:00"). Validated with the regex /^\d{2}:\d{2}$/.
hora_fin
string
required
End time in HH:MM format (e.g. "11:00"). Validated with the regex /^\d{2}:\d{2}$/. Must be after hora_inicio — enforced by the database CHECK constraint hora_valida (hora_fin > hora_inicio).
nombre_cliente
string
required
Full name of the customer. Must be at least 1 character.
telefono
string
required
Customer contact number as a string. Must be at least 7 characters.
origen
string
Channel that originated the booking. Accepted values: "whatsapp" or "interfaz". Defaults to "interfaz" if omitted.

Example request

curl -X POST http://localhost:8000/api/reservas \
  -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIs...' \
  -H 'Content-Type: application/json' \
  -d '{"cancha_id": 1, "fecha": "2025-06-15", "hora_inicio": "09:00", "hora_fin": "11:00", "nombre_cliente": "Juan Pérez", "telefono": "3001234567", "origen": "interfaz"}'

Response — 201 Created

{
  "ok": true,
  "data": {
    "id": 5,
    "cancha_id": 1,
    "fecha": "2025-06-15",
    "hora_inicio": "09:00:00",
    "hora_fin": "11:00:00",
    "nombre_cliente": "Juan Pérez",
    "telefono": "3001234567",
    "estado": "pendiente",
    "origen": "interfaz",
    "created_at": "2025-06-14T20:00:00.000Z"
  }
}
ok
boolean
Always true on successful creation.
data
Reserva
The newly inserted reservation returned from RETURNING *. Includes the auto-assigned id, estado (defaulted to pendiente), and created_at.

Response — 400 Bad Request (Zod validation failure)

Returned when the body fails CrearReservaSchema Zod parsing. Unlike POST /api/canchas, the errores array contains raw Zod ZodIssue objects (not remapped to {campo, problema}):
{
  "ok": false,
  "mensaje": "Error de validación",
  "errores": [
    {
      "code": "invalid_string",
      "validation": "regex",
      "message": "La fecha debe tener el formato YYYY-MM-DD (ej: 2025-06-15)",
      "path": ["fecha"]
    }
  ]
}

Error codes

CodeMeaning
400Request body failed Zod validation — { ok: false, mensaje: "Error de validación", errores: [<ZodIssue>, ...] }
401Missing or invalid Bearer token
404The referenced cancha_id does not exist — { ok: false, mensaje: "Cancha con ID <id> no encontrada" }
409Time slot conflict — { ok: false, mensaje: "La cancha ya se encuentra reservada de HH:MM a HH:MM" }
500Internal server error

Conflict detection

Before inserting, the API calls reservasRepository.existeSolapamiento(cancha_id, fecha, hora_inicio, hora_fin). This runs the following PostgreSQL query:
SELECT id FROM reservas
WHERE cancha_id = $1
  AND fecha = $2
  AND estado != 'cancelada'
  AND (hora_inicio, hora_fin) OVERLAPS ($3::time, $4::time)
PostgreSQL’s OVERLAPS operator returns true when two time ranges share any moment, so even a partial overlap (e.g. a new booking from 10:00–12:00 against an existing 09:00–11:00 booking) is detected and rejected. Reservations with estado = 'cancelada' are excluded from the check and do not block new bookings.

Reservation states

Reservations are created with estado = 'pendiente' by default (the INSERT statement omits the estado column, so the database default applies). The estado column has a CHECK constraint that allows exactly three values:
EstadoMeaning
pendienteBooking received, awaiting confirmation. Default on creation.
confirmadaBooking has been confirmed by staff or the system.
canceladaBooking has been cancelled. Excluded from overlap checks, freeing the slot.
There is currently no API endpoint to update estado. State transitions must be performed directly in the database or via a future PATCH /api/reservas/:id endpoint.

Courts API

Manage the courts that can be reserved, including listing, fetching by ID, and creation.

API Overview

All PitchPro endpoints at a glance with base URL, auth format, and error conventions.

Authentication Guide

Learn how to obtain and refresh Bearer tokens used on all reservation requests.

Build docs developers (and LLMs) love