# Maestras

<span>Bienvenido a la </span>**base estructural**<span> de tus integraciones. En esta sección detallamos los servicios disponibles para consultar las "entidades maestras" en la API REST de nuby.</span>

**¿Qué son exactamente las entidades maestras?**<span> Para evitar términos técnicos complejos, piensa en ellas como los </span>**diccionarios predefinidos**, los catálogos base o las listas desplegables de tu sistema.

**¿Por qué son tan importantes para tu conexión?**

- **Estandarización total:**<span> Son listas fijas que organizan la información para que todo se mantenga ordenado y sin ambigüedades (garantizando, por ejemplo, que el sistema identifique correctamente una "Casa" frente a un "Apartamento").</span>
- **Sincronización de lenguaje:**<span> Permiten que tus plataformas externas lean, entiendan y clasifiquen los datos usando exactamente los mismos parámetros y reglas que utiliza tu inmobiliaria.</span>

¡Explora las opciones a continuación para sincronizar tus catálogos y asegurar que todos tus sistemas hablen el mismo idioma!

# Propiedades / Listar Estados

Permite obtener la lista completa de estados posibles que puede tener una propiedad en el sistema. Cada elemento de la respuesta contiene el identificador numérico del estado y su descripción en texto. Este servicio es útil para poblar selectores o filtros de estado en tus integraciones.

<p class="callout info">**¿Para qué sirve este servicio?**  
Úsalo para conocer los valores válidos del campo `estado` al momento de filtrar, crear o actualizar propiedades a través de la API. Así te aseguras de enviar siempre un valor reconocido por el sistema.</p>

---

#### **1. El Endpoint (La dirección web)**

Apunta tu sistema a la siguiente dirección. Recuerda reemplazar <span style="color: rgb(241, 196, 15);">**{{instancia}}**</span> por la dirección web completa que utilizas para ingresar a tu plataforma.

```http
GET https://{{instancia}}/service/v2/public/masters/properties/states
```

<p class="callout info">**¿Qué debes colocar en {{instancia}}?**  
Es muy sencillo: corresponde a la **dirección web principal** que utilizas a diario para ingresar a tu plataforma (incluyendo la terminación `.nuby.app` o `.arrendasoft.co`).  
Por ejemplo, si para entrar a tu sistema escribes `inmobiliaria.nuby.app` o `inmobiliaria.arrendasoft.co` en tu navegador, esa será exactamente tu instancia. Solo asegúrate de no incluir el "https://" ni barras diagonales ("/") al final.</p>

#### **2. La Petición (¿Qué debes enviarnos?)**

Este servicio no requiere cuerpo en la petición. Solo necesitas enviar los encabezados correctos:

<table border="1" id="bkmrk-m%C3%A9todo-get-content-t" style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 20%;"></col><col style="width: 80%;"></col></colgroup><tbody><tr><td>**Método**</td><td>GET</td></tr><tr><td>**Content-Type**</td><td>application/json</td></tr><tr><td>**Authorization**</td><td>**Bearer token**, Token obtenido al consumir el servicio [Login](https://docs.nuby.ai/books/api-nuby-v2/page/login "Login")</td></tr></tbody></table>

