# API Reference - SmashPoint

Documentacion completa de los endpoints REST de la API de SmashPoint.

## Informacion General

- **Base URL:** `http://localhost:3000/api`
- **Autenticacion:** Basada en sesiones (NextAuth.js)
- **Formato:** JSON
- **Codificacion:** UTF-8

### Codigos de Estado HTTP

| Codigo | Descripcion |
|--------|-------------|
| 200 | Exito |
| 201 | Recurso creado |
| 400 | Solicitud invalida |
| 401 | No autorizado |
| 403 | Prohibido (sin permisos) |
| 404 | Recurso no encontrado |
| 409 | Conflicto (ej: duplicado) |
| 500 | Error interno del servidor |

### Roles de Usuario

| Rol | Descripcion | Permisos |
|-----|-------------|----------|
| `SUPER_ADMIN` | Administrador del sistema | Acceso total |
| `ORG_ADMIN` | Administrador de organizacion | Gestion completa de la organizacion |
| `SITE_ADMIN` | Administrador de sede | Gestion de una sede especifica |
| `RECEPTIONIST` | Recepcionista | Reservas, ventas, clientes |
| `COACH` | Entrenador | Acceso limitado |

---

## Autenticacion

### Endpoints de NextAuth

```
GET/POST  /api/auth/[...nextauth]
```

NextAuth maneja automaticamente los siguientes endpoints:

| Ruta | Metodo | Descripcion |
|------|--------|-------------|
| `/api/auth/signin` | GET | Pagina de inicio de sesion |
| `/api/auth/signout` | POST | Cerrar sesion |
| `/api/auth/session` | GET | Obtener sesion actual |
| `/api/auth/csrf` | GET | Token CSRF |
| `/api/auth/providers` | GET | Proveedores disponibles |
| `/api/auth/callback/:provider` | GET/POST | Callback de proveedor |

---

## Sedes (Sites)

### Listar Sedes

```http
GET /api/sites
```

**Autenticacion:** Requerida

**Respuesta Exitosa (200):**

```json
[
  {
    "id": "clxyz123",
    "name": "Padel Club Centro",
    "slug": "padel-club-centro",
    "address": "Calle Principal 123",
    "phone": "+34 600 000 000",
    "email": "centro@padelclub.com",
    "timezone": "Europe/Madrid",
    "openTime": "08:00",
    "closeTime": "22:00",
    "courtCount": 6
  }
]
```

---

## Canchas (Courts)

### Listar Canchas

```http
GET /api/courts
```

**Autenticacion:** Requerida

**Parametros de Query:**

| Parametro | Tipo | Descripcion |
|-----------|------|-------------|
| `siteId` | string | Filtrar por sede |

**Respuesta Exitosa (200):**

```json
[
  {
    "id": "clxyz456",
    "name": "Cancha 1",
    "type": "INDOOR",
    "status": "AVAILABLE",
    "pricePerHour": 30.00,
    "description": "Cancha cubierta con iluminacion LED",
    "features": ["LED", "Cristal"],
    "displayOrder": 1,
    "isActive": true,
    "site": {
      "id": "clxyz123",
      "name": "Padel Club Centro",
      "openTime": "08:00",
      "closeTime": "22:00"
    }
  }
]
```

### Crear Cancha

```http
POST /api/courts
```

**Autenticacion:** Requerida
**Roles permitidos:** `SUPER_ADMIN`, `SITE_ADMIN`

**Cuerpo de la Solicitud:**

```json
{
  "siteId": "clxyz123",
  "name": "Cancha 7",
  "type": "OUTDOOR",
  "pricePerHour": 25.00,
  "description": "Cancha exterior",
  "features": ["Cesped artificial"],
  "displayOrder": 7
}
```

**Campos Requeridos:** `siteId`, `name`, `pricePerHour`

**Respuesta Exitosa (201):**

```json
{
  "id": "clxyz789",
  "name": "Cancha 7",
  "type": "OUTDOOR",
  "status": "AVAILABLE",
  "pricePerHour": 25.00,
  "isActive": true,
  "site": { ... }
}
```

### Obtener Cancha por ID

```http
GET /api/courts/{id}
```

**Autenticacion:** Requerida

**Respuesta Exitosa (200):**

```json
{
  "id": "clxyz456",
  "name": "Cancha 1",
  "type": "INDOOR",
  "status": "AVAILABLE",
  "pricePerHour": 30.00,
  "site": {
    "id": "clxyz123",
    "name": "Padel Club Centro",
    "address": "Calle Principal 123",
    "phone": "+34 600 000 000"
  }
}
```

