# Horarios libres de un servicio

> GET /api/v1/disponibilidad

`GET /api/v1/disponibilidad`

Scope `disponibilidad:leer`. Horas en la zona del negocio. Parámetros fuera de la lista dan 400. La respuesta puede tener hasta 45 segundos de antigüedad (caché por negocio y parámetros); la reserva vuelve a validar el horario.

> Autenticación: `Authorization: Bearer <clave>`. Ver [Autenticación](https://turnovapp.com/docs/autenticacion.md).

## Parámetros

| Nombre | En | Tipo | Obligatorio | Descripción |
| --- | --- | --- | --- | --- |
| `servicioId` | query | string | Sí |  |
| `varianteId` | query | string | No | Opción del servicio (obligatoria si el servicio tiene opciones). |
| `profesionalId` | query | string | No |  |
| `sucursalId` | query | string | No |  |
| `desde` | query | string (date) | No | AAAA-MM-DD; por defecto, hoy. |
| `dias` | query | integer | No | Entre 1 y 60. Por defecto `14`. |
| `addOnIds` | query | string | No | Ids de extras separados por coma (estiran la duración). |

## Ejemplo

curl:

```bash
curl "https://turnovapp.com/api/v1/disponibilidad?servicioId=cmh3s0abc0012&desde=2030-01-01&dias=7" \
  -H "Authorization: Bearer $TURNOVA_CLAVE_SECRETA"
```

JavaScript:

```js
// Desde el navegador, en un origen cargado en la clave pública.
const res = await fetch("https://turnovapp.com/api/v1/disponibilidad?servicioId=cmh3s0abc0012&desde=2030-01-01&dias=7", {
  headers: {
    Authorization: "Bearer tnv_pk_TU_CLAVE_PUBLICA",
  },
});
const r = await res.json();
if (!r.ok) throw new Error(`${r.error.codigo}: ${r.error.mensaje}`);
```

## Respuestas

| HTTP | Qué significa |
| --- | --- |
| 200 | Horarios |
| 400 | Datos inválidos: mirá `error.campos` (`ENTRADA_INVALIDA`, `IDEMPOTENCY_KEY_FALTANTE`…). |
| 401 | Clave faltante, inválida o revocada. |
| 403 | Origen no permitido, permiso faltante, clave secreta desde un navegador o plan sin la API (`PLAN_SIN_API`). |
| 404 | No existe o no es de este negocio. |
| 429 | Demasiados pedidos (`LIMITE_USO`): esperá `Retry-After` segundos. |
| 500 | Error técnico: reintentá con los mismos datos (y la misma `Idempotency-Key`). |

### Respuesta 200

```json
{
  "version": 1,
  "ok": true,
  "progreso": {
    "principal": "CONSULTADO"
  },
  "requiereRevision": false,
  "datos": {
    "horarios": {
      "2030-01-10": [
        "10:00",
        "11:00",
        "15:30"
      ]
    },
    "horariosPorProfesional": {
      "cmh3p0lucia01": {
        "2030-01-10": [
          "10:00",
          "15:30"
        ]
      }
    },
    "diasSinLugar": [
      "2030-01-12"
    ],
    "profesionales": [
      {
        "id": "cmh4k2n9x0001",
        "nombre": "Masaje descontracturante"
      }
    ],
    "finPorHorario": {}
  }
}
```

| Campo | Tipo | Obligatorio | Descripción |
| --- | --- | --- | --- |
| `datos.horarios` | object | No | Por fecha AAAA-MM-DD. |
| `datos.horariosPorProfesional` | object | No |  |
| `datos.diasSinLugar` | array de string (date) | No |  |
| `datos.profesionales` | array de object | No |  |
| `datos.profesionales[].id` | string | No |  |
| `datos.profesionales[].nombre` | string | No |  |
| `datos.finPorHorario` | object | No | Solo combos por etapas: fin real por fecha y hora de inicio. |

Los errores siguen el formato común: ver [Errores](https://turnovapp.com/docs/errores.md).