<p class="callout warning">**¿Aún no tienes tu Token de acceso?**  
Para consumir este servicio necesitas un Token vigente. Consulta el servicio de [Login](https://docs.nuby.ai/books/api-nuby-v2/page/login) para aprender cómo obtenerlo.</p>

#### **3. La Respuesta (¿Qué te entregaremos?)**

Si tu Token es válido, el sistema te devolverá una lista con todos los estados posibles de una propiedad. La respuesta se verá así:

```json
[
    {
        "id": 1,
        "estado": "Activa"
    },
    {
        "id": 0,
        "estado": "Arrendada"
    },
    {
        "id": 2,
        "estado": "Inactiva"
    },
    {
        "id": 3,
        "estado": "Vendida"
    }
]
```

Tabla con la descripción de cada campo del JSON:

<table border="1" id="bkmrk-clave-descripci%C3%B3n-id" style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 20%;"></col><col style="width: 80%;"></col></colgroup><thead><tr><th>Clave</th><th>Descripción</th></tr></thead><tbody><tr><td>**id**</td><td>Identificador numérico del estado. Utiliza este valor cuando necesites filtrar propiedades por estado o actualizar el estado de una propiedad a través de la API.</td></tr><tr><td>**estado**</td><td>Nombre descriptivo del estado en texto legible (por ejemplo: "Activa", "Arrendada").</td></tr></tbody></table>

#### **4. Seguridad y Posibles Errores**

<p class="callout danger">**¡Tu pase tiene fecha de caducidad!**</p>

Por medidas de seguridad, el `token` que te entregamos **solo dura 1 hora**. Una vez transcurrido ese tiempo, el pase expirará y el sistema te bloqueará el acceso devolviéndote un error `401`. Cuando esto ocurra, tu sistema simplemente debe volver a consumir el servicio de [Login](https://docs.nuby.ai/books/api-nuby-v2/page/login) para pedir un pase nuevo y continuar trabajando.

Así se ve el error que te devolverá el sistema cuando tu token se haya vencido o intentes usar un pase inválido:

```json
{
    "statusCode": 401,
    "error": {
        "type": "SERVER_ERROR",
        "description": "JWT Token expired."
    }
}
```

Otros posibles errores:

<table border="1" id="bkmrk-c%C3%B3digo-http-descripc" style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 20%;"></col><col style="width: 80%;"></col></colgroup><thead><tr><th>Código HTTP</th><th>Descripción</th></tr></thead><tbody><tr><td>**400**</td><td>Token no enviado o con formato incorrecto. Asegúrate de incluir el encabezado `Authorization: Bearer TU_TOKEN`.</td></tr><tr><td>**401**</td><td>Token expirado o inválido. Solicita uno nuevo a través del servicio de Login.</td></tr><tr><td>**403**</td><td>El cliente OAuth no tiene el scope necesario para esta operación. Para endpoints GET se requiere el scope `read`. Mensaje: `"Insufficient scope. Required: 'read', granted: '{scope_actual}'."`</td></tr></tbody></table>

---

#### **5. Ejemplos de integración**

Aquí tienes ejemplos de código listos para que tus desarrolladores los adapten a tu plataforma:

<details id="bkmrk-curl-curl--x-get-%22ht"><summary>cURL</summary>

```bash
curl -X GET "https://{{instancia}}/service/v2/public/masters/properties/states" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer TU_TOKEN_AQUI"
```

</details><details id="bkmrk-php-%3C%3Fphp-%24instance-"><summary>PHP</summary>

```php
<?php

$instance = 'tu_instancia'; // Reemplaza con tu instancia real
$token = 'TU_TOKEN_AQUI'; // Token obtenido del servicio de Login

$url = "https://{$instance}/service/v2/public/masters/properties/states";

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Content-Type: application/json',
    'Authorization: Bearer ' . $token
]);

$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);

if (curl_errno($ch)) {
    echo 'Error: ' . curl_error($ch);
} else {
    echo "Código de estado HTTP: " . $http_code . "\n";

    if ($http_code === 200) {
        $estados = json_decode($response, true);
        echo "Estados de propiedades:\n";
        foreach ($estados as $estado) {
            echo "  ID: {$estado['id']} - {$estado['estado']}\n";
        }
    } else {
        echo "Error al consultar los estados.\n";
        echo $response . "\n";
    }
}
curl_close($ch);

?>
```

</details><details id="bkmrk-python-import-reques"><summary>Python</summary>

```python
import requests

# 1. Configura tus datos de acceso
instancia = 'mi-inmobiliaria.nuby.app' # Reemplaza con tu dirección web completa
token = 'TU_TOKEN_AQUI' # Token obtenido del servicio de Login

# 2. Prepara la dirección y los encabezados
url = f"https://{instancia}/service/v2/public/masters/properties/states"

headers = {
    "Content-Type": "application/json",
    "Authorization": f"Bearer {token}"
}

# 3. Envía la petición GET y procesa la respuesta
try:
    response = requests.get(url, headers=headers)

    print(f"Código de estado HTTP: {response.status_code}")

    if response.status_code == 200:
        estados = response.json()
        print("Estados de propiedades:")
        for estado in estados:
            print(f"  ID: {estado['id']} - {estado['estado']}")
    else:
        print("Error al consultar los estados.")
        print(f"Detalle del error: {response.text}")

except Exception as e:
    print(f"Ocurrió un error de conexión: {e}")

```

</details><details id="bkmrk-javascript-%2F%2F-1.-con"><summary>JavaScript</summary>

```javascript
// 1. Configura tus datos de acceso
const instancia = 'mi-inmobiliaria.nuby.app'; // Reemplaza con tu dirección web completa
const token = 'TU_TOKEN_AQUI'; // Token obtenido del servicio de Login

// 2. Prepara la dirección
const url = `https://${instancia}/service/v2/public/masters/properties/states`;

// 3. Función para consultar los estados de propiedades
async function consultarEstados() {
    try {
        const response = await fetch(url, {
            method: 'GET',
            headers: {
                'Content-Type': 'application/json',
                'Authorization': `Bearer ${token}`
            }
        });

        console.log(`Código de estado HTTP: ${response.status}`);

        if (response.ok) {
            const estados = await response.json();
            console.log('Estados de propiedades:');
            estados.forEach(estado => {
                console.log(`  ID: ${estado.id} - ${estado.estado}`);
            });
        } else {
            console.log('Error al consultar los estados.');
            const errorData = await response.text();
            console.log(`Detalle del error: ${errorData}`);
        }
    } catch (error) {
        console.error(`Ocurrió un error de conexión: ${error}`);
    }
}

// 4. Ejecutamos la función
consultarEstados();

```

</details><details id="bkmrk-power-query-m-%28excel"><summary>Power Query M (Excel / Power BI)</summary>

```powerquery
let
    // 1. Configura tus datos de acceso
    instancia = "mi-inmobiliaria.nuby.app", // Reemplaza con tu dirección web completa
    token = "TU_TOKEN_AQUI", // Token obtenido del servicio de Login

    // 2. Prepara la dirección de la petición
    url = "https://" & instancia & "/service/v2/public/masters/properties/states",

    // 3. Envía la petición GET con el token de autenticación
    response = Web.Contents(url, [
        Headers = [
            #"Content-Type" = "application/json",
            #"Authorization" = "Bearer " & token
        ]
    ]),

    // 4. Decodifica la respuesta JSON y conviértela en tabla
    jsonResponse = Json.Document(response),
    tabla = Table.FromList(jsonResponse, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
    expandido = Table.ExpandRecordColumn(tabla, "Column1", {"id", "estado"}, {"ID", "Estado"})
in
    expandido
```

</details>

# Propiedades / Listar Clases de Inmueble

Permite obtener la lista completa de clases de inmueble disponibles en el sistema. Cada elemento de la respuesta contiene el identificador único de la clase y su nombre descriptivo. Este servicio es útil para poblar selectores de tipo de inmueble en tus integraciones.

<p class="callout info">**¿Para qué sirve este servicio?**  
Úsalo para conocer los valores válidos del campo `clase` de inmueble al momento de filtrar o registrar propiedades a través de la API. Así te aseguras de enviar siempre un valor reconocido por el sistema. Las clases de inmueble disponibles dependen de la configuración de cada instancia.</p>

---

#### **1. El Endpoint (La dirección web)**

Apunta tu sistema a la siguiente dirección. Recuerda reemplazar <span style="color: rgb(241, 196, 15);">**{{instancia}}**</span> por la dirección web completa que utilizas para ingresar a tu plataforma.

```http
GET https://{{instancia}}/service/v2/public/masters/properties/property-classes
```

<p class="callout info">**¿Qué debes colocar en {{instancia}}?**  
Es muy sencillo: corresponde a la **dirección web principal** que utilizas a diario para ingresar a tu plataforma (incluyendo la terminación `.nuby.app` o `.arrendasoft.co`).  
Por ejemplo, si para entrar a tu sistema escribes `inmobiliaria.nuby.app` o `inmobiliaria.arrendasoft.co` en tu navegador, esa será exactamente tu instancia. Solo asegúrate de no incluir el "https://" ni barras diagonales ("/") al final.</p>

#### **2. La Petición (¿Qué debes enviarnos?)**

Este servicio no requiere cuerpo en la petición. Solo necesitas enviar los encabezados correctos:

<table border="1" id="bkmrk-m%C3%A9todo-get-content-t" style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 20%;"></col><col style="width: 80%;"></col></colgroup><tbody><tr><td>**Método**</td><td>GET</td></tr><tr><td>**Content-Type**</td><td>application/json</td></tr><tr><td>**Authorization**</td><td>**Bearer token**, Token obtenido al consumir el servicio [Login](https://docs.nuby.ai/books/api-nuby-v2/page/login "Login")</td></tr></tbody></table>

<p class="callout warning">**¿Aún no tienes tu Token de acceso?**  
Para consumir este servicio necesitas un Token vigente. Consulta el servicio de [Login](https://docs.nuby.ai/books/api-nuby-v2/page/login) para aprender cómo obtenerlo.</p>

#### **3. La Respuesta (¿Qué te entregaremos?)**

Si tu Token es válido, el sistema te devolverá una lista con todas las clases de inmueble configuradas en tu instancia. La respuesta se verá similar a esta:

```json
[
    {
        "id": "1367",
        "clase": "Amoblados"
    },
    {
        "id": "1253",
        "clase": "Apartaestudio"
    },
    {
        "id": "1247",
        "clase": "Apartamento"
    },
    {
        "id": "1248",
        "clase": "Bodega"
    },
    {
        "id": "1249",
        "clase": "Casa"
    }
]
```

<p class="callout info">**Nota:** Los valores de `id` y la cantidad de clases disponibles pueden variar entre instancias, ya que dependen de la configuración particular de cada inmobiliaria. La lista se devuelve ordenada alfabéticamente por el nombre de la clase.</p>

Tabla con la descripción de cada campo del JSON:

<table border="1" id="bkmrk-clave-descripci%C3%B3n-id" style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 20%;"></col><col style="width: 80%;"></col></colgroup><thead><tr><th>Clave</th><th>Descripción</th></tr></thead><tbody><tr><td>**id**</td><td>Identificador único de la clase de inmueble (tipo texto). Utiliza este valor cuando necesites filtrar propiedades por clase de inmueble a través de la API.</td></tr><tr><td>**clase**</td><td>Nombre descriptivo de la clase de inmueble (por ejemplo: "Apartamento", "Casa", "Bodega").</td></tr></tbody></table>

#### **4. Seguridad y Posibles Errores**

<p class="callout danger">**¡Tu pase tiene fecha de caducidad!**</p>

Por medidas de seguridad, el `token` que te entregamos **solo dura 1 hora**. Una vez transcurrido ese tiempo, el pase expirará y el sistema te bloqueará el acceso devolviéndote un error `401`. Cuando esto ocurra, tu sistema simplemente debe volver a consumir el servicio de [Login](https://docs.nuby.ai/books/api-nuby-v2/page/login) para pedir un pase nuevo y continuar trabajando.

Así se ve el error que te devolverá el sistema cuando tu token se haya vencido o intentes usar un pase inválido:

```json
{
    "statusCode": 401,
    "error": {
        "type": "SERVER_ERROR",
        "description": "JWT Token expired."
    }
}
```

Otros posibles errores:

<table border="1" id="bkmrk-c%C3%B3digo-http-descripc" style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 20%;"></col><col style="width: 80%;"></col></colgroup><thead><tr><th>Código HTTP</th><th>Descripción</th></tr></thead><tbody><tr><td>**400**</td><td>Token no enviado o con formato incorrecto. Asegúrate de incluir el encabezado `Authorization: Bearer TU_TOKEN`.</td></tr><tr><td>**401**</td><td>Token expirado o inválido. Solicita uno nuevo a través del servicio de Login.</td></tr><tr><td>**403**</td><td>El cliente OAuth no tiene el scope necesario para esta operación. Para endpoints GET se requiere el scope `read`. Mensaje: `"Insufficient scope. Required: 'read', granted: '{scope_actual}'."`</td></tr></tbody></table>

---

#### **5. Ejemplos de integración**

Aquí tienes ejemplos de código listos para que tus desarrolladores los adapten a tu plataforma:

<details id="bkmrk-curl-curl--x-get-%22ht"><summary>cURL</summary>

```bash
curl -X GET "https://{{instancia}}/service/v2/public/masters/properties/property-classes" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer TU_TOKEN_AQUI"
```

</details><details id="bkmrk-php-%3C%3Fphp-%24instance-"><summary>PHP</summary>

```php
<?php

$instance = 'tu_instancia'; // Reemplaza con tu instancia real
$token = 'TU_TOKEN_AQUI'; // Token obtenido del servicio de Login

$url = "https://{$instance}/service/v2/public/masters/properties/property-classes";

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Content-Type: application/json',
    'Authorization: Bearer ' . $token
]);

$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);