### Actualizar Cancha

```http
PUT /api/courts/{id}
```

**Autenticacion:** Requerida
**Roles permitidos:** `SUPER_ADMIN`, `SITE_ADMIN`

**Cuerpo de la Solicitud (todos los campos opcionales):**

```json
{
  "name": "Cancha 1 VIP",
  "type": "INDOOR",
  "status": "MAINTENANCE",
  "pricePerHour": 35.00,
  "description": "Cancha premium renovada",
  "features": ["LED", "Cristal", "Climatizada"],
  "isActive": true
}
```

### Eliminar Cancha

```http
DELETE /api/courts/{id}
```

**Autenticacion:** Requerida
**Roles permitidos:** `SUPER_ADMIN`, `SITE_ADMIN`

**Respuesta Exitosa (200):**

```json
{
  "message": "Court deleted successfully"
}
```

### Obtener Disponibilidad

```http
GET /api/courts/{id}/availability
```

**Autenticacion:** Requerida

**Parametros de Query:**

| Parametro | Tipo | Descripcion |
|-----------|------|-------------|
| `date` | string | Fecha en formato YYYY-MM-DD |

---

## Reservas (Bookings)

### Listar Reservas

```http
GET /api/bookings
```

**Autenticacion:** Requerida

**Parametros de Query:**

| Parametro | Tipo | Descripcion |
|-----------|------|-------------|
| `siteId` | string | Filtrar por sede |
| `date` | string | Filtrar por fecha (YYYY-MM-DD) |
| `status` | string | PENDING, CONFIRMED, CANCELLED, COMPLETED, NO_SHOW |
| `clientId` | string | Filtrar por cliente |
| `courtId` | string | Filtrar por cancha |

**Respuesta Exitosa (200):**

```json
[
  {
    "id": "clxyz001",
    "startTime": "2024-01-15T10:00:00.000Z",
    "endTime": "2024-01-15T11:30:00.000Z",
    "status": "CONFIRMED",
    "paymentType": "CARD",
    "totalPrice": 45.00,
    "paidAmount": 45.00,
    "notes": null,
    "playerNames": ["Juan", "Maria", "Pedro", "Ana"],
    "court": {
      "id": "clxyz456",
      "name": "Cancha 1",
      "type": "INDOOR"
    },
    "client": {
      "id": "clxyz100",
      "firstName": "Juan",
      "lastName": "Garcia",
      "email": "juan@email.com",
      "phone": "+34 600 111 222"
    },
    "site": {
      "id": "clxyz123",
      "name": "Padel Club Centro"
    }
  }
]
```

### Crear Reserva

```http
POST /api/bookings
```

**Autenticacion:** Requerida

**Cuerpo de la Solicitud:**

```json
{
  "courtId": "clxyz456",
  "clientId": "clxyz100",
  "startTime": "2024-01-15T10:00:00.000Z",
  "endTime": "2024-01-15T11:30:00.000Z",
  "paymentType": "card",
  "notes": "Reserva para cumpleanos",
  "participants": [
    { "name": "Juan" },
    { "name": "Maria" },
    { "name": "Pedro" },
    { "name": "Ana" }
  ]
}
```

**Respuesta Exitosa (201):**

```json
{
  "id": "clxyz002",
  "startTime": "2024-01-15T10:00:00.000Z",
  "endTime": "2024-01-15T11:30:00.000Z",
  "status": "PENDING",
  "totalPrice": 45.00,
  "paidAmount": 0.00,
  "court": { ... },
  "client": { ... }
}
```

**Errores Comunes:**

- `409`: Ya existe una reserva en ese horario
- `404`: Cancha o cliente no encontrado
- `400`: La cancha no esta disponible

### Obtener Reserva por ID

```http
GET /api/bookings/{id}
```

### Actualizar Reserva

```http
PUT /api/bookings/{id}
```

**Cuerpo de la Solicitud:**

```json
{
  "status": "CONFIRMED",
  "notes": "Cliente confirmado por telefono",
  "playerNames": ["Juan", "Maria", "Pedro", "Ana"]
}
```

### Cancelar Reserva

```http
DELETE /api/bookings/{id}
```

**Cuerpo Opcional:**

```json
{
  "cancelReason": "Cliente solicito cancelacion"
}
```

### Registrar Pago de Reserva

```http
POST /api/bookings/{id}/pay
```

**Cuerpo de la Solicitud:**

