# Servicios visibles, sedes y profesionales visibles del negocio

> GET /api/v1/catalogo

`GET /api/v1/catalogo`

Scope `catalogo:leer`. Mismo catálogo que la página pública de reservas.

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

## Parámetros

| Nombre | En | Tipo | Obligatorio | Descripción |
| --- | --- | --- | --- | --- |
| `sucursalId` | query | string | No | Acota los profesionales a esa sede (si el negocio tiene más de una). |

## Ejemplo

curl:

```bash
curl "https://turnovapp.com/api/v1/catalogo" \
  -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/catalogo", {
  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 | Catálogo |
| 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": {
    "negocio": {
      "nombre": "Masaje descontracturante",
      "zonaHoraria": "America/Argentina/Buenos_Aires",
      "moneda": "ARS",
      "cobraSena": false
    },
    "sedes": [
      {
        "id": "cmh4k2n9x0001",
        "nombre": "Masaje descontracturante",
        "direccion": "Av. Colón 1234, Córdoba",
        "principal": false
      }
    ],
    "profesionales": [
      {
        "id": "cmh4k2n9x0001",
        "nombre": "Masaje descontracturante",
        "especialidad": "Masajista"
      }
    ],
    "servicios": [
      {
        "id": "cmh4k2n9x0001",
        "nombre": "Masaje descontracturante",
        "descripcion": "60 minutos con aceites esenciales.",
        "duracionMin": 60,
        "precio": 25000,
        "descuentoPct": 0,
        "sesiones": 1,
        "cantidadProfesionales": 1,
        "comboPorEtapas": false,
        "seReservaPorWhatsapp": false,
        "categorias": [
          {
            "id": "cmh3c0cat001",
            "nombre": "Masajes"
          }
        ],
        "opciones": [
          {
            "id": "cmh4k2n9x0001",
            "nombre": "Masaje descontracturante",
            "precio": 25000,
            "duracionMin": 60,
            "capacidadPersonas": 1,
            "cantidadProfesionales": 1,
            "comboPorEtapas": false
          }
        ],
        "extras": [],
        "profesionales": [
          {
            "id": "cmh4k2n9x0001",
            "nombre": "Masaje descontracturante",
            "especialidad": "Masajista"
          }
        ]
      }
    ]
  }
}
```

| Campo | Tipo | Obligatorio | Descripción |
| --- | --- | --- | --- |
| `datos.negocio` | object | No |  |
| `datos.negocio.nombre` | string | No |  |
| `datos.negocio.zonaHoraria` | string | No |  |
| `datos.negocio.moneda` | `"ARS"` | No |  |
| `datos.negocio.cobraSena` | boolean | No |  |
| `datos.sedes` | array de object | No |  |
| `datos.sedes[].id` | string | No |  |
| `datos.sedes[].nombre` | string | No |  |
| `datos.sedes[].direccion` | string o null | No |  |
| `datos.sedes[].principal` | boolean | No |  |
| `datos.profesionales` | array de object | No |  |
| `datos.profesionales[].id` | string | No |  |
| `datos.profesionales[].nombre` | string | No |  |
| `datos.profesionales[].especialidad` | string o null | No |  |
| `datos.servicios` | array de object | No |  |
| `datos.servicios[].id` | string | No |  |
| `datos.servicios[].nombre` | string | No |  |
| `datos.servicios[].descripcion` | string o null | No |  |
| `datos.servicios[].duracionMin` | integer | No |  |
| `datos.servicios[].precio` | number | No | Precio de lista. El importe final lo calcula el servidor al reservar. |
| `datos.servicios[].descuentoPct` | number | No |  |
| `datos.servicios[].sesiones` | integer | No | Mayor a 1: paquete de sesiones. |
| `datos.servicios[].cantidadProfesionales` | integer | No |  |
| `datos.servicios[].comboPorEtapas` | boolean | No |  |
| `datos.servicios[].seReservaPorWhatsapp` | boolean | No | true: la reserva por la API responde 409 SERVICIO_DERIVADO_WHATSAPP. |
| `datos.servicios[].categorias` | array de object | No |  |
| `datos.servicios[].categorias[].id` | string | No |  |
| `datos.servicios[].categorias[].nombre` | string | No |  |
| `datos.servicios[].opciones` | array de object | No |  |
| `datos.servicios[].opciones[].id` | string | No |  |
| `datos.servicios[].opciones[].nombre` | string | No |  |
| `datos.servicios[].opciones[].precio` | number o null | No |  |
| `datos.servicios[].opciones[].duracionMin` | integer o null | No |  |
| `datos.servicios[].opciones[].capacidadPersonas` | integer | No |  |
| `datos.servicios[].opciones[].cantidadProfesionales` | integer o null | No |  |
| `datos.servicios[].opciones[].comboPorEtapas` | boolean | No |  |
| `datos.servicios[].extras` | array de object | No |  |
| `datos.servicios[].extras[].id` | string | No |  |
| `datos.servicios[].extras[].nombre` | string | No |  |
| `datos.servicios[].extras[].precio` | number | No |  |
| `datos.servicios[].extras[].duracionMin` | integer | No |  |
| `datos.servicios[].extras[].cantidadMax` | integer | No | Para pedir N unidades, repetir el id N veces en addOnIds. |
| `datos.servicios[].profesionales` | array de object | No |  |
| `datos.servicios[].profesionales[].id` | string | No |  |
| `datos.servicios[].profesionales[].nombre` | string | No |  |
| `datos.servicios[].profesionales[].especialidad` | string o null | No |  |

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