if (curl_errno($ch)) {
    echo 'Error: ' . curl_error($ch);
} else {
    echo "Código de estado HTTP: " . $http_code . "\n";

    if ($http_code === 200) {
        $clases = json_decode($response, true);
        echo "Clases de inmueble:\n";
        foreach ($clases as $clase) {
            echo "  ID: {$clase['id']} - {$clase['clase']}\n";
        }
    } else {
        echo "Error al consultar las clases de inmueble.\n";
        echo $response . "\n";
    }
}
curl_close($ch);

?>
```

</details><details id="bkmrk-python-import-reques"><summary>Python</summary>

```python
import requests

# 1. Configura tus datos de acceso
instancia = 'mi-inmobiliaria.nuby.app' # Reemplaza con tu dirección web completa
token = 'TU_TOKEN_AQUI' # Token obtenido del servicio de Login

# 2. Prepara la dirección y los encabezados
url = f"https://{instancia}/service/v2/public/masters/properties/property-classes"

headers = {
    "Content-Type": "application/json",
    "Authorization": f"Bearer {token}"
}

# 3. Envía la petición GET y procesa la respuesta
try:
    response = requests.get(url, headers=headers)

    print(f"Código de estado HTTP: {response.status_code}")

    if response.status_code == 200:
        clases = response.json()
        print("Clases de inmueble:")
        for clase in clases:
            print(f"  ID: {clase['id']} - {clase['clase']}")
    else:
        print("Error al consultar las clases de inmueble.")
        print(f"Detalle del error: {response.text}")

except Exception as e:
    print(f"Ocurrió un error de conexión: {e}")

```

</details><details id="bkmrk-javascript-%2F%2F-1.-con"><summary>JavaScript</summary>

```javascript
// 1. Configura tus datos de acceso
const instancia = 'mi-inmobiliaria.nuby.app'; // Reemplaza con tu dirección web completa
const token = 'TU_TOKEN_AQUI'; // Token obtenido del servicio de Login

// 2. Prepara la dirección
const url = `https://${instancia}/service/v2/public/masters/properties/property-classes`;

// 3. Función para consultar las clases de inmueble
async function consultarClasesDeInmueble() {
    try {
        const response = await fetch(url, {
            method: 'GET',
            headers: {
                'Content-Type': 'application/json',
                'Authorization': `Bearer ${token}`
            }
        });

        console.log(`Código de estado HTTP: ${response.status}`);

        if (response.ok) {
            const clases = await response.json();
            console.log('Clases de inmueble:');
            clases.forEach(clase => {
                console.log(`  ID: ${clase.id} - ${clase.clase}`);
            });
        } else {
            console.log('Error al consultar las clases de inmueble.');
            const errorData = await response.text();
            console.log(`Detalle del error: ${errorData}`);
        }
    } catch (error) {
        console.error(`Ocurrió un error de conexión: ${error}`);
    }
}

// 4. Ejecutamos la función
consultarClasesDeInmueble();