```json
{
  "amount": 45.00,
  "paymentType": "CARD",
  "reference": "TRX-123456"
}
```

---

## Clientes (Clients)

### Listar Clientes

```http
GET /api/clients
```

**Autenticacion:** Requerida

**Parametros de Query:**

| Parametro | Tipo | Descripcion |
|-----------|------|-------------|
| `search` | string | Buscar por nombre, email o telefono |
| `isActive` | boolean | Filtrar por estado activo |
| `limit` | number | Limite de resultados (max 100) |
| `offset` | number | Desplazamiento para paginacion |

**Respuesta Exitosa (200):**

```json
{
  "data": [
    {
      "id": "clxyz100",
      "firstName": "Juan",
      "lastName": "Garcia",
      "email": "juan@email.com",
      "phone": "+34 600 111 222",
      "level": "INTERMEDIATE",
      "tags": ["VIP", "Torneo"],
      "isActive": true,
      "createdAt": "2024-01-01T00:00:00.000Z",
      "memberships": [
        {
          "id": "clxyz200",
          "status": "ACTIVE",
          "remainingHours": 8,
          "endDate": "2024-06-01T00:00:00.000Z",
          "plan": {
            "id": "clxyz300",
            "name": "Plan Premium",
            "discountPercent": 20
          }
        }
      ],
      "_count": {
        "bookings": 15
      }
    }
  ],
  "pagination": {
    "total": 150,
    "limit": 50,
    "offset": 0,
    "hasMore": true
  }
}
```

### Crear Cliente

```http
POST /api/clients
```

**Cuerpo de la Solicitud:**

```json
{
  "firstName": "Maria",
  "lastName": "Lopez",
  "email": "maria@email.com",
  "phone": "+34 600 333 444",
  "dateOfBirth": "1990-05-15",
  "address": "Calle Nueva 45",
  "notes": "Prefiere canchas interiores",
  "tags": ["Principiante"],
  "skillLevel": "BEGINNER",
  "emergencyContact": {
    "name": "Pedro Lopez",
    "phone": "+34 600 555 666"
  }
}
```

**Campos Requeridos:** `firstName`, `lastName`

### Obtener Cliente por ID

```http
GET /api/clients/{id}
```

### Actualizar Cliente

```http
PUT /api/clients/{id}
```

### Obtener Membresia del Cliente

```http
GET /api/clients/{id}/membership
```

---

## Productos (Products)

### Listar Productos

```http
GET /api/products
```

**Autenticacion:** Requerida

**Parametros de Query:**

| Parametro | Tipo | Descripcion |
|-----------|------|-------------|
| `siteId` | string | Filtrar por sede |
| `categoryId` | string | Filtrar por categoria |
| `search` | string | Buscar por nombre |
| `isActive` | boolean | Solo productos activos |

**Respuesta Exitosa (200):**

```json
[
  {
    "id": "clxyz400",
    "name": "Pelotas HEAD Pro",
    "description": "Bote de 3 pelotas",
    "sku": "BALL-HEAD-001",
    "price": 6.50,
    "costPrice": 4.00,
    "stock": 50,
    "minStock": 10,
    "trackStock": true,
    "image": null,
    "isActive": true,
    "lowStock": false,
    "category": {
      "id": "clxyz500",
      "name": "Pelotas",
      "description": "Pelotas de padel"
    }
  }
]
```

### Crear Producto

```http
POST /api/products
```

**Autenticacion:** Requerida
**Roles permitidos:** `SUPER_ADMIN`, `ORG_ADMIN`, `SITE_ADMIN`

**Cuerpo de la Solicitud:**

```json
{
  "siteId": "clxyz123",
  "categoryId": "clxyz500",
  "name": "Overgrip Wilson",
  "description": "Pack de 3 overgrips",
  "sku": "GRIP-WILSON-001",
  "price": 8.00,
  "costPrice": 5.50,
  "stock": 30,
  "minStock": 5,
  "trackStock": true
}
```

### Actualizar Stock

```http
PATCH /api/products/{id}/stock
```

**Cuerpo de la Solicitud:**

```json
{
  "adjustment": 10,
  "reason": "Reposicion de inventario"
}
```

### Listar Categorias

```http
GET /api/products/categories
```

---

## Ventas (Sales)

### Listar Ventas

```http
GET /api/sales
```

**Autenticacion:** Requerida

**Parametros de Query:**

| Parametro | Tipo | Descripcion |
|-----------|------|-------------|
| `siteId` | string | Filtrar por sede |
| `startDate` | string | Fecha inicio (YYYY-MM-DD) |
| `endDate` | string | Fecha fin (YYYY-MM-DD) |
| `clientId` | string | Filtrar por cliente |
| `createdBy` | string | Filtrar por vendedor |

**Respuesta Exitosa (200):**

```json
[
  {
    "id": "clxyz600",
    "subtotal": 25.00,
    "discount": 0.00,
    "tax": 5.25,
    "total": 30.25,
    "paymentType": "CASH",
    "notes": null,
    "createdAt": "2024-01-15T14:30:00.000Z",
    "items": [
      {
        "id": "clxyz601",
        "quantity": 2,
        "unitPrice": 6.50,
        "subtotal": 13.00,
        "product": {
          "id": "clxyz400",
          "name": "Pelotas HEAD Pro",
          "sku": "BALL-HEAD-001"
        }
      }
    ],
    "payments": [
      {
        "id": "clxyz602",
        "amount": 30.25,
        "paymentType": "CASH",
        "reference": null
      }
    ],
    "client": null,
    "createdBy": {
      "id": "clxyz700",
      "firstName": "Ana",
      "lastName": "Martinez"
    },
    "cashRegister": {
      "id": "clxyz800",
      "site": {
        "id": "clxyz123",
        "name": "Padel Club Centro"
      }
    }
  }
]
```

### Crear Venta

```http
POST /api/sales
```

**Cuerpo de la Solicitud:**

```json
{
  "siteId": "clxyz123",
  "clientId": "clxyz100",
  "items": [
    {
      "productId": "clxyz400",
      "quantity": 2,
      "price": 6.50
    },
    {
      "productId": "clxyz401",
      "quantity": 1,
      "price": 12.00
    }
  ],
  "payments": [
    {
      "amount": 25.00,
      "method": "CASH"
    }
  ],
  "discount": 0,
  "tax": 0,
  "notes": "Venta rapida"
}
```

**Nota:** Requiere caja registradora abierta si hay pago en efectivo.

---

## Caja Registradora (Cash Register)

### Obtener Estado de Caja

```http
GET /api/cash-register
```

**Parametros de Query:**

| Parametro | Tipo | Descripcion |
|-----------|------|-------------|
| `siteId` | string | Sede |
| `status` | string | `open`, `closed`, o `all` |
| `date` | string | Fecha especifica (YYYY-MM-DD) |

**Respuesta Exitosa (200) - Caja Abierta:**

```json
{
  "id": "clxyz800",
  "openingAmount": 100.00,
  "closingAmount": null,
  "expectedAmount": null,
  "difference": null,
  "openedAt": "2024-01-15T08:00:00.000Z",
  "closedAt": null,
  "site": {
    "id": "clxyz123",
    "name": "Padel Club Centro"
  },
  "user": {
    "id": "clxyz700",
    "firstName": "Ana",
    "lastName": "Martinez"
  },
  "paymentBreakdown": {
    "CASH": 250.00,
    "CARD": 180.00
  },
  "totalCashSales": 250.00,
  "expectedAmount": 350.00,
  "_count": {
    "sales": 12,
    "payments": 15
  }
}
```

### Abrir Caja

```http
POST /api/cash-register
```

**Cuerpo de la Solicitud:**

```json
{
  "siteId": "clxyz123",
  "openingAmount": 100.00
}
```

### Cerrar Caja

```http
PUT /api/cash-register/{id}
```

**Cuerpo de la Solicitud:**

```json
{
  "closingAmount": 345.50,
  "notes": "Cuadre correcto"
}
```

### Obtener Transacciones

```http
GET /api/cash-register/{id}/transactions
```

---

## Torneos (Tournaments)

### Listar Torneos

```http
GET /api/tournaments
```

**Parametros de Query:**

| Parametro | Tipo | Descripcion |
|-----------|------|-------------|
| `siteId` | string | Filtrar por sede |
| `status` | string | DRAFT, REGISTRATION_OPEN, IN_PROGRESS, COMPLETED, CANCELLED |
| `startDate` | string | Fecha inicio del rango |
| `endDate` | string | Fecha fin del rango |

**Respuesta Exitosa (200):**

```json
[
  {
    "id": "clxyz900",
    "name": "Torneo de Verano 2024",
    "description": "Torneo amateur categoria B",
    "type": "BRACKET",
    "status": "REGISTRATION_OPEN",
    "startDate": "2024-07-15T09:00:00.000Z",
    "endDate": "2024-07-16T20:00:00.000Z",
    "maxPlayers": 32,
    "entryFee": 25.00,
    "site": {
      "id": "clxyz123",
      "name": "Padel Club Centro"
    },
    "_count": {
      "inscriptions": 18,
      "matches": 0
    }
  }
]
```