```

</details><details id="bkmrk-power-query-m-%28excel"><summary>Power Query M (Excel / Power BI)</summary>

```powerquery
let
    // 1. Configura tus datos de acceso
    instancia = "mi-inmobiliaria.nuby.app", // Reemplaza con tu dirección web completa
    token = "TU_TOKEN_AQUI", // Token obtenido del servicio de Login

    // 2. Prepara la dirección de la petición
    url = "https://" & instancia & "/service/v2/public/masters/properties/property-classes",

    // 3. Envía la petición GET con el token de autenticación
    response = Web.Contents(url, [
        Headers = [
            #"Content-Type" = "application/json",
            #"Authorization" = "Bearer " & token
        ]
    ]),

    // 4. Decodifica la respuesta JSON y conviértela en tabla
    jsonResponse = Json.Document(response),
    tabla = Table.FromList(jsonResponse, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
    expandido = Table.ExpandRecordColumn(tabla, "Column1", {"id", "clase"}, {"ID", "Clase"})
in
    expandido
```

</details>

# Propiedades / Listar Tipos de Servicios

Permite obtener la lista completa de tipos de servicio que puede tener una propiedad en el sistema. Cada elemento de la respuesta contiene el identificador del tipo de servicio y su nombre descriptivo. Este servicio es útil para poblar selectores o filtros de tipo de servicio en tus integraciones.

<p class="callout info">**¿Para qué sirve este servicio?**  
Úsalo para conocer los valores válidos del campo de tipo de servicio al momento de filtrar o registrar propiedades a través de la API. Así te aseguras de enviar siempre un valor reconocido por el sistema. Los nombres descriptivos pueden variar ligeramente entre instancias según la configuración de cada inmobiliaria, pero los identificadores (`id`) son siempre los mismos.</p>

---

#### **1. El Endpoint (La dirección web)**

Apunta tu sistema a la siguiente dirección. Recuerda reemplazar <span style="color: rgb(241, 196, 15);">**{{instancia}}**</span> por la dirección web completa que utilizas para ingresar a tu plataforma.

```http
GET https://{{instancia}}/service/v2/public/masters/properties/service-types
```

<p class="callout info">**¿Qué debes colocar en {{instancia}}?**  
Es muy sencillo: corresponde a la **dirección web principal** que utilizas a diario para ingresar a tu plataforma (incluyendo la terminación `.nuby.app` o `.arrendasoft.co`).  
Por ejemplo, si para entrar a tu sistema escribes `inmobiliaria.nuby.app` o `inmobiliaria.arrendasoft.co` en tu navegador, esa será exactamente tu instancia. Solo asegúrate de no incluir el "https://" ni barras diagonales ("/") al final.</p>

#### **2. La Petición (¿Qué debes enviarnos?)**

Este servicio no requiere cuerpo en la petición. Solo necesitas enviar los encabezados correctos:

<table border="1" id="bkmrk-m%C3%A9todo-get-content-t" style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 20%;"></col><col style="width: 80%;"></col></colgroup><tbody><tr><td>**Método**</td><td>GET</td></tr><tr><td>**Content-Type**</td><td>application/json</td></tr><tr><td>**Authorization**</td><td>**Bearer token**, Token obtenido al consumir el servicio [Login](https://docs.nuby.ai/books/api-nuby-v2/page/login "Login")</td></tr></tbody></table>

<p class="callout warning">**¿Aún no tienes tu Token de acceso?**  
Para consumir este servicio necesitas un Token vigente. Consulta el servicio de [Login](https://docs.nuby.ai/books/api-nuby-v2/page/login) para aprender cómo obtenerlo.</p>

#### **3. La Respuesta (¿Qué te entregaremos?)**

Si tu Token es válido, el sistema te devolverá una lista con los tres tipos de servicio disponibles para propiedades. La respuesta se verá similar a esta:

```json
[
    {
        "id": "arriendo",
        "servicio": "Arriendo"
    },
    {
        "id": "venta",
        "servicio": "Venta"
    },
    {
        "id": "venta y arriendo",
        "servicio": "Venta y Arriendo"
    }
]
```

<p class="callout info">**Nota:** El campo `id` es de tipo texto (string) y sus valores son fijos: `"arriendo"`, `"venta"` y `"venta y arriendo"`. El campo `servicio` muestra el nombre descriptivo, que puede variar ligeramente entre instancias según la configuración de cada inmobiliaria.</p>

Tabla con la descripción de cada campo del JSON:

<table border="1" id="bkmrk-clave-descripci%C3%B3n-id" style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 20%;"></col><col style="width: 80%;"></col></colgroup><thead><tr><th>Clave</th><th>Descripción</th></tr></thead><tbody><tr><td>**id**</td><td>Identificador del tipo de servicio (tipo texto). Valores posibles: `"arriendo"`, `"venta"`, `"venta y arriendo"`. Utiliza este valor cuando necesites filtrar propiedades por tipo de servicio a través de la API.</td></tr><tr><td>**servicio**</td><td>Nombre descriptivo del tipo de servicio (por ejemplo: "Arriendo", "Venta", "Venta y Arriendo").</td></tr></tbody></table>

#### **4. Seguridad y Posibles Errores**

<p class="callout danger">**¡Tu pase tiene fecha de caducidad!**</p>

Por medidas de seguridad, el `token` que te entregamos **solo dura 1 hora**. Una vez transcurrido ese tiempo, el pase expirará y el sistema te bloqueará el acceso devolviéndote un error `401`. Cuando esto ocurra, tu sistema simplemente debe volver a consumir el servicio de [Login](https://docs.nuby.ai/books/api-nuby-v2/page/login) para pedir un pase nuevo y continuar trabajando.

Así se ve el error que te devolverá el sistema cuando tu token se haya vencido o intentes usar un pase inválido:

```json
{
    "statusCode": 401,
    "error": {
        "type": "SERVER_ERROR",
        "description": "JWT Token expired."
    }
}
```

Otros posibles errores:

<table border="1" id="bkmrk-c%C3%B3digo-http-descripc" style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 20%;"></col><col style="width: 80%;"></col></colgroup><thead><tr><th>Código HTTP</th><th>Descripción</th></tr></thead><tbody><tr><td>**400**</td><td>Token no enviado o con formato incorrecto. Asegúrate de incluir el encabezado `Authorization: Bearer TU_TOKEN`.</td></tr><tr><td>**401**</td><td>Token expirado o inválido. Solicita uno nuevo a través del servicio de Login.</td></tr><tr><td>**403**</td><td>El cliente OAuth no tiene el scope necesario para esta operación. Para endpoints GET se requiere el scope `read`. Mensaje: `"Insufficient scope. Required: 'read', granted: '{scope_actual}'."`</td></tr></tbody></table>

---

#### **5. Ejemplos de integración**

Aquí tienes ejemplos de código listos para que tus desarrolladores los adapten a tu plataforma:

<details id="bkmrk-curl-curl--x-get-%22ht"><summary>cURL</summary>

```bash
curl -X GET "https://{{instancia}}/service/v2/public/masters/properties/service-types" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer TU_TOKEN_AQUI"
```

</details><details id="bkmrk-php-%3C%3Fphp-%24instance-"><summary>PHP</summary>

```php
<?php

$instance = 'tu_instancia'; // Reemplaza con tu instancia real
$token = 'TU_TOKEN_AQUI'; // Token obtenido del servicio de Login

$url = "https://{$instance}/service/v2/public/masters/properties/service-types";

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Content-Type: application/json',
    'Authorization: Bearer ' . $token
]);

$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);

if (curl_errno($ch)) {
    echo 'Error: ' . curl_error($ch);
} else {
    echo "Código de estado HTTP: " . $http_code . "\n";

    if ($http_code === 200) {
        $servicios = json_decode($response, true);
        echo "Tipos de servicio:\n";
        foreach ($servicios as $servicio) {
            echo "  ID: {$servicio['id']} - {$servicio['servicio']}\n";
        }
    } else {
        echo "Error al consultar los tipos de servicio.\n";
        echo $response . "\n";
    }
}
curl_close($ch);

?>
```

</details><details id="bkmrk-python-import-reques"><summary>Python</summary>

```python
import requests

# 1. Configura tus datos de acceso
instancia = 'mi-inmobiliaria.nuby.app' # Reemplaza con tu dirección web completa
token = 'TU_TOKEN_AQUI' # Token obtenido del servicio de Login

# 2. Prepara la dirección y los encabezados
url = f"https://{instancia}/service/v2/public/masters/properties/service-types"

headers = {
    "Content-Type": "application/json",
    "Authorization": f"Bearer {token}"
}

# 3. Envía la petición GET y procesa la respuesta
try:
    response = requests.get(url, headers=headers)

    print(f"Código de estado HTTP: {response.status_code}")

    if response.status_code == 200:
        servicios = response.json()
        print("Tipos de servicio:")
        for servicio in servicios:
            print(f"  ID: {servicio['id']} - {servicio['servicio']}")
    else:
        print("Error al consultar los tipos de servicio.")
        print(f"Detalle del error: {response.text}")

except Exception as e:
    print(f"Ocurrió un error de conexión: {e}")

```

</details><details id="bkmrk-javascript-%2F%2F-1.-con"><summary>JavaScript</summary>

```javascript
// 1. Configura tus datos de acceso
const instancia = 'mi-inmobiliaria.nuby.app'; // Reemplaza con tu dirección web completa
const token = 'TU_TOKEN_AQUI'; // Token obtenido del servicio de Login

// 2. Prepara la dirección
const url = `https://${instancia}/service/v2/public/masters/properties/service-types`;

// 3. Función para consultar los tipos de servicio
async function consultarTiposDeServicio() {
    try {
        const response = await fetch(url, {
            method: 'GET',
            headers: {
                'Content-Type': 'application/json',
                'Authorization': `Bearer ${token}`
            }
        });

        console.log(`Código de estado HTTP: ${response.status}`);

        if (response.ok) {
            const servicios = await response.json();
            console.log('Tipos de servicio:');
            servicios.forEach(servicio => {
                console.log(`  ID: ${servicio.id} - ${servicio.servicio}`);
            });
        } else {
            console.log('Error al consultar los tipos de servicio.');
            const errorData = await response.text();
            console.log(`Detalle del error: ${errorData}`);
        }
    } catch (error) {
        console.error(`Ocurrió un error de conexión: ${error}`);
    }
}

// 4. Ejecutamos la función
consultarTiposDeServicio();