### Crear Torneo

```http
POST /api/tournaments
```

**Roles permitidos:** `SUPER_ADMIN`, `ORG_ADMIN`, `SITE_ADMIN`

**Cuerpo de la Solicitud:**

```json
{
  "siteId": "clxyz123",
  "name": "Torneo de Primavera",
  "description": "Torneo para socios",
  "date": "2024-04-20T09:00:00.000Z",
  "endDate": "2024-04-21T20:00:00.000Z",
  "type": "SINGLE_ELIMINATION",
  "category": "B",
  "maxTeams": 16,
  "price": 20.00
}
```

### Obtener Torneo por ID

```http
GET /api/tournaments/{id}
```

### Actualizar Torneo

```http
PUT /api/tournaments/{id}
```

### Listar Inscripciones

```http
GET /api/tournaments/{id}/inscriptions
```

**Respuesta Exitosa (200):**

```json
[
  {
    "id": "clxyzabc",
    "teamName": "Los Campeones",
    "seedNumber": 1,
    "isPaid": true,
    "paidAmount": 25.00,
    "registeredAt": "2024-01-10T12:00:00.000Z",
    "client": {
      "id": "clxyz100",
      "firstName": "Juan",
      "lastName": "Garcia",
      "level": "ADVANCED"
    },
    "partner": {
      "id": "clxyz101",
      "firstName": "Pedro",
      "lastName": "Martinez",
      "level": "ADVANCED"
    }
  }
]
```

### Inscribir Equipo

```http
POST /api/tournaments/{id}/inscriptions
```

**Cuerpo de la Solicitud:**

```json
{
  "player1Id": "clxyz100",
  "player2Id": "clxyz101",
  "teamName": "Los Campeones"
}
```

### Generar Bracket

```http
POST /api/tournaments/{id}/generate-bracket
```

### Actualizar Resultado de Partido

```http
PUT /api/tournaments/{id}/matches/{matchId}
```

**Cuerpo de la Solicitud:**

```json
{
  "score1": "6-4",
  "score2": "6-3",
  "winnerId": "clxyzabc"
}
```

---

## Planes de Membresia (Membership Plans)

### Listar Planes

```http
GET /api/membership-plans
```

**Parametros de Query:**

| Parametro | Tipo | Descripcion |
|-----------|------|-------------|
| `includeInactive` | boolean | Incluir planes inactivos |

**Respuesta Exitosa (200):**

```json
[
  {
    "id": "clxyz300",
    "name": "Plan Premium",
    "description": "Acceso completo con beneficios exclusivos",
    "price": 99.00,
    "durationMonths": 1,
    "courtHours": 10,
    "discountPercent": 20,
    "benefits": ["Reserva anticipada", "Descuento en tienda"],
    "isActive": true,
    "subscriberCount": 45,
    "benefitsSummary": {
      "freeHours": 10,
      "bookingDiscount": 20,
      "extraBenefits": ["Reserva anticipada", "Descuento en tienda"]
    }
  }
]
```

### Crear Plan

```http
POST /api/membership-plans
```

**Roles permitidos:** `SUPER_ADMIN`, `ORG_ADMIN`

**Cuerpo de la Solicitud:**

```json
{
  "name": "Plan Basico",
  "description": "Plan de entrada",
  "price": 29.00,
  "durationMonths": 1,
  "freeHours": 2,
  "bookingDiscount": 10,
  "storeDiscount": 5,
  "extraBenefits": ["Newsletter exclusivo"]
}
```

### Actualizar Plan

```http
PUT /api/membership-plans/{id}
```

---

## Membresias (Memberships)

### Listar Membresias

```http
GET /api/memberships
```

**Parametros de Query:**

| Parametro | Tipo | Descripcion |
|-----------|------|-------------|
| `status` | string | ACTIVE, EXPIRED, CANCELLED, SUSPENDED |
| `planId` | string | Filtrar por plan |
| `search` | string | Buscar por nombre/email del cliente |
| `expiring` | boolean | Solo proximas a vencer (7 dias) |
| `limit` | number | Limite de resultados |
| `offset` | number | Desplazamiento |

**Respuesta Exitosa (200):**