```

</details><details id="bkmrk-power-query-m-%28excel"><summary>Power Query M (Excel / Power BI)</summary>

```powerquery
let
    // 1. Configura tus datos de acceso
    instancia = "mi-inmobiliaria.nuby.app", // Reemplaza con tu dirección web completa
    token = "TU_TOKEN_AQUI", // Token obtenido del servicio de Login

    // 2. Prepara la dirección de la petición
    url = "https://" & instancia & "/service/v2/public/masters/properties/service-types",

    // 3. Envía la petición GET con el token de autenticación
    response = Web.Contents(url, [
        Headers = [
            #"Content-Type" = "application/json",
            #"Authorization" = "Bearer " & token
        ]
    ]),

    // 4. Decodifica la respuesta JSON y conviértela en tabla
    jsonResponse = Json.Document(response),
    tabla = Table.FromList(jsonResponse, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
    expandido = Table.ExpandRecordColumn(tabla, "Column1", {"id", "servicio"}, {"ID", "Servicio"})
in
    expandido
```

</details>

# Propiedades / Listar Características

Permite obtener la lista completa de características que pueden tener las propiedades en el sistema. Cada elemento de la respuesta contiene la información detallada de una característica, incluyendo su tipo de campo, opciones disponibles y la clase de inmueble a la que pertenece. Este servicio es útil para construir formularios dinámicos de propiedades o para conocer qué datos se pueden registrar en cada tipo de inmueble.

<p class="callout info">**¿Para qué sirve este servicio?**  
Úsalo para obtener el catálogo de características configuradas en la plataforma. Cada característica está vinculada a una clase de inmueble específica (Apartamento, Casa, Bodega, etc.) y tiene un tipo de campo que indica cómo debe capturarse la información (numérico, checkbox, lista desplegable, etc.). Si necesitas consultar solo las características de una clase de inmueble en particular, utiliza el endpoint de **Listar Características por Clase de Inmueble**.</p>

---

#### **1. El Endpoint (La dirección web)**

Apunta tu sistema a la siguiente dirección. Recuerda reemplazar <span style="color: rgb(241, 196, 15);">**{{instancia}}**</span> por la dirección web completa que utilizas para ingresar a tu plataforma.

```http
GET https://{{instancia}}/service/v2/public/masters/properties/features
```

<p class="callout info">**¿Qué debes colocar en {{instancia}}?**  
Es muy sencillo: corresponde a la **dirección web principal** que utilizas a diario para ingresar a tu plataforma (incluyendo la terminación `.nuby.app` o `.arrendasoft.co`).  
Por ejemplo, si para entrar a tu sistema escribes `inmobiliaria.nuby.app` o `inmobiliaria.arrendasoft.co` en tu navegador, esa será exactamente tu instancia. Solo asegúrate de no incluir el "https://" ni barras diagonales ("/") al final.</p>

#### **2. La Petición (¿Qué debes enviarnos?)**

Este servicio no requiere cuerpo en la petición. Solo necesitas enviar los encabezados correctos:

<table border="1" id="bkmrk-m%C3%A9todo-get-content-t" style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 20%;"></col><col style="width: 80%;"></col></colgroup><tbody><tr><td>**Método**</td><td>GET</td></tr><tr><td>**Content-Type**</td><td>application/json</td></tr><tr><td>**Authorization**</td><td>**Bearer token**, Token obtenido al consumir el servicio [Login](https://docs.nuby.ai/books/api-nuby-v2/page/login "Login")</td></tr></tbody></table>

<p class="callout warning">**¿Aún no tienes tu Token de acceso?**  
Para consumir este servicio necesitas un Token vigente. Consulta el servicio de [Login](https://docs.nuby.ai/books/api-nuby-v2/page/login) para aprender cómo obtenerlo.</p>

#### **3. La Respuesta (¿Qué te entregaremos?)**

Si tu Token es válido, el sistema te devolverá una lista con todas las características configuradas para las propiedades. La respuesta se verá similar a esta:

```json
[
    {
        "id": "1",
        "descripcion": "Nº De Habitaciones",
        "tipo_campo": "numeric",
        "opciones_valores": null,
        "opciones_descripciones": null,
        "orden": "1",
        "grupo": "Características del inmueble",
        "clase_inmueble_id": "1367",
        "clase_inmueble": "Amoblados"
    },
    {
        "id": "2",
        "descripcion": "Nº De Baños",
        "tipo_campo": "numeric",
        "opciones_valores": null,
        "opciones_descripciones": null,
        "orden": "2",
        "grupo": "Características del inmueble",
        "clase_inmueble_id": "1367",
        "clase_inmueble": "Amoblados"
    },
    {
        "id": "54",
        "descripcion": "Oficina",
        "tipo_campo": "checkbox",
        "opciones_valores": "",
        "opciones_descripciones": "",
        "orden": "3",
        "grupo": "Características del Inmueble",
        "clase_inmueble_id": "1248",
        "clase_inmueble": "Bodega"
    },
    {
        "id": "13",
        "descripcion": "Baño Auxiliar",
        "tipo_campo": "checkbox",
        "opciones_valores": null,
        "opciones_descripciones": null,
        "orden": "4",
        "grupo": "Características del Inmueble",
        "clase_inmueble_id": "1249",
        "clase_inmueble": "Casa"
    },
    {
        "id": "38",
        "descripcion": "Parqueadero",
        "tipo_campo": "select",
        "opciones_valores": "propio,visitantes",
        "opciones_descripciones": "Propio,Visitantes",
        "orden": "12",
        "grupo": "Características del Inmueble",
        "clase_inmueble_id": "1249",
        "clase_inmueble": "Casa"
    }
]
```

<p class="callout info">**Nota:** Las características disponibles, sus grupos y las clases de inmueble asociadas dependen de la configuración de cada instancia. La lista se devuelve ordenada por grupo, luego por orden dentro del grupo, y finalmente por descripción alfabéticamente.</p>

Tabla con la descripción de cada campo del JSON:

<table border="1" id="bkmrk-clave-descripci%C3%B3n-id" style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 20%;"></col><col style="width: 80%;"></col></colgroup><thead><tr><th>Clave</th><th>Descripción</th></tr></thead><tbody><tr><td>**id**</td><td>Identificador único de la característica (tipo texto).</td></tr><tr><td>**descripcion**</td><td>Nombre descriptivo de la característica (por ejemplo: "Nº De Habitaciones", "Parqueadero").</td></tr><tr><td>**tipo\_campo**</td><td>Tipo de campo que define cómo se captura la información. Valores posibles: `numeric` (campo numérico), `checkbox` (casilla de verificación), `select` (lista desplegable con opciones predefinidas), entre otros.</td></tr><tr><td>**opciones\_valores**</td><td>Valores técnicos de las opciones disponibles, separados por coma. Aplica únicamente cuando `tipo_campo` es `select`. Será `null` o vacío para otros tipos de campo.</td></tr><tr><td>**opciones\_descripciones**</td><td>Descripciones legibles de las opciones disponibles, separadas por coma. Cada descripción corresponde posicionalmente al valor en `opciones_valores`. Por ejemplo, si `opciones_valores` es `"propio,visitantes"`, las descripciones serán `"Propio,Visitantes"`.</td></tr><tr><td>**orden**</td><td>Posición numérica que indica el orden de presentación de la característica dentro de su grupo.</td></tr><tr><td>**grupo**</td><td>Nombre del grupo al que pertenece la característica (por ejemplo: "Características del Inmueble"). Permite agrupar visualmente las características en un formulario.</td></tr><tr><td>**clase\_inmueble\_id**</td><td>Identificador de la clase de inmueble a la que está asociada esta característica. Corresponde al `id` devuelto por el servicio **Listar Clases de Inmueble**.</td></tr><tr><td>**clase\_inmueble**</td><td>Nombre descriptivo de la clase de inmueble (por ejemplo: "Amoblados", "Casa", "Bodega").</td></tr></tbody></table>

#### **4. Seguridad y Posibles Errores**

<p class="callout danger">**¡Tu pase tiene fecha de caducidad!**</p>

Por medidas de seguridad, el `token` que te entregamos **solo dura 1 hora**. Una vez transcurrido ese tiempo, el pase expirará y el sistema te bloqueará el acceso devolviéndote un error `401`. Cuando esto ocurra, tu sistema simplemente debe volver a consumir el servicio de [Login](https://docs.nuby.ai/books/api-nuby-v2/page/login) para pedir un pase nuevo y continuar trabajando.

Así se ve el error que te devolverá el sistema cuando tu token se haya vencido o intentes usar un pase inválido:

```json
{
    "statusCode": 401,
    "error": {
        "type": "SERVER_ERROR",
        "description": "JWT Token expired."
    }
}
```

Otros posibles errores:

<table border="1" id="bkmrk-c%C3%B3digo-http-descripc" style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 20%;"></col><col style="width: 80%;"></col></colgroup><thead><tr><th>Código HTTP</th><th>Descripción</th></tr></thead><tbody><tr><td>**400**</td><td>Token no enviado o con formato incorrecto. Asegúrate de incluir el encabezado `Authorization: Bearer TU_TOKEN`.</td></tr><tr><td>**401**</td><td>Token expirado o inválido. Solicita uno nuevo a través del servicio de Login.</td></tr><tr><td>**403**</td><td>El cliente OAuth no tiene el scope necesario para esta operación. Para endpoints GET se requiere el scope `read`. Mensaje: `"Insufficient scope. Required: 'read', granted: '{scope_actual}'."`</td></tr></tbody></table>

---

#### **5. Endpoint relacionado: Filtrar por Clase de Inmueble**

Si necesitas obtener únicamente las características de una clase de inmueble específica, puedes usar el siguiente endpoint en lugar de filtrar la respuesta completa:

```http
GET https://{{instancia}}/service/v2/public/masters/properties/features/property-class/{id}
```

Donde `{id}` es el identificador numérico de la clase de inmueble (obtenido del servicio **Listar Clases de Inmueble**). La respuesta tiene exactamente la misma estructura que este endpoint, pero filtrada a la clase indicada.

Si el parámetro `{id}` está vacío o no es numérico, el sistema devolverá un error `400`:

```json
{
    "error": "El ID de la clase del inmueble no puede estar vacío y debe ser de tipo numérico"
}
```

---

#### **6. Ejemplos de integración**

Aquí tienes ejemplos de código listos para que tus desarrolladores los adapten a tu plataforma:

<details id="bkmrk-curl-%23-listar-todas-"><summary>cURL</summary>

```bash
# Listar todas las características
curl -X GET "https://{{instancia}}/service/v2/public/masters/properties/features" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer TU_TOKEN_AQUI"

# Listar características de una clase de inmueble específica (ej. ID 1249 = Casa)
curl -X GET "https://{{instancia}}/service/v2/public/masters/properties/features/property-class/1249" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer TU_TOKEN_AQUI"
```

</details><details id="bkmrk-php-%3C%3Fphp-%24instance-"><summary>PHP</summary>

```php
<?php

$instance = 'tu_instancia'; // Reemplaza con tu instancia real
$token = 'TU_TOKEN_AQUI'; // Token obtenido del servicio de Login

// Para todas las características:
$url = "https://{$instance}/service/v2/public/masters/properties/features";

// Para filtrar por clase de inmueble (descomentar y reemplazar el ID):
// $claseInmuebleId = 1249; // Ejemplo: Casa
// $url = "https://{$instance}/service/v2/public/masters/properties/features/property-class/{$claseInmuebleId}";

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Content-Type: application/json',
    'Authorization: Bearer ' . $token
]);

$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);

if (curl_errno($ch)) {
    echo 'Error: ' . curl_error($ch);
} else {
    echo "Código de estado HTTP: " . $http_code . "\n";

    if ($http_code === 200) {
        $caracteristicas = json_decode($response, true);
        echo "Características de propiedades:\n";
        foreach ($caracteristicas as $car) {
            echo "  [{$car['clase_inmueble']}] {$car['descripcion']} (tipo: {$car['tipo_campo']})\n";
        }
    } else {
        echo "Error al consultar las características.\n";
        echo $response . "\n";
    }
}
curl_close($ch);

?>
```

</details><details id="bkmrk-python-import-reques"><summary>Python</summary>

```python
import requests

# 1. Configura tus datos de acceso
instancia = 'mi-inmobiliaria.nuby.app' # Reemplaza con tu dirección web completa
token = 'TU_TOKEN_AQUI' # Token obtenido del servicio de Login

# 2. Prepara la dirección y los encabezados
# Para todas las características:
url = f"https://{instancia}/service/v2/public/masters/properties/features"

# Para filtrar por clase de inmueble (descomentar y reemplazar el ID):
# clase_inmueble_id = 1249  # Ejemplo: Casa
# url = f"https://{instancia}/service/v2/public/masters/properties/features/property-class/{clase_inmueble_id}"

headers = {
    "Content-Type": "application/json",
    "Authorization": f"Bearer {token}"
}

# 3. Envía la petición GET y procesa la respuesta
try:
    response = requests.get(url, headers=headers)

    print(f"Código de estado HTTP: {response.status_code}")

    if response.status_code == 200:
        caracteristicas = response.json()
        print("Características de propiedades:")
        for car in caracteristicas:
            print(f"  [{car['clase_inmueble']}] {car['descripcion']} (tipo: {car['tipo_campo']})")
    else:
        print("Error al consultar las características.")
        print(f"Detalle del error: {response.text}")

except Exception as e:
    print(f"Ocurrió un error de conexión: {e}")

```

</details><details id="bkmrk-javascript-%2F%2F-1.-con"><summary>JavaScript</summary>

```javascript
// 1. Configura tus datos de acceso
const instancia = 'mi-inmobiliaria.nuby.app'; // Reemplaza con tu dirección web completa
const token = 'TU_TOKEN_AQUI'; // Token obtenido del servicio de Login

// 2. Prepara la dirección
// Para todas las características:
const url = `https://${instancia}/service/v2/public/masters/properties/features`;

// Para filtrar por clase de inmueble (descomentar y reemplazar el ID):
// const claseInmuebleId = 1249; // Ejemplo: Casa
// const url = `https://${instancia}/service/v2/public/masters/properties/features/property-class/${claseInmuebleId}`;

// 3. Función para consultar las características
async function consultarCaracteristicas() {
    try {
        const response = await fetch(url, {
            method: 'GET',
            headers: {
                'Content-Type': 'application/json',
                'Authorization': `Bearer ${token}`
            }
        });

        console.log(`Código de estado HTTP: ${response.status}`);

        if (response.ok) {
            const caracteristicas = await response.json();
            console.log('Características de propiedades:');
            caracteristicas.forEach(car => {
                console.log(`  [${car.clase_inmueble}] ${car.descripcion} (tipo: ${car.tipo_campo})`);
            });
        } else {
            console.log('Error al consultar las características.');
            const errorData = await response.text();
            console.log(`Detalle del error: ${errorData}`);
        }
    } catch (error) {
        console.error(`Ocurrió un error de conexión: ${error}`);
    }
}

// 4. Ejecutamos la función
consultarCaracteristicas();