```json
{
  "data": [
    {
      "id": "clxyz200",
      "startDate": "2024-01-01T00:00:00.000Z",
      "endDate": "2024-06-01T00:00:00.000Z",
      "status": "ACTIVE",
      "remainingHours": 8,
      "autoRenew": true,
      "notes": null,
      "plan": {
        "id": "clxyz300",
        "name": "Plan Premium",
        "price": 99.00,
        "durationMonths": 1,
        "courtHours": 10,
        "discountPercent": 20
      },
      "client": {
        "id": "clxyz100",
        "firstName": "Juan",
        "lastName": "Garcia",
        "email": "juan@email.com"
      },
      "isExpiring": false,
      "daysUntilExpiry": 45,
      "benefitsSummary": {
        "freeHours": 10,
        "hoursRemaining": 8,
        "bookingDiscount": 20,
        "extraBenefits": []
      }
    }
  ],
  "pagination": {
    "total": 150,
    "limit": 50,
    "offset": 0,
    "hasMore": true
  }
}
```

### Crear Membresia

```http
POST /api/memberships
```

**Roles permitidos:** `SUPER_ADMIN`, `ORG_ADMIN`, `SITE_ADMIN`, `RECEPTIONIST`

**Cuerpo de la Solicitud:**

```json
{
  "clientId": "clxyz100",
  "planId": "clxyz300",
  "startDate": "2024-02-01T00:00:00.000Z",
  "endDate": "2024-03-01T00:00:00.000Z",
  "autoRenew": true,
  "notes": "Primera membresia del cliente"
}
```

### Renovar Membresia

```http
POST /api/memberships/{id}/renew
```

**Cuerpo de la Solicitud:**

```json
{
  "planId": "clxyz300",
  "paymentMethod": "CARD"
}
```

---

## Dashboard

### Obtener Estadisticas

```http
GET /api/dashboard/stats
```

**Parametros de Query:**

| Parametro | Tipo | Descripcion |
|-----------|------|-------------|
| `siteId` | string | Filtrar por sede |
| `date` | string | Fecha especifica (YYYY-MM-DD) |

**Respuesta Exitosa (200):**

```json
{
  "stats": {
    "todayBookings": 24,
    "todayRevenue": 580.50,
    "occupancyRate": 75,
    "activeMembers": 145,
    "pendingBookings": 3,
    "upcomingTournaments": 2
  },
  "courtOccupancy": [
    {
      "courtId": "clxyz456",
      "courtName": "Cancha 1",
      "availableHours": 14,
      "bookedHours": 11.5,
      "occupancyPercent": 82
    }
  ],
  "recentBookings": [
    {
      "id": "clxyz001",
      "startTime": "2024-01-15T10:00:00.000Z",
      "endTime": "2024-01-15T11:30:00.000Z",
      "status": "CONFIRMED",
      "court": {
        "id": "clxyz456",
        "name": "Cancha 1"
      },
      "client": {
        "id": "clxyz100",
        "name": "Juan Garcia"
      }
    }
  ],
  "date": "2024-01-15"
}
```

---

## Errores Comunes

### Error de Autenticacion

```json
{
  "error": "No autorizado"
}
```
**Codigo:** 401

### Error de Permisos

```json
{
  "error": "Forbidden: Insufficient permissions"
}
```
**Codigo:** 403

### Recurso No Encontrado

```json
{
  "error": "Court not found"
}
```
**Codigo:** 404

### Conflicto

```json
{
  "error": "Ya existe una reserva en ese horario"
}
```
**Codigo:** 409

### Error de Validacion

```json
{
  "error": "Invalid booking data",
  "details": {
    "courtId": ["Invalid court ID"],
    "startTime": ["Required"]
  }
}
```
**Codigo:** 400

---

## Notas Adicionales

### Paginacion

Los endpoints que devuelven listas soportan paginacion mediante:

- `limit`: Numero maximo de resultados (default: 50, max: 100)
- `offset`: Numero de registros a saltar

La respuesta incluye metadatos de paginacion:

```json
{
  "data": [...],
  "pagination": {
    "total": 150,
    "limit": 50,
    "offset": 0,
    "hasMore": true
  }
}
```

### Filtrado por Sede

La mayoria de endpoints filtran automaticamente por la sede del usuario si tiene una asignada. Para usuarios con acceso a multiples sedes, se puede especificar `siteId` en los parametros de query.

### Zonas Horarias

Las fechas se manejan en UTC. Cada sede tiene configurada su zona horaria para mostrar correctamente los horarios de apertura/cierre.