```

</details><details id="bkmrk-power-query-m-%28excel"><summary>Power Query M (Excel / Power BI)</summary>

```powerquery
let
    // 1. Configura tus datos de acceso
    instancia = "mi-inmobiliaria.nuby.app", // Reemplaza con tu dirección web completa
    token = "TU_TOKEN_AQUI", // Token obtenido del servicio de Login

    // 2. Prepara la dirección de la petición
    url = "https://" & instancia & "/service/v2/public/masters/properties/features",

    // 3. Envía la petición GET con el token de autenticación
    response = Web.Contents(url, [
        Headers = [
            #"Content-Type" = "application/json",
            #"Authorization" = "Bearer " & token
        ]
    ]),

    // 4. Decodifica la respuesta JSON y conviértela en tabla
    jsonResponse = Json.Document(response),
    tabla = Table.FromList(jsonResponse, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
    expandido = Table.ExpandRecordColumn(tabla, "Column1",
        {"id", "descripcion", "tipo_campo", "opciones_valores", "opciones_descripciones", "orden", "grupo", "clase_inmueble_id", "clase_inmueble"},
        {"ID", "Descripcion", "TipoCampo", "OpcionesValores", "OpcionesDescripciones", "Orden", "Grupo", "ClaseInmuebleID", "ClaseInmueble"})
in
    expandido
```

</details>

# Propiedades / Listar Características por Clase de Inmueble

Permite obtener la lista de características que puede tener una propiedad, filtrada por una clase de inmueble específica. Cada elemento de la respuesta contiene la información detallada de una característica perteneciente a la clase indicada. Este servicio es ideal cuando ya conoces la clase de inmueble y solo necesitas las características aplicables a ese tipo.

<p class="callout info">**¿Para qué sirve este servicio?**  
Úsalo cuando necesites construir un formulario dinámico para un tipo de inmueble en particular (por ejemplo, solo las características de "Casa" o de "Apartamento"). Si prefieres obtener todas las características de todas las clases de una sola vez, utiliza el endpoint de [**Listar Características**](https://docs.nuby.ai/books/api-nuby-v2/page/listar-caracteristicas). Para conocer los identificadores válidos de clases de inmueble, consulta el servicio de [**Listar Clases de Inmueble**](https://docs.nuby.ai/books/api-nuby-v2/page/listar-clases-de-inmueble).</p>

---

#### **1. El Endpoint (La dirección web)**

Apunta tu sistema a la siguiente dirección. Recuerda reemplazar <span style="color: rgb(241, 196, 15);">**{{instancia}}**</span> por la dirección web completa que utilizas para ingresar a tu plataforma, y <span style="color: rgb(241, 196, 15);">**{{id}}**</span> por el identificador numérico de la clase de inmueble que deseas consultar.

```http
GET https://{{instancia}}/service/v2/public/masters/properties/features/property-class/{{id}}
```

<p class="callout info">**¿Qué debes colocar en {{instancia}}?**  
Es muy sencillo: corresponde a la **dirección web principal** que utilizas a diario para ingresar a tu plataforma (incluyendo la terminación `.nuby.app` o `.arrendasoft.co`).  
Por ejemplo, si para entrar a tu sistema escribes `inmobiliaria.nuby.app` o `inmobiliaria.arrendasoft.co` en tu navegador, esa será exactamente tu instancia. Solo asegúrate de no incluir el "https://" ni barras diagonales ("/") al final.</p>

#### **2. La Petición (¿Qué debes enviarnos?)**

Este servicio no requiere cuerpo en la petición. Solo necesitas enviar los encabezados correctos y el parámetro de ruta:

<table border="1" id="bkmrk-m%C3%A9todo-get-content-t" style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 20%;"></col><col style="width: 80%;"></col></colgroup><tbody><tr><td>**Método**</td><td>GET</td></tr><tr><td>**Content-Type**</td><td>application/json</td></tr><tr><td>**Authorization**</td><td>**Bearer token**, Token obtenido al consumir el servicio [Login](https://docs.nuby.ai/books/api-nuby-v2/page/login "Login")</td></tr></tbody></table>

**Parámetro de ruta:**

<table border="1" id="bkmrk-par%C3%A1metro-tipo-reque" style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 20%;"></col><col style="width: 15%;"></col><col style="width: 15%;"></col><col style="width: 50%;"></col></colgroup><thead><tr><th>Parámetro</th><th>Tipo</th><th>Requerido</th><th>Descripción</th></tr></thead><tbody><tr><td>**id**</td><td>Numérico</td><td>Sí</td><td>Identificador único de la clase de inmueble. Puedes obtener los valores válidos consultando el servicio de [**Listar Clases de Inmueble**](https://docs.nuby.ai/books/api-nuby-v2/page/listar-clases-de-inmueble).</td></tr></tbody></table>

<p class="callout warning">**¿Aún no tienes tu Token de acceso?**  
Para consumir este servicio necesitas un Token vigente. Consulta el servicio de [Login](https://docs.nuby.ai/books/api-nuby-v2/page/login) para aprender cómo obtenerlo.</p>

#### **3. La Respuesta (¿Qué te entregaremos?)**

Si tu Token es válido y el `id` de la clase de inmueble es correcto, el sistema te devolverá una lista con las características asociadas a esa clase. Por ejemplo, para la clase "Casa" (`id = 1249`), la respuesta se verá similar a esta:

```json
[
    {
        "id": "1",
        "descripcion": "Nº De Habitaciones",
        "tipo_campo": "numeric",
        "opciones_valores": null,
        "opciones_descripciones": null,
        "orden": "1",
        "grupo": "Características del Inmueble",
        "clase_inmueble_id": "1249",
        "clase_inmueble": "Casa"
    },
    {
        "id": "31",
        "descripcion": "Red de gas",
        "tipo_campo": "select",
        "opciones_valores": "si,no",
        "opciones_descripciones": "Si,No",
        "orden": "5",
        "grupo": "Características del Inmueble",
        "clase_inmueble_id": "1249",
        "clase_inmueble": "Casa"
    },
    {
        "id": "22",
        "descripcion": "Balcón",
        "tipo_campo": "checkbox",
        "opciones_valores": null,
        "opciones_descripciones": null,
        "orden": "10",
        "grupo": "Características del Inmueble",
        "clase_inmueble_id": "1249",
        "clase_inmueble": "Casa"
    },
    {
        "id": "38",
        "descripcion": "Parqueadero",
        "tipo_campo": "select",
        "opciones_valores": "propio,visitantes",
        "opciones_descripciones": "Propio,Visitantes",
        "orden": "12",
        "grupo": "Características del Inmueble",
        "clase_inmueble_id": "1249",
        "clase_inmueble": "Casa"
    }
]
```

<p class="callout info">**Nota:** Las características disponibles y sus grupos dependen de la configuración de cada instancia. La lista se devuelve ordenada por grupo, luego por orden dentro del grupo, y finalmente por descripción alfabéticamente. La estructura de la respuesta es idéntica a la del servicio de **Listar Características**, pero filtrada a la clase de inmueble indicada.</p>

Tabla con la descripción de cada campo del JSON:

<table border="1" id="bkmrk-clave-descripci%C3%B3n-id" style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 20%;"></col><col style="width: 80%;"></col></colgroup><thead><tr><th>Clave</th><th>Descripción</th></tr></thead><tbody><tr><td>**id**</td><td>Identificador único de la característica (tipo texto).</td></tr><tr><td>**descripcion**</td><td>Nombre descriptivo de la característica (por ejemplo: "Nº De Habitaciones", "Parqueadero").</td></tr><tr><td>**tipo\_campo**</td><td>Tipo de campo que define cómo se captura la información. Valores posibles: `numeric` (campo numérico), `checkbox` (casilla de verificación), `select` (lista desplegable con opciones predefinidas), entre otros.</td></tr><tr><td>**opciones\_valores**</td><td>Valores técnicos de las opciones disponibles, separados por coma. Aplica únicamente cuando `tipo_campo` es `select`. Será `null` o vacío para otros tipos de campo.</td></tr><tr><td>**opciones\_descripciones**</td><td>Descripciones legibles de las opciones disponibles, separadas por coma. Cada descripción corresponde posicionalmente al valor en `opciones_valores`. Por ejemplo, si `opciones_valores` es `"propio,visitantes"`, las descripciones serán `"Propio,Visitantes"`.</td></tr><tr><td>**orden**</td><td>Posición numérica que indica el orden de presentación de la característica dentro de su grupo.</td></tr><tr><td>**grupo**</td><td>Nombre del grupo al que pertenece la característica (por ejemplo: "Características del Inmueble"). Permite agrupar visualmente las características en un formulario.</td></tr><tr><td>**clase\_inmueble\_id**</td><td>Identificador de la clase de inmueble a la que está asociada esta característica. Coincidirá con el `id` enviado en la URL.</td></tr><tr><td>**clase\_inmueble**</td><td>Nombre descriptivo de la clase de inmueble (por ejemplo: "Casa", "Apartamento", "Bodega").</td></tr></tbody></table>

#### **4. Seguridad y Posibles Errores**

<p class="callout danger">**¡Tu pase tiene fecha de caducidad!**</p>

Por medidas de seguridad, el `token` que te entregamos **solo dura 1 hora**. Una vez transcurrido ese tiempo, el pase expirará y el sistema te bloqueará el acceso devolviéndote un error `401`. Cuando esto ocurra, tu sistema simplemente debe volver a consumir el servicio de [Login](https://docs.nuby.ai/books/api-nuby-v2/page/login) para pedir un pase nuevo y continuar trabajando.

Así se ve el error que te devolverá el sistema cuando tu token se haya vencido o intentes usar un pase inválido:

```json
{
    "statusCode": 401,
    "error": {
        "type": "SERVER_ERROR",
        "description": "JWT Token expired."
    }
}
```

Si envías un `id` vacío o no numérico, el sistema te devolverá un error de validación:

```json
{
    "error": "El ID de la clase del inmueble no puede estar vacío y debe ser de tipo numérico"
}
```

Otros posibles errores:

<table border="1" id="bkmrk-c%C3%B3digo-http-descripc" style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 20%;"></col><col style="width: 80%;"></col></colgroup><thead><tr><th>Código HTTP</th><th>Descripción</th></tr></thead><tbody><tr><td>**400**</td><td>Token no enviado, formato incorrecto, o el parámetro `id` está vacío o no es numérico.</td></tr><tr><td>**401**</td><td>Token expirado o inválido. Solicita uno nuevo a través del servicio de Login.</td></tr><tr><td>**403**</td><td>El cliente OAuth no tiene el scope necesario para esta operación. Para endpoints GET se requiere el scope `read`. Mensaje: `"Insufficient scope. Required: 'read', granted: '{scope_actual}'."`</td></tr></tbody></table>

---

#### **5. Ejemplos de integración**

Aquí tienes ejemplos de código listos para que tus desarrolladores los adapten a tu plataforma. En estos ejemplos se consulta la clase "Casa" con `id = 1249`:

<details id="bkmrk-curl-curl--x-get-%22ht"><summary>cURL</summary>

```bash
curl -X GET "https://{{instancia}}/service/v2/public/masters/properties/features/property-class/1249" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer TU_TOKEN_AQUI"
```

</details><details id="bkmrk-php-%3C%3Fphp-%24instance-"><summary>PHP</summary>

```php
<?php

$instance = 'tu_instancia'; // Reemplaza con tu instancia real
$token = 'TU_TOKEN_AQUI'; // Token obtenido del servicio de Login
$claseInmuebleId = 1249; // ID de la clase de inmueble (ej. Casa)

$url = "https://{$instance}/service/v2/public/masters/properties/features/property-class/{$claseInmuebleId}";

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Content-Type: application/json',
    'Authorization: Bearer ' . $token
]);

$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);

if (curl_errno($ch)) {
    echo 'Error: ' . curl_error($ch);
} else {
    echo "Código de estado HTTP: " . $http_code . "\n";

    if ($http_code === 200) {
        $caracteristicas = json_decode($response, true);
        echo "Características de la clase de inmueble (ID {$claseInmuebleId}):\n";
        foreach ($caracteristicas as $car) {
            echo "  {$car['descripcion']} (tipo: {$car['tipo_campo']})\n";
        }
    } else {
        echo "Error al consultar las características.\n";
        echo $response . "\n";
    }
}
curl_close($ch);

?>
```

</details><details id="bkmrk-python-import-reques"><summary>Python</summary>

```python
import requests

# 1. Configura tus datos de acceso
instancia = 'mi-inmobiliaria.nuby.app' # Reemplaza con tu dirección web completa
token = 'TU_TOKEN_AQUI' # Token obtenido del servicio de Login
clase_inmueble_id = 1249 # ID de la clase de inmueble (ej. Casa)

# 2. Prepara la dirección y los encabezados
url = f"https://{instancia}/service/v2/public/masters/properties/features/property-class/{clase_inmueble_id}"

headers = {
    "Content-Type": "application/json",
    "Authorization": f"Bearer {token}"
}

# 3. Envía la petición GET y procesa la respuesta
try:
    response = requests.get(url, headers=headers)

    print(f"Código de estado HTTP: {response.status_code}")

    if response.status_code == 200:
        caracteristicas = response.json()
        print(f"Características de la clase de inmueble (ID {clase_inmueble_id}):")
        for car in caracteristicas:
            print(f"  {car['descripcion']} (tipo: {car['tipo_campo']})")
    else:
        print("Error al consultar las características.")
        print(f"Detalle del error: {response.text}")

except Exception as e:
    print(f"Ocurrió un error de conexión: {e}")

```

</details><details id="bkmrk-javascript-%2F%2F-1.-con"><summary>JavaScript</summary>

```javascript
// 1. Configura tus datos de acceso
const instancia = 'mi-inmobiliaria.nuby.app'; // Reemplaza con tu dirección web completa
const token = 'TU_TOKEN_AQUI'; // Token obtenido del servicio de Login
const claseInmuebleId = 1249; // ID de la clase de inmueble (ej. Casa)

// 2. Prepara la dirección
const url = `https://${instancia}/service/v2/public/masters/properties/features/property-class/${claseInmuebleId}`;

// 3. Función para consultar las características por clase de inmueble
async function consultarCaracteristicasPorClase() {
    try {
        const response = await fetch(url, {
            method: 'GET',
            headers: {
                'Content-Type': 'application/json',
                'Authorization': `Bearer ${token}`
            }
        });

        console.log(`Código de estado HTTP: ${response.status}`);

        if (response.ok) {
            const caracteristicas = await response.json();
            console.log(`Características de la clase de inmueble (ID ${claseInmuebleId}):`);
            caracteristicas.forEach(car => {
                console.log(`  ${car.descripcion} (tipo: ${car.tipo_campo})`);
            });
        } else {
            console.log('Error al consultar las características.');
            const errorData = await response.text();
            console.log(`Detalle del error: ${errorData}`);
        }
    } catch (error) {
        console.error(`Ocurrió un error de conexión: ${error}`);
    }
}

// 4. Ejecutamos la función
consultarCaracteristicasPorClase();

```

</details><details id="bkmrk-power-query-m-%28excel"><summary>Power Query M (Excel / Power BI)</summary>

```powerquery
let
    // 1. Configura tus datos de acceso
    instancia = "mi-inmobiliaria.nuby.app", // Reemplaza con tu dirección web completa
    token = "TU_TOKEN_AQUI", // Token obtenido del servicio de Login
    claseInmuebleId = "1249", // ID de la clase de inmueble (ej. Casa)

    // 2. Prepara la dirección de la petición
    url = "https://" & instancia & "/service/v2/public/masters/properties/features/property-class/" & claseInmuebleId,

    // 3. Envía la petición GET con el token de autenticación
    response = Web.Contents(url, [
        Headers = [
            #"Content-Type" = "application/json",
            #"Authorization" = "Bearer " & token
        ]
    ]),

    // 4. Decodifica la respuesta JSON y conviértela en tabla
    jsonResponse = Json.Document(response),
    tabla = Table.FromList(jsonResponse, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
    expandido = Table.ExpandRecordColumn(tabla, "Column1",
        {"id", "descripcion", "tipo_campo", "opciones_valores", "opciones_descripciones", "orden", "grupo", "clase_inmueble_id", "clase_inmueble"},
        {"ID", "Descripcion", "TipoCampo", "OpcionesValores", "OpcionesDescripciones", "Orden", "Grupo", "ClaseInmuebleID", "ClaseInmueble"})
in
    expandido
```

</details>