API nuby V2

Aquí encontrarás el catálogo detallado de todos los servicios que nuestra plataforma tiene disponibles para ti.

Para que quede súper claro, piensa en esta sección como si fuera el menú de un restaurante o un directorio muy bien organizado. Aquí te vamos a mostrar qué opciones tienes disponibles y cómo pedirnos la información.

En el mundo de la tecnología, a estas opciones las llamamos endpoints (puntos de conexión a los que te diriges para pedir algo específico). A lo largo de este documento te explicaremos:

Con este directorio a la mano, tú o tu equipo técnico sabrán exactamente cómo comunicarse con el sistema, permitiendo que tus plataformas externas se integren a la perfección con el ecosistema (al que llamamos "instancia") de tu inmobiliaria en nuby.

¡Explora nuestro directorio y descubre toda la información que puedes consultar y gestionar!

Autenticación

Bienvenido al filtro de seguridad de nuestra API. Antes de consultar o enviar información, necesitamos validar que tu conexión tenga los permisos necesarios para proteger tus datos en todo momento.

¿Cómo funciona el acceso? Piensa en esta sección como la recepción de un edificio privado. Aquí te explicamos cómo tu aplicación debe "identificarse" para obtener un token (tu llave de acceso temporal).

Reglas clave de tu token de acceso:

¡Explora cómo generar tu primera llave para comenzar a integrarte de forma segura!

Autenticación

Login

Antes de que tus sistemas puedan comunicarse con nuestra API, necesitan identificarse. Este servicio es como la recepción de nuestro edificio digital: aquí entregas tus credenciales y, a cambio, recibes un "pase de invitado" temporal (llamado Token). Necesitarás presentar este pase para que el sistema te permita acceder a cualquier otra sección (como contratos, facturas o propiedades).

¿Aún no tienes tus credenciales de acceso?
Para usar este servicio, primero necesitas un usuario y contraseña especiales para tu aplicación. Descubre cómo crear un nuevo cliente OAuth2 en nuby para consumo de la API paso a paso aquí.


1. El Endpoint (La dirección web)

Apunta tu sistema a la siguiente dirección. Recuerda reemplazar {{instancia}} por la dirección web completa que utilizas para ingresar a tu plataforma.

POST https://{{instancia}}/service/v2/public/auth/login

¿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.

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

Tu sistema debe enviarnos un paquete de datos en formato JSON indicando que el contenido es application/json. El cuerpo de tu petición debe verse así:

{
    "username": "TU_CLIENT_ID",
    "password": "TU_SECRET_KEY"
}
username Es el ID del Cliente (OAuth2) que generaste previamente en el sistema.
password Es la Clave Secreta (Secret Key / OAuth2) vinculada a tu usuario.

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

Si tus credenciales son correctas, el sistema te dará la bienvenida entregándote tu pase de acceso (Token). La respuesta se verá similar a esta:

{
  "message": null,
  "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
  "expiration": 1690540790
}
token Tu llave de acceso. A partir de ahora, en todas tus siguientes consultas a nuestra plataforma, deberás incluir este código en los encabezados (Headers) de tu petición usando el formato: Authorization: Bearer TU_TOKEN_AQUI
expiration La fecha y hora exacta (en formato timestamp) en la que este pase dejará de funcionar.
message Mensaje de confirmación o texto explicativo (en caso de presentarse alguna novedad).

4. Seguridad y Posibles Errores

¡Tu pase tiene fecha de caducidad!

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 Unauthorized. Cuando esto ocurra, tu sistema simplemente debe volver a consumir este servicio de 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:

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

5. Ejemplos de integración

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

cURL
curl -X POST "https://{{instancia}}/service/v2/public/auth/login" \
-H "Content-Type: application/json" \
-d '{
  "username": "TU_CLIENT_ID", 
  "password": "TU_SECRET_KEY"
}'
PHP
<?php

$instance = 'tu_instancia'; // Reemplaza con tu instancia real
$username = 'TU_CLIENT_ID'; // Reemplaza con el ID de cliente proporcionado
$password = 'TU_SECRET_KEY'; // Reemplaza con la clave secreta proporcionada

$url = "https://{$instance}/service/v2/public/auth/login";

$data = json_encode([
    'username' => $username,
    'password' => $password
]);

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Content-Type: application/json',
    'Content-Length: ' . strlen($data)
]);

$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";
    $responseData = json_decode($response, true);
    
    if (isset($responseData['token'])) {
        echo "¡Éxito! Tu Token de Autenticación es: " . $responseData['token'] . "\n";
    } else {
        echo "Autenticación fallida.\n";
    }
}
curl_close($ch);

?>
Python
import requests

# 1. Configura tus datos de acceso
instancia = 'mi-inmobiliaria.nuby.app' # Reemplaza con tu dirección web completa
username = 'TU_CLIENT_ID' # Reemplaza con el ID de cliente proporcionado
password = 'TU_SECRET_KEY' # Reemplaza con la clave secreta proporcionada

# 2. Prepara la dirección y los datos a enviar
url = f"https://{instancia}/service/v2/public/auth/login"

headers = {
    "Content-Type": "application/json"
}

payload = {
    "username": username,
    "password": password
}

# 3. Envía la petición a la plataforma y procesa la respuesta
try:
    # Enviamos la petición POST (la librería convierte automáticamente el payload a JSON)
    response = requests.post(url, json=payload, headers=headers)
    
    print(f"Código de estado HTTP: {response.status_code}")
    
    # Si la petición es exitosa (código 200 OK)
    if response.status_code == 200:
        data = response.json()
        token = data.get("token")
        print(f"¡Éxito! Tu Token de Autenticación es: {token}")
    else:
        print("Autenticación fallida.")
        print(f"Detalle del error: {response.text}")

except Exception as e:
    print(f"Ocurrió un error de conexión: {e}")
JavaScript
// 1. Configura tus datos de acceso
const instancia = 'mi-inmobiliaria.nuby.app'; // Reemplaza con tu dirección web completa
const username = 'TU_CLIENT_ID'; // Reemplaza con el ID de cliente proporcionado
const password = 'TU_SECRET_KEY'; // Reemplaza con la clave secreta proporcionada

// 2. Prepara la dirección y los datos a enviar
const url = `https://${instancia}/service/v2/public/auth/login`;

const data = {
    username: username,
    password: password
};

// 3. Función para enviar la petición a la plataforma
async function realizarLogin() {
    try {
        // Configuramos y enviamos la petición POST
        const response = await fetch(url, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify(data) // Convertimos los datos a formato JSON
        });
        
        console.log(`Código de estado HTTP: ${response.status}`);
        
        // Si la petición es exitosa (códigos 200-299)
        if (response.ok) {
            const responseData = await response.json();
            console.log(`¡Éxito! Tu Token de Autenticación es: ${responseData.token}`);
        } else {
            console.log("Autenticación fallida.");
            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
realizarLogin();
Power Query M (Excel / Power BI)
let
    // 1. Configura tus datos de acceso
    instancia = "mi-inmobiliaria.nuby.app", // Reemplaza con tu dirección web completa
    username = "TU_CLIENT_ID", // Reemplaza con el ID de cliente proporcionado
    password = "TU_SECRET_KEY", // Reemplaza con la clave secreta proporcionada

    // 2. Prepara la dirección y el cuerpo de la petición (en formato JSON)
    url = "https://" & instancia & "/service/v2/public/auth/login",
    
    body = Json.FromValue([
        username = username,
        password = password
    ]),

    // 3. Envía la petición POST a la plataforma
    response = Web.Contents(url, [
        Headers = [#"Content-Type"="application/json"],
        Content = body
    ]),

    // 4. Decodifica la respuesta JSON y extrae el token
    jsonResponse = Json.Document(response),
    token = jsonResponse[token]
in
    token

Maestras

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

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

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

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

Maestras

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.

¿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.


1. El Endpoint (La dirección web)

Apunta tu sistema a la siguiente dirección. Recuerda reemplazar {{instancia}} por la dirección web completa que utilizas para ingresar a tu plataforma.

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

¿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.

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

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

Método GET
Content-Type application/json
Authorization Bearer token, Token obtenido al consumir el servicio Login

¿Aún no tienes tu Token de acceso?
Para consumir este servicio necesitas un Token vigente. Consulta el servicio de Login para aprender cómo obtenerlo.

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í:

[
    {
        "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:

Clave Descripción
id 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.
estado Nombre descriptivo del estado en texto legible (por ejemplo: "Activa", "Arrendada").

4. Seguridad y Posibles Errores

¡Tu pase tiene fecha de caducidad!

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 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:

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

Otros posibles errores:

Código HTTP Descripción
400 Token no enviado o con formato incorrecto. Asegúrate de incluir el encabezado Authorization: Bearer TU_TOKEN.
401 Token expirado o inválido. Solicita uno nuevo a través del servicio de Login.
403 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}'."

5. Ejemplos de integración

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

cURL
curl -X GET "https://{{instancia}}/service/v2/public/masters/properties/states" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer TU_TOKEN_AQUI"
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);

?>
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}")
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();
Power Query M (Excel / Power BI)
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
Maestras

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.

¿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.


1. El Endpoint (La dirección web)

Apunta tu sistema a la siguiente dirección. Recuerda reemplazar {{instancia}} por la dirección web completa que utilizas para ingresar a tu plataforma.

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

¿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.

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

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

Método GET
Content-Type application/json
Authorization Bearer token, Token obtenido al consumir el servicio Login

¿Aún no tienes tu Token de acceso?
Para consumir este servicio necesitas un Token vigente. Consulta el servicio de Login para aprender cómo obtenerlo.

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:

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

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.

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

Clave Descripción
id 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.
clase Nombre descriptivo de la clase de inmueble (por ejemplo: "Apartamento", "Casa", "Bodega").

4. Seguridad y Posibles Errores

¡Tu pase tiene fecha de caducidad!

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 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:

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

Otros posibles errores:

Código HTTP Descripción
400 Token no enviado o con formato incorrecto. Asegúrate de incluir el encabezado Authorization: Bearer TU_TOKEN.
401 Token expirado o inválido. Solicita uno nuevo a través del servicio de Login.
403 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}'."

5. Ejemplos de integración

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

cURL
curl -X GET "https://{{instancia}}/service/v2/public/masters/properties/property-classes" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer TU_TOKEN_AQUI"
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);

?>
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}")
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();
Power Query M (Excel / Power BI)
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
Maestras

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.

¿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.


1. El Endpoint (La dirección web)

Apunta tu sistema a la siguiente dirección. Recuerda reemplazar {{instancia}} por la dirección web completa que utilizas para ingresar a tu plataforma.

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

¿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.

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

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

Método GET
Content-Type application/json
Authorization Bearer token, Token obtenido al consumir el servicio Login

¿Aún no tienes tu Token de acceso?
Para consumir este servicio necesitas un Token vigente. Consulta el servicio de Login para aprender cómo obtenerlo.

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:

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

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.

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

Clave Descripción
id 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.
servicio Nombre descriptivo del tipo de servicio (por ejemplo: "Arriendo", "Venta", "Venta y Arriendo").

4. Seguridad y Posibles Errores

¡Tu pase tiene fecha de caducidad!

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 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:

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

Otros posibles errores:

Código HTTP Descripción
400 Token no enviado o con formato incorrecto. Asegúrate de incluir el encabezado Authorization: Bearer TU_TOKEN.
401 Token expirado o inválido. Solicita uno nuevo a través del servicio de Login.
403 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}'."

5. Ejemplos de integración

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

cURL
curl -X GET "https://{{instancia}}/service/v2/public/masters/properties/service-types" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer TU_TOKEN_AQUI"
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);

?>
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}")
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();
Power Query M (Excel / Power BI)
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
Maestras

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.

¿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.


1. El Endpoint (La dirección web)

Apunta tu sistema a la siguiente dirección. Recuerda reemplazar {{instancia}} por la dirección web completa que utilizas para ingresar a tu plataforma.

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

¿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.

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

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

Método GET
Content-Type application/json
Authorization Bearer token, Token obtenido al consumir el servicio Login

¿Aún no tienes tu Token de acceso?
Para consumir este servicio necesitas un Token vigente. Consulta el servicio de Login para aprender cómo obtenerlo.

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:

[
    {
        "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"
    }
]

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.

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

Clave Descripción
id Identificador único de la característica (tipo texto).
descripcion Nombre descriptivo de la característica (por ejemplo: "Nº De Habitaciones", "Parqueadero").
tipo_campo 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.
opciones_valores 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.
opciones_descripciones 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".
orden Posición numérica que indica el orden de presentación de la característica dentro de su grupo.
grupo Nombre del grupo al que pertenece la característica (por ejemplo: "Características del Inmueble"). Permite agrupar visualmente las características en un formulario.
clase_inmueble_id 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.
clase_inmueble Nombre descriptivo de la clase de inmueble (por ejemplo: "Amoblados", "Casa", "Bodega").

4. Seguridad y Posibles Errores

¡Tu pase tiene fecha de caducidad!

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 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:

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

Otros posibles errores:

Código HTTP Descripción
400 Token no enviado o con formato incorrecto. Asegúrate de incluir el encabezado Authorization: Bearer TU_TOKEN.
401 Token expirado o inválido. Solicita uno nuevo a través del servicio de Login.
403 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}'."

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:

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:

{
    "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:

cURL
# 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"
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);

?>
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}")
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();
Power Query M (Excel / Power BI)
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
Maestras

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.

¿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. Para conocer los identificadores válidos de clases de inmueble, consulta el servicio de Listar Clases de Inmueble.


1. El Endpoint (La dirección web)

Apunta tu sistema a la siguiente dirección. Recuerda reemplazar {{instancia}} por la dirección web completa que utilizas para ingresar a tu plataforma, y {{id}} por el identificador numérico de la clase de inmueble que deseas consultar.

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

¿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.

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:

Método GET
Content-Type application/json
Authorization Bearer token, Token obtenido al consumir el servicio Login

Parámetro de ruta:

Parámetro Tipo Requerido Descripción
id Numérico Identificador único de la clase de inmueble. Puedes obtener los valores válidos consultando el servicio de Listar Clases de Inmueble.

¿Aún no tienes tu Token de acceso?
Para consumir este servicio necesitas un Token vigente. Consulta el servicio de Login para aprender cómo obtenerlo.

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:

[
    {
        "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"
    }
]

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.

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

Clave Descripción
id Identificador único de la característica (tipo texto).
descripcion Nombre descriptivo de la característica (por ejemplo: "Nº De Habitaciones", "Parqueadero").
tipo_campo 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.
opciones_valores 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.
opciones_descripciones 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".
orden Posición numérica que indica el orden de presentación de la característica dentro de su grupo.
grupo Nombre del grupo al que pertenece la característica (por ejemplo: "Características del Inmueble"). Permite agrupar visualmente las características en un formulario.
clase_inmueble_id Identificador de la clase de inmueble a la que está asociada esta característica. Coincidirá con el id enviado en la URL.
clase_inmueble Nombre descriptivo de la clase de inmueble (por ejemplo: "Casa", "Apartamento", "Bodega").

4. Seguridad y Posibles Errores

¡Tu pase tiene fecha de caducidad!

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 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:

{
    "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:

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

Otros posibles errores:

Código HTTP Descripción
400 Token no enviado, formato incorrecto, o el parámetro id está vacío o no es numérico.
401 Token expirado o inválido. Solicita uno nuevo a través del servicio de Login.
403 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}'."

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:

cURL
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"
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);

?>
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}")
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();
Power Query M (Excel / Power BI)
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

Propiedades

Bienvenido al inventario digital de tu inmobiliaria. En esta sección te explicamos cómo conectar tus herramientas externas para gestionar, consultar y mantener sincronizada toda la información de tus inmuebles.

¿Qué puedes hacer en este módulo?

1. Exploración y consulta detallada: Extrae tu catálogo completo utilizando filtros estratégicos (como fechas de creación o actualización) o profundiza en los datos de una propiedad específica. Podrás acceder a sus características precisas, material multimedia (fotografías y videos) y la información de sus propietarios.

2. Gestión segura de estados: ¡No solo puedes leer información, también puedes tomar acción! Mantén tu inventario al día actualizando la disponibilidad de tus inmuebles. Para tu tranquilidad, nuestro sistema cuenta con validaciones inteligentes que protegen tu información y previenen errores accidentales (por ejemplo, bloqueando cambios automáticos si la propiedad ya figura como "Arrendada").

¡Explora las opciones a continuación y sácale el máximo provecho a la gestión automatizada de tu portafolio!

Propiedades

Listar Propiedades

Permite obtener una lista paginada de propiedades registradas en la inmobiliaria, incluyendo información detallada de cada una: datos generales, ubicación, valores económicos, características, propietarios, imágenes, videos y códigos de portales inmobiliarios.

¿Para qué sirve este servicio?
Úsalo para sincronizar el inventario de propiedades con tu sistema externo, alimentar un sitio web, generar reportes o integrar la información de inmuebles con plataformas de terceros. El endpoint soporta paginación y filtros por rangos de fecha para consultas eficientes.


1. El Endpoint (La dirección web)

Apunta tu sistema a la siguiente dirección. Recuerda reemplazar {{instancia}} por la dirección web completa que utilizas para ingresar a tu plataforma.

GET https://{{instancia}}/service/v2/public/properties

¿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.

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

Este servicio requiere autenticación mediante un Token JWT. Envía los encabezados requeridos y opcionalmente los parámetros de filtrado en la URL:

Método GET
Content-Type application/json
Authorization Bearer token, Token obtenido al consumir el servicio Login.

Autenticación requerida
Este servicio requiere un Token de autenticación válido. Debes incluir el encabezado Authorization: Bearer TU_TOKEN en cada petición. El token se obtiene consumiendo el servicio de Login. Adicionalmente, el cliente OAuth debe contar con el scope read para poder consumir este endpoint.

Parámetros de consulta (query string):

Parámetro Tipo Requerido Por defecto Descripción
page integer No 1 Número de página de resultados que se desea recuperar.
limit integer No 10 Número máximo de propiedades por página. Valor máximo permitido: 50.
listing_start_date string No Fecha de inicio del rango de consignación del inmueble.
Formato: YYYY-MM-DD (ejemplo: 2024-03-01).
listing_end_date string No Fecha de fin del rango de consignación del inmueble.
Formato: YYYY-MM-DD.
created_start_date string No Fecha de inicio del rango de creación del inmueble en el sistema.
Formato: YYYY-MM-DD.
created_end_date string No Fecha de fin del rango de creación del inmueble en el sistema.
Formato: YYYY-MM-DD.
last_modified_start_date string No Fecha de inicio del rango de última modificación del inmueble.
Formato: YYYY-MM-DD.
last_modified_end_date string No Fecha de fin del rango de última modificación del inmueble.
Formato: YYYY-MM-DD.

Comportamiento de los filtros de fecha
Para los parámetros de tipo fecha que se componen de un rango (por ejemplo listing_start_date y listing_end_date):
— Si envías solo el start_date: se retornarán registros con fecha mayor o igual (>=) a la indicada.
— Si envías solo el end_date: se retornarán registros con fecha menor o igual (<=) a la indicada.
— Si envías ambos: se retornarán registros dentro de ese rango de fechas (BETWEEN).
— La fecha de inicio no puede ser mayor que la fecha de fin; de lo contrario se devolverá un error de validación.

Ejemplos de peticiones:

GET https://{{instancia}}/service/v2/public/properties
GET https://{{instancia}}/service/v2/public/properties?page=1&limit=10
GET https://{{instancia}}/service/v2/public/properties?page=1&limit=10&listing_start_date=2024-03-26
GET https://{{instancia}}/service/v2/public/properties?page=1&limit=10&listing_start_date=2024-03-01&listing_end_date=2024-03-31
GET https://{{instancia}}/service/v2/public/properties?page=2&limit=20&created_start_date=2024-01-01&created_end_date=2024-06-30

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

El sistema te devolverá una lista con las propiedades que coincidan con los filtros aplicados. Cada propiedad incluye datos generales, ubicación, valores económicos, características, propietarios, imágenes, videos y códigos de portales inmobiliarios. La respuesta se verá similar a esta:

[
    {
        "codigo": "137",
        "titulo": "Apartamento amplio con vista al parque central",
        "clase_id": "1247",
        "clase_inmueble": "Apartamento",
        "tipo_servicio_id": "arriendo",
        "tipo_servicio": "Arriendo",
        "estrato": "1258",
        "estrato_texto": "Cuatro",
        "fecha_consignacion": "2024-04-26",
        "asesor_id": "5",
        "asesor": "María López Ramírez",
        "pais_id": "1",
        "pais": "COLOMBIA",
        "departamento_id": "5",
        "departamento": "Antioquia",
        "municipio_id": "1",
        "municipio": "Medellin",
        "barrio_id": "3",
        "barrio": "Los Rosales",
        "direccion": "CALLE 45 # 32 - 18",
        "coordenadas": "6.24830000000000:-75.56120000000000",
        "valor_arriendo1": "1600000",
        "valor_arriendo2": "0",
        "valor_venta1": "0",
        "valor_venta2": "0",
        "valor_administracion": "0",
        "avaluo_catastral": "0",
        "impuesto_predial": "0.00",
        "area": "75.00",
        "observaciones": null,
        "propiedad_destacada": "No",
        "llaves_en": "oficina",
        "llaves_otro": null,
        "paga_cuota_sost": "propietario",
        "folio_matricula": null,
        "referencia_catastral": null,
        "edificio_unidad": "urbanizacion",
        "estado": "1",
        "estado_texto": "Activa",
        "cantidad_images": "3",
        "cantidad_videos": "1",
        "fecha_creacion": "2024-04-26 10:30:00",
        "ultima_fecha_modificacion": "2024-05-15 14:22:00",
        "caracteristicas": [
            {
                "id": "1",
                "descripcion": "Nº De Habitaciones",
                "tipo_campo": "numeric",
                "orden": "1",
                "grupo": "Características del inmueble",
                "valor": "4"
            },
            {
                "id": "2",
                "descripcion": "Nº De Baños",
                "tipo_campo": "numeric",
                "orden": "2",
                "grupo": "Características del inmueble",
                "valor": "3"
            },
            {
                "id": "31",
                "descripcion": "Red de gas",
                "tipo_campo": "select",
                "orden": "5",
                "grupo": "Características del Inmueble",
                "valor": "si",
                "valor_texto": "Si"
            },
            {
                "id": "14",
                "descripcion": "Cocina Integral",
                "tipo_campo": "checkbox",
                "orden": "5",
                "grupo": "Características Internas",
                "valor": "1"
            }
        ],
        "propietarios": [
            {
                "id": "272",
                "documento": "1020304050",
                "nombres": "ANA MARÍA",
                "apellidos": "PÉREZ RODRÍGUEZ"
            }
        ],
        "imagenes": [
            {
                "posicion": "1",
                "size": "19201080",
                "img": "img/fotos/1920x1080_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6.jpeg",
                "imagen": "https://mi-inmobiliaria.nuby.app/img/fotos/1920x1080_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6.jpeg"
            },
            {
                "posicion": "2",
                "size": "19201080",
                "img": "img/fotos/1920x1080_f6e5d4c3b2a1f6e5d4c3b2a1f6e5d4c3.jpeg",
                "imagen": "https://mi-inmobiliaria.nuby.app/img/fotos/1920x1080_f6e5d4c3b2a1f6e5d4c3b2a1f6e5d4c3.jpeg"
            }
        ],
        "videos": [
            {
                "url": "dQw4w9WgXcQ",
                "tipo": "youtube",
                "descripcion": null,
                "posicion": "1"
            }
        ],
        "codigos_portales": [
            {
                "nombre_portal": "metrocuadrado",
                "id_portal": "MC-12345",
                "tipo_servicio": "arriendo"
            }
        ]
    }
]
Campos principales de la propiedad

Esta tabla enumera las claves presentes en el JSON de cada propiedad y proporciona una descripción de cada una:

Clave Descripción
codigo Código único del inmueble en el sistema.
titulo Título del anuncio del inmueble.
clase_id Identificador de la clase de inmueble. Corresponde al id del servicio Listar Clases de Inmueble.
clase_inmueble Nombre de la clase de inmueble (por ejemplo: "Apartamento", "Casa", "Finca").
tipo_servicio_id Identificador del tipo de servicio. Valores posibles: "arriendo", "venta", "venta y arriendo".
tipo_servicio Nombre descriptivo del tipo de servicio (por ejemplo: "Arriendo", "Venta").
estrato Identificador del estrato socioeconómico del inmueble.
estrato_texto Texto descriptivo del estrato (por ejemplo: "Cuatro", "Tres").
fecha_consignacion Fecha en que el inmueble fue captado/consignado para su gestión. Formato: YYYY-MM-DD.
asesor_id Identificador del asesor asignado al inmueble. Vacío si no tiene asesor asignado.
asesor Nombre completo del asesor asignado.
pais_id Identificador del país donde se ubica el inmueble.
pais Nombre del país.
departamento_id Identificador del departamento/estado/provincia.
departamento Nombre del departamento.
municipio_id Identificador del municipio/ciudad.
municipio Nombre del municipio.
barrio_id Identificador del barrio. Puede ser null si no se ha asignado barrio.
barrio Nombre del barrio.
direccion Dirección física del inmueble.
coordenadas Coordenadas geográficas del inmueble en formato latitud:longitud.
valor_arriendo1 Valor principal de arriendo (canon mensual).
valor_arriendo2 Valor secundario de arriendo. 0 si no aplica.
valor_venta1 Valor principal de venta.
valor_venta2 Valor secundario de venta. 0 si no aplica.
valor_administracion Valor de la cuota de administración.
avaluo_catastral Avalúo catastral del inmueble.
impuesto_predial Valor del impuesto predial.
area Área del inmueble en metros cuadrados.
observaciones Observaciones o descripción adicional del inmueble. Puede ser null.
propiedad_destacada Indica si la propiedad está marcada como destacada. Valores: "Si" o "No".
llaves_en Lugar donde se encuentran las llaves del inmueble (por ejemplo: "oficina").
llaves_otro Ubicación alternativa de las llaves, si aplica. Puede ser null.
paga_cuota_sost Quién paga la cuota de sostenimiento (por ejemplo: "propietario"). Puede ser null.
folio_matricula Número de folio de matrícula inmobiliaria. Puede ser null.
referencia_catastral Referencia catastral del inmueble. Puede ser null.
edificio_unidad Tipo de agrupamiento del inmueble (por ejemplo: "urbanizacion", "edificio", "conjunto").
estado Identificador numérico del estado del inmueble. Valores: 0 (Arrendada), 1 (Activa), 2 (Inactiva), 3 (Vendida).
estado_texto Texto descriptivo del estado (por ejemplo: "Activa", "Arrendada").
cantidad_images Cantidad de imágenes asociadas al inmueble.
cantidad_videos Cantidad de videos asociados al inmueble.
fecha_creacion Fecha y hora de creación del registro en el sistema. Formato: YYYY-MM-DD HH:MM:SS.
ultima_fecha_modificacion Fecha y hora de la última modificación del registro. Formato: YYYY-MM-DD HH:MM:SS.
caracteristicas Lista de características del inmueble (ver tabla detallada abajo).
propietarios Lista de propietarios del inmueble (ver tabla detallada abajo).
imagenes Lista de imágenes del inmueble (ver tabla detallada abajo).
videos Lista de videos del inmueble (ver tabla detallada abajo).
codigos_portales Lista de códigos de publicación en portales inmobiliarios externos (ver tabla detallada abajo).
Características

Cada elemento dentro de la lista caracteristicas contiene la información de una característica del inmueble y su valor asignado:

Clave Descripción
id Identificador de la característica. Corresponde al id del servicio Listar Características.
descripcion Nombre descriptivo de la característica (por ejemplo: "Nº De Habitaciones").
tipo_campo Tipo de campo: numeric, checkbox, select, entre otros.
orden Posición de la característica dentro de su grupo.
grupo Grupo al que pertenece la característica.
valor Valor asignado a la característica para esta propiedad. Para numeric: un número. Para checkbox: "1" (marcado). Para select: el valor técnico de la opción seleccionada.
valor_texto Descripción legible del valor seleccionado. Solo presente cuando tipo_campo es select (por ejemplo: valor "si" → valor_texto "Si").
Propietarios

Cada elemento dentro de la lista propietarios contiene la información de un propietario del inmueble:

Clave Descripción
id Identificador del propietario (tercero) en el sistema.
documento Número de documento de identificación del propietario.
nombres Nombres del propietario.
apellidos Apellidos del propietario.
Imágenes

Cada elemento dentro de la lista imagenes contiene la información de una fotografía del inmueble:

Clave Descripción
posicion Posición de ordenamiento de la imagen (1 = principal).
size Resolución de la imagen (por ejemplo: "19201080").
img Ruta relativa de la imagen en el servidor.
imagen URL completa de la imagen, lista para consumir directamente.
Videos

Cada elemento dentro de la lista videos contiene la información de un video asociado al inmueble:

Clave Descripción
url Identificador o URL del video (por ejemplo, el ID de YouTube: "608AV8w6gL0").
tipo Plataforma del video (por ejemplo: "youtube").
descripcion Descripción del video. Puede ser null.
posicion Posición de ordenamiento del video.
Códigos de Portales

Cada elemento dentro de la lista codigos_portales contiene la información de publicación del inmueble en un portal inmobiliario externo:

Clave Descripción
nombre_portal Nombre del portal inmobiliario (por ejemplo: "metrocuadrado", "fincaraiz").
id_portal Identificador de la propiedad en el portal externo.
tipo_servicio Tipo de servicio bajo el cual fue publicada la propiedad en ese portal.

4. Seguridad y Posibles Errores

El sistema realiza validaciones de autenticación, scopes y parámetros. Si alguna falla, devolverá un error con su respectivo código HTTP:

Código HTTP Descripción
400 Token faltante o inválido. Posibles causas:
— No se envió el encabezado Authorization. Mensaje: "JWT Token required."
— El encabezado no tiene el formato Bearer {token}. Mensaje: "JWT Token not send."
— El token no fue encontrado en el sistema. Mensaje: "JWT Token not found."

Parámetros inválidos. Posibles causas:
page no es numérico.
limit no es numérico o es mayor a 50.
— Las fechas no tienen el formato YYYY-MM-DD.
— La fecha de inicio es mayor que la fecha de fin en un rango.
401 El token ha expirado. Debes generar uno nuevo consumiendo el servicio de Login. Mensaje: "JWT Token expired."
403 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}'."

5. Ejemplos de integración

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

cURL
# Listar propiedades con paginación
curl -X GET "https://{{instancia}}/service/v2/public/properties?page=1&limit=10" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer TU_TOKEN_AQUI"

# Filtrar por rango de fecha de consignación
curl -X GET "https://{{instancia}}/service/v2/public/properties?page=1&limit=10&listing_start_date=2024-03-01&listing_end_date=2024-03-31" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer TU_TOKEN_AQUI"

# Filtrar por fecha de creación
curl -X GET "https://{{instancia}}/service/v2/public/properties?page=1&limit=20&created_start_date=2024-01-01" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer TU_TOKEN_AQUI"
PHP
<?php

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

// Parámetros de consulta
$page = 1;
$limit = 10;
$listingStartDate = '2024-03-01';
$listingEndDate = '2024-03-31';

$queryParams = http_build_query([
    'page' => $page,
    'limit' => $limit,
    'listing_start_date' => $listingStartDate,
    'listing_end_date' => $listingEndDate
]);

$url = "https://{$instance}/service/v2/public/properties?{$queryParams}";

$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) {
        $propiedades = json_decode($response, true);
        echo "Propiedades encontradas: " . count($propiedades) . "\n";
        foreach ($propiedades as $propiedad) {
            echo "  [{$propiedad['codigo']}] {$propiedad['titulo']} - {$propiedad['estado_texto']}\n";
        }
    } else {
        echo "Error al consultar las propiedades.\n";
        echo $response . "\n";
    }
}
curl_close($ch);

?>
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 Login

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

params = {
    "page": 1,
    "limit": 10,
    "listing_start_date": "2024-03-01",
    "listing_end_date": "2024-03-31"
}

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, params=params, headers=headers)

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

    if response.status_code == 200:
        propiedades = response.json()
        print(f"Propiedades encontradas: {len(propiedades)}")
        for prop in propiedades:
            print(f"  [{prop['codigo']}] {prop['titulo']} - {prop['estado_texto']}")
    else:
        print("Error al consultar las propiedades.")
        print(f"Detalle del error: {response.text}")

except Exception as e:
    print(f"Ocurrió un error de conexión: {e}")
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 Login

// 2. Prepara la dirección con parámetros
const params = new URLSearchParams({
    page: 1,
    limit: 10,
    listing_start_date: '2024-03-01',
    listing_end_date: '2024-03-31'
});

const url = `https://${instancia}/service/v2/public/properties?${params}`;

// 3. Función para consultar las propiedades
async function consultarPropiedades() {
    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 propiedades = await response.json();
            console.log(`Propiedades encontradas: ${propiedades.length}`);
            propiedades.forEach(prop => {
                console.log(`  [${prop.codigo}] ${prop.titulo} - ${prop.estado_texto}`);
            });
        } else {
            console.log('Error al consultar las propiedades.');
            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
consultarPropiedades();
Power Query M (Excel / Power BI)
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 Login

    // 2. Prepara la dirección de la petición con parámetros
    url = "https://" & instancia & "/service/v2/public/properties?page=1&limit=50",

    // 3. Envía la petición GET
    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",
        {"codigo", "titulo", "clase_inmueble", "tipo_servicio", "estado_texto", "direccion", "municipio", "departamento", "area", "valor_arriendo1", "valor_venta1", "fecha_consignacion"},
        {"Codigo", "Titulo", "ClaseInmueble", "TipoServicio", "Estado", "Direccion", "Municipio", "Departamento", "Area", "ValorArriendo", "ValorVenta", "FechaConsignacion"})
in
    expandido
Propiedades

Buscar Propiedad por Código

Permite obtener la información completa de una propiedad específica a partir de su código único. La respuesta incluye datos generales, ubicación, valores económicos, características, propietarios, imágenes, videos y códigos de portales inmobiliarios.

¿Para qué sirve este servicio?
Úsalo cuando ya conoces el código del inmueble y necesitas consultar toda su información detallada. Es ideal para mostrar la ficha completa de una propiedad en tu sitio web, sincronizar datos de un inmueble puntual o verificar la información registrada en el sistema.


1. El Endpoint (La dirección web)

Apunta tu sistema a la siguiente dirección. Recuerda reemplazar {{instancia}} por la dirección web completa que utilizas para ingresar a tu plataforma, y {{code}} por el código numérico del inmueble que deseas consultar.

GET https://{{instancia}}/service/v2/public/properties/{{code}}

¿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.

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

Este servicio requiere autenticación mediante un Token JWT. Construye la URL con el código de la propiedad como parte de la ruta e incluye los encabezados requeridos:

Método GET
Content-Type application/json
Authorization Bearer token, Token obtenido al consumir el servicio Login.

Autenticación requerida
Este servicio requiere un Token de autenticación válido. Debes incluir el encabezado Authorization: Bearer TU_TOKEN en cada petición. El token se obtiene consumiendo el servicio de Login. Adicionalmente, el cliente OAuth debe contar con el scope read para poder consumir este endpoint.

Parámetro de ruta:

Parámetro Tipo Requerido Descripción
code integer Código numérico único del inmueble que se desea consultar. Debe ser un número entero positivo.

Ejemplos de peticiones:

GET https://{{instancia}}/service/v2/public/properties/137
GET https://{{instancia}}/service/v2/public/properties/2045

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

El sistema te devolverá un objeto JSON con toda la información de la propiedad solicitada. Si el código no corresponde a ningún inmueble registrado, se devolverá un arreglo vacío [].

Respuesta como objeto, no como lista
A diferencia del servicio Listar Propiedades que devuelve un arreglo de objetos [{...}, {...}], este servicio devuelve directamente un único objeto {...} con la información del inmueble consultado.

La respuesta exitosa se verá similar a esta:

{
    "codigo": "137",
    "titulo": "Apartamento amplio con vista al parque central",
    "clase_id": "1247",
    "clase_inmueble": "Apartamento",
    "tipo_servicio_id": "arriendo",
    "tipo_servicio": "Arriendo",
    "estrato": "1258",
    "estrato_texto": "Cuatro",
    "fecha_consignacion": "2024-04-26",
    "asesor_id": "5",
    "asesor": "María López Ramírez",
    "pais_id": "1",
    "pais": "COLOMBIA",
    "departamento_id": "5",
    "departamento": "Antioquia",
    "municipio_id": "1",
    "municipio": "Medellin",
    "barrio_id": "3",
    "barrio": "Los Rosales",
    "direccion": "CALLE 45 # 32 - 18",
    "coordenadas": "6.24830000000000:-75.56120000000000",
    "valor_arriendo1": "1600000",
    "valor_arriendo2": "0",
    "valor_venta1": "0",
    "valor_venta2": "0",
    "valor_administracion": "250000",
    "avaluo_catastral": "185000000",
    "impuesto_predial": "1250000.00",
    "area": "75.00",
    "observaciones": "Inmueble ubicado en zona residencial tranquila, cerca de centros comerciales y transporte público.",
    "propiedad_destacada": "No",
    "llaves_en": "oficina",
    "llaves_otro": null,
    "paga_cuota_sost": "propietario",
    "folio_matricula": "001-123456",
    "referencia_catastral": "05001010203040",
    "edificio_unidad": "urbanizacion",
    "estado": "1",
    "estado_texto": "Activa",
    "cantidad_images": "3",
    "cantidad_videos": "1",
    "fecha_creacion": "2024-04-26 10:30:00",
    "ultima_fecha_modificacion": "2024-05-15 14:22:00",
    "caracteristicas": [
        {
            "id": "1",
            "descripcion": "Nº De Habitaciones",
            "tipo_campo": "numeric",
            "orden": "1",
            "grupo": "Características del inmueble",
            "valor": "4"
        },
        {
            "id": "2",
            "descripcion": "Nº De Baños",
            "tipo_campo": "numeric",
            "orden": "2",
            "grupo": "Características del inmueble",
            "valor": "3"
        },
        {
            "id": "5",
            "descripcion": "Nº De Piso",
            "tipo_campo": "numeric",
            "orden": "3",
            "grupo": "Características del inmueble",
            "valor": "1"
        },
        {
            "id": "4",
            "descripcion": "Antigüedad del Inmueble",
            "tipo_campo": "numeric",
            "orden": "5",
            "grupo": "Características del Inmueble",
            "valor": "3"
        },
        {
            "id": "14",
            "descripcion": "Cocina Integral",
            "tipo_campo": "checkbox",
            "orden": "5",
            "grupo": "Características Internas",
            "valor": "1"
        },
        {
            "id": "34",
            "descripcion": "Sala",
            "tipo_campo": "checkbox",
            "orden": "6",
            "grupo": "Características del Inmueble",
            "valor": "1"
        },
        {
            "id": "31",
            "descripcion": "Red de gas",
            "tipo_campo": "select",
            "orden": "5",
            "grupo": "Características del Inmueble",
            "valor": "si",
            "valor_texto": "Si"
        },
        {
            "id": "63",
            "descripcion": "Garaje",
            "tipo_campo": "checkbox",
            "orden": "10",
            "grupo": "Características Internas",
            "valor": "1"
        }
    ],
    "propietarios": [
        {
            "id": "272",
            "documento": "1020304050",
            "nombres": "ANA MARÍA",
            "apellidos": "PÉREZ RODRÍGUEZ"
        }
    ],
    "imagenes": [
        {
            "posicion": "1",
            "size": "19201080",
            "img": "img/fotos/1920x1080_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6.jpeg",
            "imagen": "https://mi-inmobiliaria.nuby.app/img/fotos/1920x1080_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6.jpeg"
        },
        {
            "posicion": "2",
            "size": "19201080",
            "img": "img/fotos/1920x1080_f6e5d4c3b2a1f6e5d4c3b2a1f6e5d4c3.jpeg",
            "imagen": "https://mi-inmobiliaria.nuby.app/img/fotos/1920x1080_f6e5d4c3b2a1f6e5d4c3b2a1f6e5d4c3.jpeg"
        },
        {
            "posicion": "3",
            "size": "19201080",
            "img": "img/fotos/1920x1080_b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8.jpeg",
            "imagen": "https://mi-inmobiliaria.nuby.app/img/fotos/1920x1080_b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8.jpeg"
        }
    ],
    "videos": [
        {
            "url": "dQw4w9WgXcQ",
            "tipo": "youtube",
            "descripcion": null,
            "posicion": "1"
        }
    ],
    "codigos_portales": [
        {
            "nombre_portal": "metrocuadrado",
            "id_portal": "MC-98765",
            "tipo_servicio": "arriendo"
        }
    ]
}

Cuando el código no corresponde a ningún inmueble, la respuesta será:

[]
Campos principales de la propiedad

Esta tabla enumera las claves presentes en el JSON de la propiedad y proporciona una descripción de cada una:

Clave Descripción
codigo Código único del inmueble en el sistema.
titulo Título del anuncio del inmueble.
clase_id Identificador de la clase de inmueble. Corresponde al id del servicio Listar Clases de Inmueble.
clase_inmueble Nombre de la clase de inmueble (por ejemplo: "Apartamento", "Casa", "Finca").
tipo_servicio_id Identificador del tipo de servicio. Valores posibles: "arriendo", "venta", "venta y arriendo".
tipo_servicio Nombre descriptivo del tipo de servicio (por ejemplo: "Arriendo", "Venta").
estrato Identificador del estrato socioeconómico del inmueble.
estrato_texto Texto descriptivo del estrato (por ejemplo: "Cuatro", "Tres").
fecha_consignacion Fecha en que el inmueble fue captado/consignado para su gestión. Formato: YYYY-MM-DD.
asesor_id Identificador del asesor asignado al inmueble. Cadena vacía si no tiene asesor asignado.
asesor Nombre completo del asesor asignado.
pais_id Identificador del país donde se ubica el inmueble.
pais Nombre del país.
departamento_id Identificador del departamento/estado/provincia.
departamento Nombre del departamento.
municipio_id Identificador del municipio/ciudad.
municipio Nombre del municipio.
barrio_id Identificador del barrio. Puede ser null si no se ha asignado barrio.
barrio Nombre del barrio.
direccion Dirección física del inmueble.
coordenadas Coordenadas geográficas del inmueble en formato latitud:longitud.
valor_arriendo1 Valor principal de arriendo (canon mensual).
valor_arriendo2 Valor secundario de arriendo. 0 si no aplica.
valor_venta1 Valor principal de venta.
valor_venta2 Valor secundario de venta. 0 si no aplica.
valor_administracion Valor de la cuota de administración.
avaluo_catastral Avalúo catastral del inmueble.
impuesto_predial Valor del impuesto predial.
area Área del inmueble en metros cuadrados.
observaciones Observaciones o descripción adicional del inmueble. Puede ser null.
propiedad_destacada Indica si la propiedad está marcada como destacada. Valores: "Si" o "No".
llaves_en Lugar donde se encuentran las llaves del inmueble (por ejemplo: "oficina").
llaves_otro Ubicación alternativa de las llaves, si aplica. Puede ser null.
paga_cuota_sost Quién paga la cuota de sostenimiento (por ejemplo: "propietario"). Puede ser null.
folio_matricula Número de folio de matrícula inmobiliaria. Puede ser null.
referencia_catastral Referencia catastral del inmueble. Puede ser null.
edificio_unidad Tipo de agrupamiento del inmueble (por ejemplo: "urbanizacion", "edificio", "conjunto").
estado Identificador numérico del estado del inmueble. Valores: 0 (Arrendada), 1 (Activa), 2 (Inactiva), 3 (Vendida).
estado_texto Texto descriptivo del estado (por ejemplo: "Activa", "Arrendada").
cantidad_images Cantidad de imágenes asociadas al inmueble.
cantidad_videos Cantidad de videos asociados al inmueble.
fecha_creacion Fecha y hora de creación del registro en el sistema. Formato: YYYY-MM-DD HH:MM:SS.
ultima_fecha_modificacion Fecha y hora de la última modificación del registro. Formato: YYYY-MM-DD HH:MM:SS.
caracteristicas Lista de características del inmueble (ver tabla detallada abajo).
propietarios Lista de propietarios del inmueble (ver tabla detallada abajo).
imagenes Lista de imágenes del inmueble (ver tabla detallada abajo).
videos Lista de videos del inmueble (ver tabla detallada abajo).
codigos_portales Lista de códigos de publicación en portales inmobiliarios externos (ver tabla detallada abajo).
Características

Cada elemento dentro de la lista caracteristicas contiene la información de una característica del inmueble y su valor asignado:

Clave Descripción
id Identificador de la característica. Corresponde al id del servicio Listar Características.
descripcion Nombre descriptivo de la característica (por ejemplo: "Nº De Habitaciones").
tipo_campo Tipo de campo: numeric, checkbox, select, entre otros.
orden Posición de la característica dentro de su grupo.
grupo Grupo al que pertenece la característica.
valor Valor asignado a la característica para esta propiedad. Para numeric: un número. Para checkbox: "1" (marcado). Para select: el valor técnico de la opción seleccionada.
valor_texto Descripción legible del valor seleccionado. Solo presente cuando tipo_campo es select (por ejemplo: valor "si" → valor_texto "Si").
Propietarios

Cada elemento dentro de la lista propietarios contiene la información de un propietario del inmueble:

Clave Descripción
id Identificador del propietario (tercero) en el sistema.
documento Número de documento de identificación del propietario.
nombres Nombres del propietario.
apellidos Apellidos del propietario.
Imágenes

Cada elemento dentro de la lista imagenes contiene la información de una fotografía del inmueble:

Clave Descripción
posicion Posición de ordenamiento de la imagen (1 = principal).
size Resolución de la imagen (por ejemplo: "19201080").
img Ruta relativa de la imagen en el servidor.
imagen URL completa de la imagen, lista para consumir directamente.
Videos

Cada elemento dentro de la lista videos contiene la información de un video asociado al inmueble:

Clave Descripción
url Identificador o URL del video (por ejemplo, el ID de YouTube: "dQw4w9WgXcQ").
tipo Plataforma del video (por ejemplo: "youtube").
descripcion Descripción del video. Puede ser null.
posicion Posición de ordenamiento del video.
Códigos de Portales

Cada elemento dentro de la lista codigos_portales contiene la información de publicación del inmueble en un portal inmobiliario externo:

Clave Descripción
nombre_portal Nombre del portal inmobiliario (por ejemplo: "metrocuadrado", "fincaraiz").
id_portal Identificador de la propiedad en el portal externo.
tipo_servicio Tipo de servicio bajo el cual fue publicada la propiedad en ese portal.

4. Seguridad y Posibles Errores

El sistema realiza validaciones de autenticación, scopes y parámetros de ruta:

Cuando el código es numérico pero no corresponde a ningún inmueble registrado, el sistema no devuelve un error. En su lugar, responde con un HTTP 200 y un arreglo vacío:

[]

Importante
Asegúrate de validar en tu integración si la respuesta es un arreglo vacío [] para manejar correctamente el caso en que la propiedad no exista.

Código HTTP Descripción
200 Respuesta exitosa. Contiene el objeto JSON de la propiedad, o un arreglo vacío [] si no se encontró ningún inmueble con ese código.
400 Token faltante o inválido. Posibles causas:
— No se envió el encabezado Authorization. Mensaje: "JWT Token required."
— El encabezado no tiene el formato Bearer {token}. Mensaje: "JWT Token not send."
— El token no fue encontrado en el sistema. Mensaje: "JWT Token not found."
401 El token ha expirado. Debes generar uno nuevo consumiendo el servicio de Login. Mensaje: "JWT Token expired."
403 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}'."
404 La ruta no fue encontrada. Ocurre cuando el valor de code no es numérico (por ejemplo: /properties/abc).

5. Ejemplos de integración

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

cURL
# Consultar propiedad por código
curl -X GET "https://{{instancia}}/service/v2/public/properties/137" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer TU_TOKEN_AQUI"
PHP
<?php

$instance = 'tu_instancia'; // Reemplaza con tu instancia real
$token = 'TU_TOKEN_AQUI'; // Token obtenido del servicio Login
$code = 137; // Código de la propiedad a consultar

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

$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) {
        $propiedad = json_decode($response, true);

        if (!empty($propiedad)) {
            echo "Propiedad encontrada:\n";
            echo "  Código: {$propiedad['codigo']}\n";
            echo "  Título: {$propiedad['titulo']}\n";
            echo "  Estado: {$propiedad['estado_texto']}\n";
            echo "  Dirección: {$propiedad['direccion']}\n";
            echo "  Imágenes: {$propiedad['cantidad_images']}\n";
        } else {
            echo "No se encontró ninguna propiedad con el código {$code}.\n";
        }
    } else {
        echo "Error al consultar la propiedad.\n";
        echo $response . "\n";
    }
}
curl_close($ch);

?>
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 Login
codigo = 137 # Código de la propiedad a consultar

# 2. Prepara la dirección de la petición
url = f"https://{instancia}/service/v2/public/properties/{codigo}"

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:
        propiedad = response.json()

        if propiedad:
            print(f"Propiedad encontrada:")
            print(f"  Código: {propiedad['codigo']}")
            print(f"  Título: {propiedad['titulo']}")
            print(f"  Estado: {propiedad['estado_texto']}")
            print(f"  Dirección: {propiedad['direccion']}")
            print(f"  Características: {len(propiedad['caracteristicas'])}")
        else:
            print(f"No se encontró ninguna propiedad con el código {codigo}.")
    else:
        print("Error al consultar la propiedad.")
        print(f"Detalle del error: {response.text}")

except Exception as e:
    print(f"Ocurrió un error de conexión: {e}")
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 Login
const codigo = 137; // Código de la propiedad a consultar

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

// 3. Función para consultar la propiedad
async function consultarPropiedad() {
    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 propiedad = await response.json();

            if (propiedad && !Array.isArray(propiedad)) {
                console.log(`Propiedad encontrada:`);
                console.log(`  Código: ${propiedad.codigo}`);
                console.log(`  Título: ${propiedad.titulo}`);
                console.log(`  Estado: ${propiedad.estado_texto}`);
                console.log(`  Dirección: ${propiedad.direccion}`);
                console.log(`  Imágenes: ${propiedad.cantidad_images}`);
            } else {
                console.log(`No se encontró ninguna propiedad con el código ${codigo}.`);
            }
        } else {
            console.log('Error al consultar la propiedad.');
            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
consultarPropiedad();
Power Query M (Excel / Power BI)
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 Login
    codigo = "137", // Código de la propiedad a consultar

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

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

    // 4. Decodifica la respuesta JSON y conviértela en registro
    jsonResponse = Json.Document(response),
    resultado = Record.ToTable(jsonResponse),
    expandido = Table.Pivot(resultado, List.Distinct(resultado[Name]), "Name", "Value")
in
    expandido
Propiedades

Actualizar Estado de la Propiedad

Permite actualizar el estado de una propiedad específica a partir de su código único. Este servicio es útil para cambiar el estado de un inmueble entre los estados permitidos por el sistema.

¿Para qué sirve este servicio?
Úsalo cuando necesites cambiar el estado de un inmueble desde tu sistema externo, por ejemplo: marcar una propiedad como inactiva cuando se retira del mercado, reactivarla cuando vuelve a estar disponible, o registrar que fue vendida.


1. El Endpoint (La dirección web)

Apunta tu sistema a la siguiente dirección. Recuerda reemplazar {{instancia}} por la dirección web completa que utilizas para ingresar a tu plataforma, y {{code}} por el código numérico del inmueble cuyo estado deseas actualizar.

PATCH https://{{instancia}}/service/v2/public/properties/{{code}}/status

¿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.

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

Debes enviar una petición PATCH con el nuevo estado en el cuerpo de la solicitud en formato JSON:

Método PATCH
Content-Type application/json
Authorization Bearer token, Token obtenido al consumir el servicio Login.

Autenticación requerida
Este servicio requiere un Token de autenticación válido. Debes incluir el encabezado Authorization: Bearer TU_TOKEN en cada petición. El token se obtiene consumiendo el servicio de Login. Adicionalmente, el cliente OAuth debe contar con el scope update para poder consumir este endpoint.

Parámetro de ruta:

Parámetro Tipo Requerido Descripción
code integer Código numérico único del inmueble cuyo estado se desea actualizar.

Cuerpo de la petición (Body):

Campo Tipo Requerido Descripción
status integer Nuevo estado que se desea asignar a la propiedad. Los valores válidos son:
1 = Activa
2 = Inactiva
3 = Vendida

Restricción importante sobre el estado "Arrendada" (0)
Aunque el estado 0 (Arrendada) existe en el sistema, no es posible asignar este estado a través de la API. El estado "Arrendada" se gestiona internamente por el sistema cuando se registra un contrato de arrendamiento asociado al inmueble.

Estados válidos del sistema
ID Estado Descripción
0 Arrendada El inmueble tiene un contrato de arrendamiento vigente. No se puede asignar vía API.
1 Activa El inmueble está disponible en el mercado para arriendo o venta.
2 Inactiva El inmueble fue retirado temporalmente del mercado.
3 Vendida El inmueble fue vendido.
Reglas de transición de estado

El sistema solo permite cambiar el estado de una propiedad cuando su estado actual es Activa (1) o Inactiva (2). Las transiciones posibles son:

Estado actual Puede cambiar a
Activa (1) 2 (Inactiva) o 3 (Vendida)
Inactiva (2) 1 (Activa) o 3 (Vendida)
Arrendada (0) No se permite cambiar el estado vía API.
Vendida (3) No se permite cambiar el estado vía API.

¿Por qué no se puede modificar el estado de una propiedad "Arrendada" o "Vendida"?
Estos son estados terminales que representan transacciones completadas. El cambio de estos estados se gestiona internamente a través de los procesos de negocio del sistema (por ejemplo, al finalizar un contrato de arrendamiento o reversar una venta).

Ejemplo de petición:

PATCH https://{{instancia}}/service/v2/public/properties/137/status
{
    "status": 2
}

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

Si la actualización fue exitosa, el sistema responderá con HTTP 200 y un mensaje de confirmación:

{
    "message": "Se actualizo el estado de la propiedad correctamente"
}
Clave Descripción
message Mensaje indicando que el estado de la propiedad fue actualizado correctamente.

4. Seguridad y Posibles Errores

El sistema realiza validaciones de autenticación, scopes y datos de la petición. Si alguna falla, devolverá un error con su respectivo código HTTP:

Código HTTP Descripción Ejemplo de respuesta
400 Token faltante o inválido. Posibles causas:
— No se envió el encabezado Authorization. Mensaje: "JWT Token required."
— El encabezado no tiene el formato Bearer {token}. Mensaje: "JWT Token not send."
— El token no fue encontrado en el sistema. Mensaje: "JWT Token not found."

Parámetros inválidos. El campo status no fue enviado o no es numérico.
{
    "error": "El estado(status) es requerido"
}
401 El token ha expirado. Debes generar uno nuevo consumiendo el servicio de Login.
"JWT Token expired."
403 El cliente OAuth no tiene el scope necesario. Para endpoints PATCH se requiere el scope update.
"Insufficient scope. Required: 'update', granted: '{scope_actual}'."
404 No se encontró ninguna propiedad con el código indicado.
{
    "error": "No se encontró la propiedad"
}
422 El valor de status no corresponde a un estado válido del sistema (no es 0, 1, 2 o 3).
{
    "error": "El estado no es válido"
}
422 El estado actual de la propiedad no permite la modificación (por ejemplo: la propiedad está en estado "Arrendada" o "Vendida").
{
    "error": "El estado actual de la propiedad no permite este tipo de modificación."
}
500 Error interno del servidor. No se pudo ejecutar la actualización en la base de datos.
{
    "error": "No se pudo actualizar el estado de la propiedad"
}

5. Ejemplos de integración

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

cURL
# Cambiar estado de propiedad 137 a Inactiva (2)
curl -X PATCH "https://{{instancia}}/service/v2/public/properties/137/status" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer TU_TOKEN_AQUI" \
-d '{"status": 2}'

# Cambiar estado de propiedad 2045 a Vendida (3)
curl -X PATCH "https://{{instancia}}/service/v2/public/properties/2045/status" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer TU_TOKEN_AQUI" \
-d '{"status": 3}'

# Reactivar propiedad 890 (de Inactiva a Activa)
curl -X PATCH "https://{{instancia}}/service/v2/public/properties/890/status" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer TU_TOKEN_AQUI" \
-d '{"status": 1}'
PHP
<?php

$instance = 'tu_instancia'; // Reemplaza con tu instancia real
$token = 'TU_TOKEN_AQUI'; // Token obtenido del servicio Login
$code = 137; // Código de la propiedad
$nuevoEstado = 2; // 1 = Activa, 2 = Inactiva, 3 = Vendida

$url = "https://{$instance}/service/v2/public/properties/{$code}/status";

$body = json_encode([
    'status' => $nuevoEstado
]);

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PATCH');
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
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";

    $data = json_decode($response, true);

    if ($http_code === 200) {
        echo "Éxito: " . $data['message'] . "\n";
    } else {
        echo "Error: " . ($data['error'] ?? 'Error desconocido') . "\n";
    }
}
curl_close($ch);

?>
Python
import requests
import json

# 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 Login
codigo = 137 # Código de la propiedad
nuevo_estado = 2 # 1 = Activa, 2 = Inactiva, 3 = Vendida

# 2. Prepara la dirección y el cuerpo de la petición
url = f"https://{instancia}/service/v2/public/properties/{codigo}/status"

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

body = {
    "status": nuevo_estado
}

# 3. Envía la petición PATCH y procesa la respuesta
try:
    response = requests.patch(url, headers=headers, json=body)

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

    data = response.json()

    if response.status_code == 200:
        print(f"Éxito: {data['message']}")
    else:
        error_msg = data.get('error', 'Error desconocido')
        print(f"Error: {error_msg}")

except Exception as e:
    print(f"Ocurrió un error de conexión: {e}")
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 Login
const codigo = 137; // Código de la propiedad
const nuevoEstado = 2; // 1 = Activa, 2 = Inactiva, 3 = Vendida

// 2. Prepara la dirección de la petición
const url = `https://${instancia}/service/v2/public/properties/${codigo}/status`;

// 3. Función para actualizar el estado
async function actualizarEstadoPropiedad() {
    try {
        const response = await fetch(url, {
            method: 'PATCH',
            headers: {
                'Content-Type': 'application/json',
                'Authorization': `Bearer ${token}`
            },
            body: JSON.stringify({
                status: nuevoEstado
            })
        });

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

        const data = await response.json();

        if (response.ok) {
            console.log(`Éxito: ${data.message}`);
        } else {
            console.log(`Error: ${data.error || 'Error desconocido'}`);
        }
    } catch (error) {
        console.error(`Ocurrió un error de conexión: ${error}`);
    }
}

// 4. Ejecutamos la función
actualizarEstadoPropiedad();
Power Query M (Excel / Power BI)
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 Login
    codigo = "137", // Código de la propiedad
    nuevoEstado = 2, // 1 = Activa, 2 = Inactiva, 3 = Vendida

    // 2. Prepara la dirección y el cuerpo de la petición
    url = "https://" & instancia & "/service/v2/public/properties/" & codigo & "/status",
    body = Json.FromValue([status = nuevoEstado]),

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

    // 4. Decodifica la respuesta JSON
    jsonResponse = Json.Document(response)
in
    jsonResponse
Propiedades

Crear Propiedad

Permite registrar una nueva propiedad en el sistema de forma integral. A través de este servicio, es posible guardar la información básica de la propiedad, asociar propietarios (existentes o creados dinámicamente en la misma petición), registrar características personalizadas, coordenadas geográficas, videos de recorridos, fotos del inmueble y relacionar otras propiedades.

¿Para qué sirve este servicio?
Úsalo cuando necesites automatizar el ingreso de propiedades a nuby desde portales externos, aplicaciones móviles o sistemas de captación propios. Este endpoint está diseñado bajo un modelo transaccional robusto, asegurando que si algún paso crítico falla (por ejemplo, validación de un propietario o falta de características obligatorias del tipo de propiedad), toda la operación se cancele de forma automática para evitar datos inconsistentes en tu base de datos.


1. El Endpoint (La dirección web)

Apunta tu sistema a la siguiente dirección de petición POST. Recuerda reemplazar {{instancia}} por la dirección web completa que utilizas para ingresar a tu plataforma.

POST https://{{instancia}}/service/v2/public/properties

¿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.

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

Este servicio requiere autenticación mediante un Token JWT. Envía los encabezados requeridos y estructura la petición con un cuerpo (Body) en formato JSON que contenga las secciones detalladas a continuación:

Método POST
Content-Type application/json
Authorization Bearer token, Token obtenido al consumir el servicio Login.

Autenticación requerida
Este servicio requiere un Token de autenticación válido. Debes incluir el encabezado Authorization: Bearer TU_TOKEN en cada petición. El token se obtiene consumiendo el servicio de Login. Adicionalmente, el cliente OAuth debe contar con el scope write para poder consumir este endpoint.

Cuerpo de la petición (JSON Body - Estructura General)

La raíz del JSON enviado debe estructurarse con las siguientes llaves principales:

Elemento Raíz Tipo Requerido Descripción
Propiedad object Contiene la información básica del inmueble (Título, tipo, ubicación, valores, etc.).
Propietarios array Lista de propietarios asociados. Puede ser un arreglo de IDs existentes o de objetos con datos de nuevos propietarios.
Caracteristicas object No Mapeo de características de la propiedad en formato llave-valor {"id_caracteristica": "valor"}.
Videos array No Listado de enlaces a videos del inmueble.
Fotos array No Listado de imágenes del inmueble en formato base64 o URLs públicas.
PropiedadesRelacionadas array No Arreglo de códigos numéricos de propiedades que se desea relacionar de forma recíproca.
Coordenadas string | object No Coordenadas de latitud y longitud. Ejemplo de texto: "6.2089,-75.5678".

Estructura Detallada de las Secciones

2.1 Sección "Propiedad" 🏢

Contiene la información comercial y técnica base del inmueble. Los siguientes campos son validados estrictamente bajo validación rápida (Fail-Fast):

Campo Tipo Requerido Descripción
txtTitulo string Título descriptivo o publicitario del inmueble. Máximo 255 caracteres.
tipo_id integer ID de la clase de propiedad (Ej: apartamento, casa, local). Debe ser una clase existente en la maestra de clases de inmueble.
propiedad_tipo string Modalidad de comercialización. Valores válidos: "arriendo", "venta", o "venta y arriendo".
municipio_id integer ID de la ciudad o municipio donde se ubica el inmueble (debe existir en la maestra de municipios).
direccion string Dirección exacta del inmueble. El sistema validará que no exista otra propiedad con la misma dirección en el mismo municipio para evitar duplicados accidentales.
estrato integer Estrato socioeconómico del inmueble. Debe ser un número entero entre 1 y 6.
barrio_id integer No ID del barrio (debe existir en la maestra de barrios de la ciudad).
urbanizacion string No Nombre del edificio, conjunto cerrado o urbanización.
valor_arriendo numeric No Canon mensual del arriendo (monto mayor o igual a 0).
valor_venta numeric No Precio de venta solicitado (monto mayor o igual a 0).
valor_administracion numeric No Costo de la cuota de administración de la copropiedad.
propiedad_area numeric No Área privada del inmueble en metros cuadrados. Se envía estrictamente con el nombre físico de columna.
observaciones string No Descripción comercial extensa del inmueble.
llaves_en string No Ubicación física de las llaves. Valores válidos: "oficina", "propiedad", o "otro".
paga_cuota_sost string No Establece quién asume el pago de la cuota de administración. Valores válidos: "propietario" o "inquilino".
folio_matricula string No Número de matrícula inmobiliaria del inmueble.
referencia_catastral string No Número de referencia catastral asignado por el municipio.

2.2 Sección "Propietarios" 👥

Cada propiedad en nuby requiere obligatoriamente tener asociado al menos un propietario. El arreglo acepta dos formatos de datos, los cuales pueden combinarse:

Formato A: Propietario Existente (Por ID)

Si el propietario ya se encuentra registrado en el ERP nuby, simplemente envía su identificador único (ID de tercero) como un entero dentro del arreglo:

"Propietarios": [1528, 4390]

Formato B: Creación Dinámica de Propietario (Objeto de Datos)

Si el propietario no existe, puedes enviar sus datos completos estructurados en un objeto. El sistema validará su información, lo creará automáticamente en la base de datos de nuby, y lo asociará al inmueble bajo una misma transacción comercial:

Campo Tipo Requerido Descripción
persona integer Naturaleza jurídica del tercero: 1 = Persona Natural, 2 = Persona Jurídica.
documento string Número de documento de identidad o NIT.
tipo_doc_id integer ID de la maestra de tipos de documentos (Cédula, NIT, Pasaporte, etc.).
nombre1 string Primer nombre del propietario o razón social completa.
apellido1 string Sí (para Natural) Primer apellido del propietario (requerido si persona = 1).
direccion1 string Dirección de domicilio del propietario.
municipio_id integer ID del municipio de residencia (debe existir en la base de datos).
email string Correo electrónico para envío de facturas and notificaciones. Debe tener formato de email válido.
telefono string Número telefónico o celular de contacto.
tipo_persona_id integer Sí (para Natural) ID de tipo de persona tributaria (requerido si persona = 1).
regimen_id integer Sí (para Natural) ID del régimen tributario del propietario (requerido si persona = 1).
resp_fiscal_id integer Sí (para Natural) ID de la responsabilidad fiscal (requerido si persona = 1).

2.3 Sección "Caracteristicas" ⚙️

Permite registrar valores para las características personalizadas del inmueble. Se envía en formato de objeto clave-valor, donde la clave es el ID numérico de la característica y el valor es el contenido a asignar:

"Caracteristicas": {
    "1": "3",   // ID 1 (Habitaciones) = 3
    "2": "2",   // ID 2 (Baños) = 2
    "31": "si", // ID 31 (Red de gas) = si (Obligatoria)
    "63": "1"   // ID 63 (Garaje) = 1 (Checkbox de Garaje activo)
}

Validación de Características Obligatorias por Tipo
El motor de validación del sistema nuby verificará qué características están configuradas en el ERP como obligatorias para el tipo de propiedad seleccionado (tipo_id). Si omites alguna de estas características obligatorias en la petición, o el formato del valor es erróneo (por ejemplo, enviar texto en un campo netamente numérico), el endpoint devolverá un código de estado 422 Unprocessable Entity y se revertirá todo el proceso de guardado.
Nota: En una configuración estándar, el apartamento (1247) y la casa (1249) exigen de forma obligatoria las características de: N° de Habitaciones (ID 1), N° de Baños (ID 2) y Red de gas (ID 31).


2.4 Sección "Fotos" 📸

Permite adjuntar imágenes del inmueble de forma directa. El procesamiento de imágenes está automatizado y realiza optimizaciones de rendimiento y de presentación visual (redimensionamiento, corrección de orientación por metadatos EXIF, e inserción de la marca de agua corporativa configurada en el sistema).

Campo Tipo Requerido Descripción
url string Contenido de la imagen. Puede enviarse como una cadena Base64 válida (data:image/jpeg;base64,...) o como una URL accesible públicamente para su descarga.
nombre string No Nombre del archivo o descripción física para almacenar el documento.

2.5 Sección "Videos" 🎥

Permite registrar recorridos en video de las propiedades (por ejemplo, cargados en plataformas como YouTube o Vimeo):

Campo Tipo Requerido Descripción
video_url string URL completa o código físico del video. Ejemplo: "https://www.youtube.com/watch?v=...".
video_tipo string No Tipo o plataforma emisora del video (Ej: "youtube" o "vimeo").
video_descripcion string No Descripción del video.
video_posicion integer No Posición de visualización de este video.

2.6 Sección "PropiedadesRelacionadas" y "Coordenadas" 📍


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

Esta sección describe la respuesta que recibirás del sistema cuando la creación del inmueble sea completamente exitosa.

Respuesta Exitosa (201 Created)

Se genera cuando la propiedad y todos sus componentes asociados han sido validados e insertados con éxito. Se retorna el identificador único físico asignado al inmueble:

{
  "error": false,
  "type": "success",
  "msg": "La propiedad ha sido creada exitosamente.",
  "propiedad_id": 7786,
  "warnings": []
}

¿Qué contiene la sección "warnings"?
Si se incluyen fotos o videos y el almacenamiento en la nube o procesamiento de marcas de agua tiene algún inconveniente no letal (por ejemplo, formato no soportado o redimensión fallida de una imagen en particular), el inmueble se creará con éxito, pero se devolverán advertencias en esta sección para que puedas corregir los archivos de forma manual. Esto no interrumpe el registro del inmueble.


4. Seguridad y Posibles Errores

El sistema realiza validaciones de autenticación, permisos (scopes) y estructura de datos. Si alguna falla, devolverá un error con su respectivo código HTTP y un mensaje descriptivo:

Código HTTP Significado y Solución
400 Bad Request Causa: La estructura de la petición es incorrecta o faltan datos esenciales. Ocurre antes de que se intente procesar la lógica de negocio.
Ejemplos comunes:
  • No se envió el objeto Propiedad o el array Propietarios.
  • El array Propietarios está vacío.
  • Se omitieron campos obligatorios dentro de la sección Propiedad (ej: municipio_id, direccion).
  • Se envió un tipo de dato incorrecto (ej: texto en un campo numérico como estrato).
Solución: Revisa el cuerpo (body) de tu petición JSON y compáralo con la estructura definida en la sección 2 de esta guía. Asegúrate de que todos los campos requeridos estén presentes y tengan el tipo de dato correcto.
401 Unauthorized Causa: El Token JWT de autenticación no es válido o ha expirado.
Solución: Vuelve a consumir el servicio de Login para generar un nuevo token de acceso y úsalo en el encabezado Authorization.
403 Forbidden Causa: El token es válido, pero el cliente OAuth con el que fue generado no tiene los permisos (scopes) necesarios para esta operación.
Solución: Verifica la configuración de tu cliente OAuth en nuby y asegúrate de que tenga asignado el scope write.
422 Unprocessable Entity Causa: La petición es sintácticamente correcta, pero incumple una regla de negocio del sistema.
Ejemplos comunes:
  • La direccion enviada ya existe para otra propiedad en el mismo municipio_id.
  • Se omitió una característica marcada como obligatoria para el tipo_id de la propiedad.
  • Se intentó crear un propietario persona natural omitiendo los campos fiscales requeridos.
  • Se usó un ID de un modelo que no existe (ej: un municipio_id o tipo_id inválido).
Solución: Lee con atención el msg del JSON de error. Te indicará exactamente qué regla de negocio se infringió para que puedas corregir los datos enviados.

Operación Atómica y de Transacción Segura
nuby implementa transacciones anidadas en sus modelos de negocio. Si el endpoint responde con un código 422 (o un fallo 500 del servidor), toda la creación física del inmueble es cancelada de forma automática (ROLLBACK). No tendrás propiedades huérfanas sin propietario ni registros incompletos en las tablas del sistema.


5. Ejemplos de integración

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

Ejemplos de JSON Body
Ejemplo 1: Creación de propiedad con propietario existente
{
  "Propiedad": {
    "txtTitulo": "Penthouse Duplex El Poblado con Terraza",
    "tipo_id": 1247,
    "propiedad_tipo": "arriendo",
    "municipio_id": 1,
    "direccion": "Carrera 35 # 10B - 120, Apartamento 1201",
    "estrato": 1260,
    "barrio_id": 5,
    "valor_arriendo": 4800000,
    "valor_administracion": 650000,
    "urbanizacion": "Torres de San Lucas",
    "observaciones": "Espectacular penthouse con vista de 360 grados, tina de hidromasajes en terraza principal, 3 alcobas cada una con baño.",
    "propiedad_area": 185.4,
    "llaves_en": "oficina",
    "paga_cuota_sost": "propietario"
  },
  "Propietarios": [
    1247
  ],
  "Caracteristicas": {
    "1": "3",   // Alcobas
    "2": "4",   // Baños
    "31": "si", // Red de gas (Obligatoria)
    "63": "1"   // Garaje (Checkbox de Garaje - ID 63 en nuby)
  },
  "Coordenadas": "6.205210,-75.561240"
}
Ejemplo 2: Creación de propiedad con propietario nuevo, videos y fotos
{
  "Propiedad": {
    "txtTitulo": "Casa de Campo en Llanogrande",
    "tipo_id": 1249,
    "propiedad_tipo": "venta",
    "municipio_id": 2,
    "direccion": "Vía Llanogrande Kilómetro 4, Parcelación La Sofía",
    "estrato": 1259,
    "valor_venta": 1250000000,
    "valor_administracion": 300000,
    "observaciones": "Hermosa casa de un solo nivel, amplias zonas verdes, deck con zona BBQ, acabados campestres modernos.",
    "propiedad_area": 320.0,
    "paga_cuota_sost": "propietario"
  },
  "Propietarios": [
    {
      "persona": 1,
      "documento": "1024567890",
      "tipo_doc_id": 1,
      "nombre1": "Alejandro",
      "apellido1": "Restrepo",
      "direccion1": "Transversal 39B # 4G - 85",
      "municipio_id": 1,
      "email": "alejandro.restrepo@email.com",
      "telefono": "3104567890",
      "tipo_persona_id": 1,
      "regimen_id": 2,
      "resp_fiscal_id": 11
    }
  ],
  "Caracteristicas": {
    "1": "4",
    "2": "5",
    "31": "si", // Red de gas (Obligatoria)
    "63": "1",  // Garaje (Checkbox de Garaje - ID 63 en nuby)
    "8": "Sí"
  },
  "Videos": [
    {
      "video_url": "https://www.youtube.com/watch?v=abc123xyz",
      "video_tipo": "youtube",
      "video_descripcion": "Video aéreo con Dron de la parcelación"
    }
  ],
  "Fotos": [
    {
      "url": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==",
      "nombre": "foto_fachada_casa_campo.jpg"
    }
  ]
}
cURL
# Define tu token y tu instancia
TOKEN="TU_TOKEN_AQUI"
INSTANCIA="tu-inmobiliaria.nuby.app"

# Prepara el cuerpo de la petición utilizando estrictamente los nombres de campos físicos
PAYLOAD='{
  "Propiedad": {
    "txtTitulo": "Apartamento para prueba cURL",
    "tipo_id": 1247,
    "propiedad_tipo": "arriendo",
    "municipio_id": 127,
    "direccion": "Calle Falsa 123 via cURL",
    "estrato": 1258,
    "propiedad_area": 97
  },
  "Propietarios": [1],
  "Caracteristicas": {
    "1": "3",
    "2": "3",
    "31": "si",
    "63": "1"
  }
}'

curl -X POST "https://${INSTANCIA}/service/v2/public/properties" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${TOKEN}" \
-d "${PAYLOAD}"
PHP
<?php

$instancia = 'tu-inmobiliaria.nuby.app';
$token = 'TU_TOKEN_AQUI';

$url = "https://{$instancia}/service/v2/public/properties";

$payload = [
    'Propiedad' => [
        'txtTitulo' => 'Propiedad creada desde PHP',
        'tipo_id' => 1247,
        'propiedad_tipo' => 'venta',
        'municipio_id' => 127,
        'direccion' => 'Avenida Siempreviva 742, PHP',
        'estrato' => 1258,
        'propiedad_area' => 97 // Nombre exacto de la columna física
    ],
    'Propietarios' => [1], // ID de un propietario existente
    'Caracteristicas' => [
        '1' => '3',   // Habitaciones
        '2' => '3',   // Baños
        '31' => 'si', // Red de gas (Obligatoria)
        '63' => '1'   // Garaje (Checkbox de Garaje - ID 63 en nuby)
    ]
];

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Content-Type: application/json',
    "Authorization: Bearer {$token}"
]);

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

curl_close($ch);

echo "Código de estado HTTP: {$http_code}\n";
echo "Respuesta del servidor:\n";
print_r($response);

?>
Python
import requests
import json

instancia = 'tu-inmobiliaria.nuby.app'
token = 'TU_TOKEN_AQUI'
url = f"https://{instancia}/service/v2/public/properties"

payload = {
    "Propiedad": {
        "txtTitulo": "Propiedad Creada desde Python",
        "tipo_id": 1247,
        "propiedad_tipo": "venta",
        "municipio_id": 127,
        "direccion": "Calle de Python, 101",
        "estrato": 1258,
        "propiedad_area": 97
    },
    "Propietarios": [1], # ID de un propietario existente
    "Caracteristicas": {
        "1": "3",
        "2": "3",
        "31": "si",
        "63": "1"
    }
}

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

try:
    response = requests.post(url, headers=headers, data=json.dumps(payload))
    
    print(f"Código de estado HTTP: {response.status_code}")
    print("Respuesta del servidor:")
    print(response.json())

except requests.exceptions.RequestException as e:
    print(f"Ocurrió un error en la petición: {e}")

JavaScript (Fetch API)
const instancia = 'tu-inmobiliaria.nuby.app';
const token = 'TU_TOKEN_AQUI';
const url = `https://${instancia}/service/v2/public/properties`;

const payload = {
    "Propiedad": {
        "txtTitulo": "Propiedad Creada desde JavaScript",
        "tipo_id": 1247,
        "propiedad_tipo": "arriendo",
        "municipio_id": 127,
        "direccion": "Avenida JavaScript, Lote 5",
        "estrato": 1258,
        "propiedad_area": 97
    },
    "Propietarios": [1], // ID de un propietario existente
    "Caracteristicas": {
        "1": "3",
        "2": "3",
        "31": "si",
        "63": "1"
    }
};

async function crearPropiedad() {
    try {
        const response = await fetch(url, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'Authorization': `Bearer ${token}`
            },
            body: JSON.stringify(payload)
        });

        const data = await response.json();

        console.log(`Código de estado HTTP: ${response.status}`);
        console.log('Respuesta del servidor:');
        console.log(data);

    } catch (error) {
        console.error('Error en la petición:', error);
    }
}

crearPropiedad();
Power Query M (Excel / Power BI)
let
    instancia = "tu-inmobiliaria.nuby.app",
    token = "TU_TOKEN_AQUI",
    url = "https://" & instancia & "/service/v2/public/properties",

    payload = [
        Propiedad = [
            txtTitulo = "Propiedad desde Power Query",
            tipo_id = 1247,
            propiedad_tipo = "venta",
            municipio_id = 127,
            direccion = "Calle Power BI, 4.0",
            estrato = 1258,
            propiedad_area = 97
        ],
        Propietarios = {1}, // ID de un propietario existente
        Caracteristicas = [
            #"1" = "3",
            #"2" = "3",
            #"31" = "si",
            #"63" = "1"
        ]
    ],

    jsonPayload = Json.FromValue(payload),

    response = Web.Contents(url, [
        Headers = [
            #"Content-Type" = "application/json",
            #"Authorization" = "Bearer " & token
        ],
        Content = jsonPayload
    ]),
    
    jsonResponse = Json.Document(response)
in
    jsonResponse

Asesores

Bienvenido al directorio digital de personal de tu inmobiliaria. En esta sección agrupamos las herramientas necesarias para que tus aplicaciones externas consulten y sincronicen la información de tu equipo de asesores.

¿Cuál es el objetivo de este módulo? Garantizar que tu ecosistema de herramientas siempre sepa quiénes conforman tu equipo de trabajo. Ya sea que necesites extraer tu plantilla completa o ubicar a alguien en particular de manera rápida, tus plataformas podrán acceder a estos datos de forma totalmente automática.

¿Qué datos obtendrás en tus consultas? Por cada asesor, el sistema devolverá una "tarjeta de presentación" digital completa y lista para usar, que incluye:

¡Explora las opciones a continuación para que tus plataformas externas mantengan la información de tu equipo perfectamente actualizada!

Asesores

Listar Asesores

Permite obtener la lista completa de asesores registrados en el sistema. Cada elemento de la respuesta contiene los datos básicos de contacto de cada asesor: documento de identidad, nombre completo, teléfono, correo electrónico y fotografía.

¿Para qué sirve este servicio?
Úsalo cuando necesites conocer los asesores disponibles en la inmobiliaria, por ejemplo para mostrar un directorio de agentes en tu sitio web, poblar un selector de asesores en un formulario de contacto, o sincronizar la información de los agentes con tu sistema externo.


1. El Endpoint (La dirección web)

Apunta tu sistema a la siguiente dirección. Recuerda reemplazar {{instancia}} por la dirección web completa que utilizas para ingresar a tu plataforma.

GET https://{{instancia}}/service/v2/public/agents

¿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.

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

Este servicio no requiere cuerpo en la petición ni parámetros adicionales. Solo necesitas enviar los encabezados correctos:

Método GET
Content-Type application/json
Authorization Bearer token, Token obtenido al consumir el servicio Login

¿Aún no tienes tu Token de acceso?
Para consumir este servicio necesitas un Token vigente. Consulta el servicio de Login para aprender cómo obtenerlo.

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

Si tu Token es válido, el sistema te devolverá una lista con todos los asesores registrados (excluyendo usuarios internos del sistema). Los asesores se devuelven ordenados alfabéticamente por nombre. La respuesta se verá similar a esta:

[
    {
        "id": "3",
        "documento": "52498731",
        "nombre": "ANDREA MILENA CASTRO ROJAS",
        "telefono": "3104567890",
        "email": "andrea.castro@miredinmobiliaria.com",
        "path_photo": "https://mi-inmobiliaria.nuby.app/pic/usuarios/foto_andrea_castro.jpg"
    },
    {
        "id": "7",
        "documento": "80213654",
        "nombre": "CARLOS EDUARDO PINEDA VARGAS",
        "telefono": "3209876543",
        "email": "carlos.pineda@miredinmobiliaria.com",
        "path_photo": "https://mi-inmobiliaria.nuby.app/pic/usuarios/foto_carlos_pineda.jpg"
    },
    {
        "id": "12",
        "documento": "1098745231",
        "nombre": "JULIANA PATRICIA RÍOS MENDOZA",
        "telefono": "3156781234",
        "email": "juliana.rios@miredinmobiliaria.com",
        "path_photo": "https://mi-inmobiliaria.nuby.app/pic/iconos/user_photo.png"
    }
]

Descripción de cada campo:

Campo Tipo Descripción
id string Identificador único del usuario en el sistema.
documento string Número de documento de identidad del asesor.
nombre string Nombre completo del asesor (compuesto por primer nombre, segundo nombre, primer apellido y segundo apellido).
telefono string Número de teléfono del asesor.
email string Dirección de correo electrónico del asesor.
path_photo string URL completa de la fotografía del asesor. Si el asesor no tiene foto registrada, se devuelve la imagen genérica del sistema.

Nota sobre la respuesta
El listado excluye automáticamente los usuarios internos del sistema (cuentas de administración y soporte). Solo se devuelven los asesores reales de la inmobiliaria. Si no hay asesores registrados, la respuesta será un arreglo vacío [].


4. Seguridad y Posibles Errores

¡Tu pase tiene fecha de caducidad!

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 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:

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

Otros posibles errores:

Código HTTP Descripción
400 Token no enviado o con formato incorrecto. Asegúrate de incluir el encabezado Authorization: Bearer TU_TOKEN.
401 Token expirado o inválido. Solicita uno nuevo a través del servicio de Login.
403 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}'."

5. Ejemplos de integración

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

cURL
curl -X GET "https://{{instancia}}/service/v2/public/agents" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer TU_TOKEN_AQUI"
PHP
<?php

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

$url = "https://{$instance}/service/v2/public/agents";

$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) {
        $asesores = json_decode($response, true);
        echo "Asesores encontrados: " . count($asesores) . "\n";
        foreach ($asesores as $asesor) {
            echo "  [{$asesor['id']}] {$asesor['nombre']} - {$asesor['email']}\n";
        }
    } else {
        echo "Error al consultar los asesores.\n";
        echo $response . "\n";
    }
}
curl_close($ch);

?>
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 Login

# 2. Prepara la dirección de la petición
url = f"https://{instancia}/service/v2/public/agents"

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:
        asesores = response.json()
        print(f"Asesores encontrados: {len(asesores)}")
        for asesor in asesores:
            print(f"  [{asesor['id']}] {asesor['nombre']} - {asesor['email']}")
    else:
        print("Error al consultar los asesores.")
        print(f"Detalle del error: {response.text}")

except Exception as e:
    print(f"Ocurrió un error de conexión: {e}")
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 Login

// 2. Prepara la dirección de la petición
const url = `https://${instancia}/service/v2/public/agents`;

// 3. Función para consultar los asesores
async function consultarAsesores() {
    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 asesores = await response.json();
            console.log(`Asesores encontrados: ${asesores.length}`);
            asesores.forEach(asesor => {
                console.log(`  [${asesor.id}] ${asesor.nombre} - ${asesor.email}`);
            });
        } else {
            console.log('Error al consultar los asesores.');
            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
consultarAsesores();
Power Query M (Excel / Power BI)
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 Login

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

    // 3. Envía la petición GET
    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", "documento", "nombre", "telefono", "email", "path_photo"},
        {"ID", "Documento", "Nombre", "Telefono", "Email", "Foto"})
in
    expandido
Asesores

Buscar Asesor por Documento

Permite obtener la información de un asesor específico a partir de su número de documento de identidad. La respuesta contiene los datos básicos de contacto del asesor: documento, nombre completo, teléfono, correo electrónico y fotografía.

¿Para qué sirve este servicio?
Úsalo cuando ya conoces el número de documento del asesor y necesitas consultar su información detallada. Es ideal para mostrar la ficha de un agente en particular, verificar datos de un asesor asignado a una propiedad o sincronizar la información de un agente puntual con tu sistema externo.


1. El Endpoint (La dirección web)

Apunta tu sistema a la siguiente dirección. Recuerda reemplazar {{instancia}} por la dirección web completa que utilizas para ingresar a tu plataforma, y {{document}} por el número de documento de identidad del asesor que deseas consultar.

GET https://{{instancia}}/service/v2/public/agents/{{document}}

¿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.

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

Este servicio no requiere cuerpo en la petición. Solo necesitas construir la URL con el número de documento del asesor como parte de la ruta e incluir los encabezados requeridos:

Método GET
Content-Type application/json
Authorization Bearer token, Token obtenido al consumir el servicio Login

¿Aún no tienes tu Token de acceso?
Para consumir este servicio necesitas un Token vigente. Consulta el servicio de Login para aprender cómo obtenerlo.

Parámetro de ruta:

Parámetro Tipo Requerido Descripción
document string Número de documento de identidad del asesor que se desea consultar. Se envía directamente en la URL.

Ejemplo de petición:

GET https://mi-inmobiliaria.nuby.app/service/v2/public/agents/52498731

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

Si tu Token es válido y el documento corresponde a un asesor registrado, el sistema te devolverá un objeto JSON con la información del asesor. La respuesta se verá similar a esta:

{
    "id": "3",
    "documento": "52498731",
    "nombre": "ANDREA MILENA CASTRO ROJAS",
    "telefono": "3104567890",
    "email": "andrea.castro@miredinmobiliaria.com",
    "path_photo": "https://mi-inmobiliaria.nuby.app/pic/usuarios/foto_andrea_castro.jpg"
}

Descripción de cada campo:

Campo Tipo Descripción
id string Identificador único del usuario en el sistema.
documento string Número de documento de identidad del asesor.
nombre string Nombre completo del asesor (compuesto por primer nombre, segundo nombre, primer apellido y segundo apellido).
telefono string Número de teléfono del asesor.
email string Dirección de correo electrónico del asesor.
path_photo string URL completa de la fotografía del asesor. Si el asesor no tiene foto registrada, se devuelve la imagen genérica del sistema.

Importante: asesor no encontrado
Cuando el documento no corresponde a ningún asesor registrado, el sistema no devuelve un error. En su lugar, responde con un HTTP 200 y un arreglo vacío:

[]

Asegúrate de validar en tu integración si la respuesta es un arreglo vacío [] para manejar correctamente el caso en que el asesor no exista.


4. Seguridad y Posibles Errores

¡Tu pase tiene fecha de caducidad!

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 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:

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

Otros posibles errores:

Código HTTP Descripción
200 Respuesta exitosa. Contiene el objeto JSON del asesor, o un arreglo vacío [] si no se encontró ningún asesor con ese documento.
400 Token no enviado o con formato incorrecto. Asegúrate de incluir el encabezado Authorization: Bearer TU_TOKEN.
401 Token expirado o inválido. Solicita uno nuevo a través del servicio de Login.
403 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}'."

5. Ejemplos de integración

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

cURL
# Consultar asesor por documento
curl -X GET "https://{{instancia}}/service/v2/public/agents/52498731" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer TU_TOKEN_AQUI"
PHP
<?php

$instance = 'tu_instancia'; // Reemplaza con tu instancia real
$token = 'TU_TOKEN_AQUI'; // Token obtenido del servicio Login
$documento = '52498731'; // Documento del asesor a consultar

$url = "https://{$instance}/service/v2/public/agents/{$documento}";

$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) {
        $asesor = json_decode($response, true);

        if (!empty($asesor)) {
            echo "Asesor encontrado:\n";
            echo "  ID: {$asesor['id']}\n";
            echo "  Nombre: {$asesor['nombre']}\n";
            echo "  Email: {$asesor['email']}\n";
            echo "  Teléfono: {$asesor['telefono']}\n";
        } else {
            echo "No se encontró ningún asesor con el documento {$documento}.\n";
        }
    } else {
        echo "Error al consultar el asesor.\n";
        echo $response . "\n";
    }
}
curl_close($ch);

?>
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 Login
documento = '52498731' # Documento del asesor a consultar

# 2. Prepara la dirección de la petición
url = f"https://{instancia}/service/v2/public/agents/{documento}"

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:
        asesor = response.json()

        if asesor:
            print(f"Asesor encontrado:")
            print(f"  ID: {asesor['id']}")
            print(f"  Nombre: {asesor['nombre']}")
            print(f"  Email: {asesor['email']}")
            print(f"  Teléfono: {asesor['telefono']}")
        else:
            print(f"No se encontró ningún asesor con el documento {documento}.")
    else:
        print("Error al consultar el asesor.")
        print(f"Detalle del error: {response.text}")

except Exception as e:
    print(f"Ocurrió un error de conexión: {e}")
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 Login
const documento = '52498731'; // Documento del asesor a consultar

// 2. Prepara la dirección de la petición
const url = `https://${instancia}/service/v2/public/agents/${documento}`;

// 3. Función para consultar el asesor
async function consultarAsesor() {
    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 asesor = await response.json();

            if (asesor && !Array.isArray(asesor)) {
                console.log(`Asesor encontrado:`);
                console.log(`  ID: ${asesor.id}`);
                console.log(`  Nombre: ${asesor.nombre}`);
                console.log(`  Email: ${asesor.email}`);
                console.log(`  Teléfono: ${asesor.telefono}`);
            } else {
                console.log(`No se encontró ningún asesor con el documento ${documento}.`);
            }
        } else {
            console.log('Error al consultar el asesor.');
            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
consultarAsesor();
Power Query M (Excel / Power BI)
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 Login
    documento = "52498731", // Documento del asesor a consultar

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

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

    // 4. Decodifica la respuesta JSON y conviértela en registro
    jsonResponse = Json.Document(response),
    resultado = Record.ToTable(jsonResponse),
    expandido = Table.Pivot(resultado, List.Distinct(resultado[Name]), "Name", "Value")
in
    expandido

Facturas

Bienvenido a la caja registradora virtual de tu inmobiliaria. En esta sección centralizamos las conexiones para que tus plataformas externas gestionen automáticamente todo el ciclo de facturación y cobros.

¿Qué puedes lograr en este módulo?

1. Consulta sincronizada: Tus aplicaciones podrán revisar el historial de cuentas, buscar saldos pendientes por cliente y obtener enlaces seguros para descargar documentos en PDF. Además, tendrás acceso a configuraciones clave como tus resoluciones de facturación y medios de pago habilitados.

2. Acción directa sobre tu cartera: ¡Esta sección no es de solo lectura! Si recibes un pago en una plataforma externa, tu sistema puede reportarnos el monto y la fecha. Nosotros nos encargamos del trabajo pesado: calculamos el saldo, registramos el abono (ya sea parcial o total), generamos el recibo de ingreso y creamos el documento contable de forma automática.

Explora las opciones a continuación para automatizar tus cobros y mantener las finanzas de tus clientes siempre al día.

Facturas

Listar Facturas

Permite obtener la lista paginada de todas las facturas registradas en el sistema. Cada elemento incluye el número de factura, resolución, fechas, valor total, saldo pendiente, tercero facturado, estado, información DIAN y datos de auditoría.

¿Para qué sirve este servicio?
Úsalo para sincronizar la información de facturación con tu sistema externo, generar reportes de cartera, alimentar dashboards con indicadores de facturación, validar el estado de cobro de los contratos o exportar la información a Excel y Power BI.


1. El Endpoint (La dirección web)

Apunta tu sistema a la siguiente dirección. Recuerda reemplazar {{instancia}} por la dirección web completa que utilizas para ingresar a tu plataforma.

GET https://{{instancia}}/service/v2/public/invoices/list

¿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.

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

Este servicio no requiere cuerpo en la petición. Envía los encabezados requeridos y opcionalmente los parámetros de paginación en la URL:

Método GET
Content-Type application/json
Authorization Bearer token, Token obtenido al consumir el servicio Login

¿Aún no tienes tu Token de acceso?
Para consumir este servicio necesitas un Token vigente. Consulta el servicio de Login para aprender cómo obtenerlo.

Parámetros de consulta (query string):

Parámetro Tipo Requerido Por defecto Descripción
page integer No 1 Número de página de resultados que se desea recuperar. Debe ser un número positivo.
page_size integer No 10 Número máximo de facturas por página. Debe ser un número positivo. Valor máximo permitido: 1000.

Ejemplos de petición:

GET https://mi-inmobiliaria.nuby.app/service/v2/public/invoices/list
GET https://mi-inmobiliaria.nuby.app/service/v2/public/invoices/list?page=2
GET https://mi-inmobiliaria.nuby.app/service/v2/public/invoices/list?page_size=50
GET https://mi-inmobiliaria.nuby.app/service/v2/public/invoices/list?page=3&page_size=100

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

Si tu Token es válido, el sistema te devolverá un objeto JSON con el estado de la respuesta, el listado de facturas y la información de paginación. Los resultados están ordenados por fecha de factura descendente (más recientes primero). La respuesta se verá similar a esta:

{
    "status": 200,
    "message": null,
    "body": [
        {
            "factura_id": 15230,
            "factura_numero": 8745,
            "resolucion": "FECO - 18764000002851",
            "fecha_factura": "2025-04-01",
            "fecha_vencimiento": "2025-04-06",
            "valor_total": "2850000.00",
            "saldo": "2850000.00",
            "documento_tercero": "80213654",
            "nombre_tercero": "CARLOS EDUARDO PINEDA VARGAS",
            "estado": "Facturada",
            "estado_dian": "Aceptada",
            "estado_cliente_dian": "Recibida",
            "notas": 0,
            "creado_por": "Sandra",
            "fecha_envio_dian": "2025-04-01 08:30:15",
            "fecha_creacion": "2025-04-01 07:45:22"
        },
        {
            "factura_id": 15229,
            "factura_numero": 8744,
            "resolucion": "FECO - 18764000002851",
            "fecha_factura": "2025-04-01",
            "fecha_vencimiento": "2025-04-06",
            "valor_total": "4500000.00",
            "saldo": "0.00",
            "documento_tercero": "1098745231",
            "nombre_tercero": "JULIANA PATRICIA RÍOS MENDOZA",
            "estado": "Pagada",
            "estado_dian": "Aceptada",
            "estado_cliente_dian": "Recibida",
            "notas": 0,
            "creado_por": "Sandra",
            "fecha_envio_dian": "2025-04-01 08:31:02",
            "fecha_creacion": "2025-04-01 07:46:10"
        },
        {
            "factura_id": 15210,
            "factura_numero": 8730,
            "resolucion": "0 - 18764000002851",
            "fecha_factura": "2025-03-01",
            "fecha_vencimiento": "2025-03-06",
            "valor_total": "1200000.00",
            "saldo": "1200000.00",
            "documento_tercero": "43876123",
            "nombre_tercero": "DIANA MARCELA OSPINA VELÁSQUEZ",
            "estado": "Facturada",
            "estado_dian": null,
            "estado_cliente_dian": null,
            "notas": 1,
            "creado_por": "Administrador",
            "fecha_envio_dian": null,
            "fecha_creacion": "2025-03-01 09:12:33"
        },
        {
            "factura_id": 14850,
            "factura_numero": 8520,
            "resolucion": "FECO - 18764000002851",
            "fecha_factura": "2025-02-01",
            "fecha_vencimiento": "2025-02-06",
            "valor_total": "3950000.00",
            "saldo": "3950000.00",
            "documento_tercero": "900456789",
            "nombre_tercero": "INVERSIONES HORIZONTE S.A.S.",
            "estado": "Anulada por NC",
            "estado_dian": "Aceptada",
            "estado_cliente_dian": null,
            "notas": 1,
            "creado_por": "Sandra",
            "fecha_envio_dian": "2025-02-01 10:05:44",
            "fecha_creacion": "2025-02-01 08:20:15"
        }
    ],
    "pagination": {
        "total_records": 15230,
        "total_pages": 305,
        "current_page": 1,
        "page_size": 50,
        "current_page_records": 4,
        "has_next_page": true,
        "has_previous_page": false
    }
}
Estructura principal de la respuesta
Campo Tipo Descripción
status integer Código del estado de la respuesta. 200 para exitoso, 400 para error de validación, 500 para error interno.
message string | null Cuando la respuesta es exitosa vale null. Si no se encuentran facturas, contiene el mensaje informativo. Si hay error, describe el problema.
body array | null Listado de facturas devueltas. Arreglo vacío [] si no hay resultados. null en caso de error.
pagination object | null Información de paginación para recorrer los resultados. null en caso de error.
Campos de cada factura (body)

Cada elemento dentro del arreglo body contiene las siguientes claves:

Campo Tipo Descripción
factura_id integer Identificador único de la factura en el sistema.
factura_numero integer Número consecutivo de la factura.
resolucion string Prefijo y número de la resolución de facturación en formato PREFIJO - NÚMERO (ej. "FECO - 18764000002851").
fecha_factura string Fecha de emisión de la factura en formato YYYY-MM-DD.
fecha_vencimiento string Fecha de vencimiento de la factura en formato YYYY-MM-DD.
valor_total string Valor total de la factura con decimales (ej. "2850000.00").
saldo string Saldo pendiente de pago de la factura con decimales (ej. "0.00" cuando está pagada).
documento_tercero string Número de documento de identidad del tercero/cliente facturado.
nombre_tercero string Nombre completo del tercero/cliente facturado.
estado string Estado textual de la factura. Valores posibles: Facturada, Anulada, Pagada, Borrador, Anulada por NC, Contabilizada.
estado_dian string | null Estado de la factura en la DIAN cuando es factura electrónica (ej. "Aceptada"). null si no aplica o no se ha enviado.
estado_cliente_dian string | null Estado de aceptación/rechazo del cliente ante la DIAN cuando es factura electrónica. null si no aplica.
notas integer Cantidad de notas débito o crédito asociadas a la factura.
creado_por string Nombre del usuario que creó la factura en el sistema.
fecha_envio_dian string | null Fecha y hora de envío de la factura a la DIAN en formato YYYY-MM-DD HH:MM:SS. null si no se ha enviado.
fecha_creacion string Fecha y hora de creación del registro en formato YYYY-MM-DD HH:MM:SS.
Campos de paginación (pagination)

El objeto pagination contiene las siguientes claves:

Campo Tipo Descripción
total_records integer Total de facturas registradas en el sistema.
total_pages integer Cantidad total de páginas disponibles (total de registros dividido por el tamaño de página).
current_page integer Número de la página actual consultada.
page_size integer Tamaño de la página (cantidad de registros solicitados por consulta).
current_page_records integer Cantidad de registros efectivamente devueltos en la página actual.
has_next_page boolean true si existen páginas posteriores que se pueden consultar.
has_previous_page boolean true si existen páginas anteriores que se pueden consultar.

Nota sobre facturas sin resultados
Si no existen facturas registradas en el sistema, la respuesta tendrá HTTP 200 con body vacío ([]), un message informativo: "No se encontraron facturas en el sistema." y los valores de paginación en cero.


4. Seguridad y Posibles Errores

¡Tu pase tiene fecha de caducidad!

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 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:

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

Si alguno de los parámetros de paginación no cumple con las validaciones, el sistema devolverá un error 400. Por ejemplo:

{
    "status": 400,
    "message": "El parámetro \"page_size\" debe ser un número positivo.",
    "body": null,
    "pagination": null
}

Posibles errores:

Código HTTP Descripción
400 Token faltante o inválido. Posibles causas:
— No se envió el encabezado Authorization. Mensaje: "JWT Token required."
— El encabezado no tiene el formato Bearer {token}. Mensaje: "JWT Token not send."
— El token no fue encontrado en el sistema. Mensaje: "JWT Token not found."

Parámetros inválidos. Posibles causas:
page no es numérico o no es positivo. Mensaje: "El parámetro \"page\" debe ser un número positivo."
page_size no es numérico o no es positivo. Mensaje: "El parámetro \"page_size\" debe ser un número positivo."
401 El token ha expirado. Debes generar uno nuevo consumiendo el servicio de Login. Mensaje: "JWT Token expired."
403 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}'."
500 Error interno del servidor al procesar la consulta de facturas. Mensaje: "Error interno del servidor al obtener las facturas."

5. Ejemplos de integración

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

cURL
# Listar facturas con paginación por defecto
curl -X GET "https://{{instancia}}/service/v2/public/invoices/list" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer TU_TOKEN_AQUI"

# Listar facturas página 3 con 100 registros por página
curl -X GET "https://{{instancia}}/service/v2/public/invoices/list?page=3&page_size=100" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer TU_TOKEN_AQUI"
PHP
<?php

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

// Parámetros de paginación
$page = 1;
$page_size = 50;

$queryParams = http_build_query([
    'page' => $page,
    'page_size' => $page_size
]);

$url = "https://{$instance}/service/v2/public/invoices/list?{$queryParams}";

$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";

    $info = json_decode($response, true);
    $body = $info['body'] ?? [];

    if ($http_code === 200 && !empty($body)) {
        $pagination = $info['pagination'];
        echo "Facturas encontradas: {$pagination['total_records']} (página {$pagination['current_page']} de {$pagination['total_pages']})\n";

        foreach ($body as $factura) {
            echo "  Factura #{$factura['factura_numero']} - {$factura['nombre_tercero']} - {$factura['estado']} - Total: \${$factura['valor_total']} - Saldo: \${$factura['saldo']}\n";
        }
    } else {
        echo "Mensaje: " . ($info['message'] ?? 'Sin resultados') . "\n";
    }
}
curl_close($ch);

?>
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 Login

# 2. Prepara la dirección y los parámetros
url = f"https://{instancia}/service/v2/public/invoices/list"

params = {
    "page": 1,
    "page_size": 50
}

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, params=params, headers=headers)

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

    if response.status_code == 200:
        info = response.json()
        body = info.get('body', [])
        pagination = info.get('pagination', {})

        if body:
            print(f"Facturas: {pagination['total_records']} total (página {pagination['current_page']} de {pagination['total_pages']})")
            for factura in body:
                print(f"  #{factura['factura_numero']} - {factura['nombre_tercero']} - {factura['estado']} - Total: ${factura['valor_total']} - Saldo: ${factura['saldo']}")
        else:
            print(f"Mensaje: {info.get('message', 'Sin resultados')}")
    else:
        print("Error al consultar las facturas.")
        print(f"Detalle del error: {response.text}")

except Exception as e:
    print(f"Ocurrió un error de conexión: {e}")
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 Login

// 2. Prepara la dirección con parámetros
const params = new URLSearchParams({
    page: 1,
    page_size: 50
});

const url = `https://${instancia}/service/v2/public/invoices/list?${params}`;

// 3. Función para consultar las facturas
async function consultarFacturas() {
    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 info = await response.json();
            const body = info.body || [];
            const pagination = info.pagination || {};

            if (body.length > 0) {
                console.log(`Facturas: ${pagination.total_records} total (página ${pagination.current_page} de ${pagination.total_pages})`);
                body.forEach(factura => {
                    console.log(`  #${factura.factura_numero} - ${factura.nombre_tercero} - ${factura.estado} - Total: $${factura.valor_total} - Saldo: $${factura.saldo}`);
                });
            } else {
                console.log(`Mensaje: ${info.message || 'Sin resultados'}`);
            }
        } else {
            console.log('Error al consultar las facturas.');
            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
consultarFacturas();
Power Query M (Excel / Power BI)
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 Login

    // 2. Prepara la dirección de la petición con parámetros
    url = "https://" & instancia & "/service/v2/public/invoices/list?page=1&page_size=1000",

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

    // 4. Decodifica la respuesta JSON
    jsonResponse = Json.Document(response),
    body = jsonResponse[body],

    // 5. Convierte el listado en tabla
    tabla = Table.FromList(body, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
    expandido = Table.ExpandRecordColumn(tabla, "Column1",
        {"factura_id", "factura_numero", "resolucion", "fecha_factura", "fecha_vencimiento", "valor_total", "saldo", "documento_tercero", "nombre_tercero", "estado", "estado_dian", "notas", "creado_por", "fecha_creacion"},
        {"FacturaID", "Numero", "Resolucion", "FechaFactura", "FechaVencimiento", "ValorTotal", "Saldo", "DocTercero", "NombreTercero", "Estado", "EstadoDian", "Notas", "CreadoPor", "FechaCreacion"})
in
    expandido
Facturas

Registrar Pago de Factura

Permite registrar el pago de una factura existente en el sistema. Si no se especifica la forma de pago, el sistema intentará determinarla automáticamente basándose en el cliente OAuth2 autenticado o utilizará la forma de pago por defecto configurada (Consignación bancaria).

Endpoint: https://{{instancia}}.arrendasoft.co/service/v2/public/invoices/register-payment

{{instancia}}: Hace referencia a la instancia de cada inmobiliaria.

Petición

Método POST
Content-Type application/json
Authorization Bearer token, Token obtenido al consumir el servicio Login
Parámetros del Body (JSON)
Parámetro Tipo Obligatorio Valor por defecto Descripción
factura_id integer - Identificador único de la factura a la cual se registrará el pago. Debe ser un número entero positivo y coincidir con una factura en el sistema.
monto float - Monto del pago a registrar. Debe ser un número positivo y no puede exceder el saldo pendiente de la factura.
fecha_pago string -
Fecha y hora en que se realizó el pago. Formato: Y-m-d H:i:s (ej: 2026-02-05 14:30:00).
forma_pago_id integer No Auto ID de la forma de pago. Si no se proporciona, se determina automáticamente según el cliente o la configuración por defecto.
n_comprobante string No - Número de comprobante o referencia del pago realizado. Máximo 100 caracteres. Solo se permiten letras, números, guiones (-), guiones bajos (_), puntos (.) y espacios.

Ejemplo de petición (Body JSON)

{
    "factura_id": 366,
    "monto": 50000,
    "fecha_pago": "2026-02-05 14:30:00",
    "forma_pago_id": 1,
    "n_comprobante": "REF123456"
}

Ejemplo mínimo (solo campos requeridos):

{
    "factura_id": 366,
    "monto": 50000,
    "fecha_pago": "2026-02-05 10:00:00"
}

Respuestas

Respuesta Exitosa (200)

Cuando el pago se registra correctamente, la respuesta incluye los detalles completos del pago registrado, incluyendo los IDs de los registros generados en el sistema (pago, recibo de ingreso y documento contable) así como el estado actualizado de la factura.

{
    "success": true,
    "status": 200,
    "message": "Pago registrado exitosamente.",
    "body": {
        "factura_id": 366,
        "pago_id": 142,
        "recibo_id": 589,
        "documento_contable_id": 1023,
        "monto_pagado": 50000,
        "fecha_pago": "2026-02-05 14:30:00",
        "forma_pago_id": 1,
        "forma_pago": "Consignación bancaria",
        "n_comprobante": "REF123456",
        "saldo_anterior": 150000,
        "saldo_actual": 100000,
        "estado_factura": "Facturada",
        "gateway": null,
        "client_name": "MiAplicacion"
    }
}
Claves y Descripciones del JSON de Respuesta
Clave Tipo Descripción

success

Booleano Indica si la operación fue exitosa (true) o fallida (false).
status Entero Código HTTP de la respuesta: 200 (exitoso), 400 (error de validación), 404 (no encontrado), 422 (error de negocio), 500 (error interno).
message Texto Mensaje descriptivo del resultado de la operación.
body Objeto Contiene los detalles del pago registrado cuando la operación es exitosa. Es nulo cuando hay error.
errors Array Lista de errores de validación. Solo presente cuando status es 400.
Cuerpo de Respuesta Exitosa (body)

Cuando la operación es exitosa, el objeto body contiene las siguientes claves:

Clave Tipo Descripción
factura_id Entero ID de la factura a la que se aplicó el pago.
pago_id Entero ID del registro de pago creado en el sistema.
recibo_id Entero ID del recibo de caja generado.
documento_contable_id Entero ID del documento contable creado.
monto_pagado Numérico Monto del pago registrado.
fecha_pago Texto Fecha y hora del pago en formato Y-m-d H:i:s.
forma_pago_id Entero ID de la forma de pago utilizada.
forma_pago Texto Nombre de la forma de pago utilizada.
n_comprobante Texto Número de comprobante o referencia del pago. Máximo 100 caracteres. Nulo si no se proporcionó.
saldo_anterior Numérico Saldo de la factura antes de aplicar el pago.
saldo_actual Numérico Saldo de la factura después de aplicar el pago. Si es 0, la factura quedó totalmente pagada.
estado_factura Texto Estado de la factura después de aplicar el pago (ej: "Facturada", "Pagada").
gateway Texto Nombre de la pasarela de pago si aplica. Nulo si no se usó pasarela.
client_name Texto Nombre del cliente OAuth autenticado que realizó la petición.

Respuestas de Error

Error de Validación (400)

Se retorna cuando los parámetros enviados no cumplen con las validaciones requeridas.

{
    "success": false,
    "status": 400,
    "message": "Errores de validación",
    "body": null,
    "errors": [
        "El parámetro \"factura_id\" es requerido.",
        "El parámetro \"monto\" debe ser un número positivo.",
        "El parámetro \"fecha_pago\" debe tener el formato Y-m-d H:i:s (ej: 2026-02-02 14:30:00).",
        "El parámetro \"n_comprobante\" no puede exceder 100 caracteres.",
        "El parámetro \"n_comprobante\" contiene caracteres no permitidos. Solo se aceptan letras, números, guiones, guiones bajos, puntos y espacios."
    ]
}
Factura No Encontrada (404)

Se retorna cuando no existe una factura con el ID proporcionado.

{
    "success": false,
    "status": 404,
    "message": "No se encontró la factura con el ID proporcionado.",
    "body": null
}
Error de Negocio (422)

Se retorna cuando la factura existe pero no puede recibir el pago por razones de negocio.

Factura no activa:

{
    "success": false,
    "status": 422,
    "message": "La factura no está en estado activo/pendiente de pago. Estado actual: Pagada",
    "body": null
}

Monto excede saldo:

{
    "success": false,
    "status": 422,
    "message": "El monto a pagar (100000) excede el saldo de la factura (50000).",
    "body": null
}

Forma de pago no determinada:

{
    "success": false,
    "status": 422,
    "message": "No se pudo determinar la forma de pago automáticamente. Por favor especifique el parámetro \"forma_pago_id\".",
    "body": null
}

Factura sin detalles:

{
    "success": false,
    "status": 422,
    "message": "La factura no tiene detalles asociados. No es posible registrar el pago.",
    "body": null
}

Forma de pago sin cuenta contable:

{
    "success": false,
    "status": 422,
    "message": "La forma de pago seleccionada no tiene una cuenta contable configurada. No es posible registrar el pago.",
    "body": null
}

Periodo contable no activo:

{
    "success": false,
    "status": 422,
    "message": "No existe un periodo contable activo para la fecha 2026-01-15. Verifique que el periodo esté abierto en el módulo de contabilidad.",
    "body": null
}
Error Interno (500)

Se retorna cuando ocurre un error inesperado en el servidor o cuando el proceso de registro del pago falla.

Error general:

{
    "success": false,
    "status": 500,
    "message": "Error interno del servidor al registrar el pago.",
    "body": null
}

Error al generar recibo de ingreso:

{
    "success": false,
    "status": 500,
    "message": "Error al crear el recibo de ingreso para el pago de la factura.",
    "body": null
}

Pago procesado sin confirmación de ID:

{
    "success": false,
    "status": 500,
    "message": "El pago se procesó pero no se pudo obtener el ID del registro de pago. Verifique manualmente en el sistema.",
    "body": null
}

Códigos de Respuesta HTTP

Código Descripción
200 Pago registrado exitosamente. La respuesta incluye los IDs del pago, recibo y documento contable generados.
400 Error de validación en los parámetros enviados, forma de pago inexistente, o n_comprobante con formato inválido.
404 La factura especificada no existe.
422
Error de regla de negocio: factura no activa, monto excede saldo, factura sin detalles, forma de pago sin cuenta contable, periodo contable no activo, o no se pudo determinar forma de pago.
500 Error interno del servidor, error al generar recibo de ingreso, o pago procesado sin confirmación de ID.

Notas Importantes

  1. Determinación Automática de Forma de Pago: Si no se proporciona forma_pago_id, el sistema intentará:

    • Primero, determinar la forma de pago basándose en el cliente OAuth autenticado (integración con pasarelas de pago).
    • Si no encuentra una pasarela asociada, buscará la forma de pago por defecto configurada con código DIAN 42 (Consignación bancaria).
  2. Estados de Factura: Solo se pueden registrar pagos en facturas con estado "Facturada" (estado_id = 1). Los estados posibles son:

    • 1: Facturada (permite pagos)
    • 2: Anulada
    • 3: Pagada
    • 5: Borrador
    • 6: Anulada por NC
  3. Pagos Parciales: El sistema permite pagos parciales. El monto debe ser mayor a cero y no puede exceder el saldo pendiente de la factura. Tras un pago parcial, la respuesta incluye `saldo_anterior` y `saldo_actual` para verificar la diferencia.

  4. Formas de Pago: Para obtener el listado de formas de pago disponibles, consulte el endpoint Listar Formas de Pago.

  5. Verificación del Pago: La respuesta exitosa incluye `pago_id`, `recibo_id` y `documento_contable_id` que permiten verificar que el pago, el recibo de ingreso y el asiento contable se crearon correctamente en el sistema.

  6. Estado de la Factura: El campo `estado_factura` en la respuesta indica el estado actualizado de la factura tras el pago. Si el saldo queda en 0, la factura pasará automáticamente a estado "Pagada".

  7. Validación de n_comprobante: El número de comprobante tiene las siguientes restricciones:

    • Máximo 100 caracteres.

    • Solo se permiten: letras (a-z, A-Z), números (0-9), guiones (-), guiones bajos (\_), puntos (.) y espacios.

    • No se permiten caracteres especiales como comillas, signos de mayor/menor, punto y coma, etc.

  8. Periodo Contable: La fecha del pago debe corresponder a un periodo contable activo en el sistema. Si la fecha está fuera de un periodo activo, se retornará un error 422 indicando que debe verificarse la configuración de periodos en el módulo de contabilidad.

  9. Validación de forma_pago_id: Si se proporciona el parámetro `forma_pago_id`, debe ser un número entero positivo.

Ejemplos

Curl
curl -X POST "https://{{instancia}}.arrendasoft.co/service/v2/public/invoices/register-payment" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_AUTHENTICATION_TOKEN" \
  -d '{
    "factura_id": 366,
    "monto": 50000,
    "fecha_pago": "2026-02-05 10:00:00",
    "n_comprobante": "REF123456"
  }'
PHP Curl
<?php

$instance = 'your_instance'; // Reemplace con su instancia actual
$token = 'YOUR_AUTHENTICATION_TOKEN'; // Reemplace con el token obtenido desde el servicio de login

// Datos del pago a registrar
$paymentData = [
    'factura_id' => 366,
    'monto' => 50000,
    'fecha_pago' => '2026-02-05 14:30:00',
    'forma_pago_id' => 1, // Opcional
    'n_comprobante' => 'REF123456' // Opcional
];

$url = "https://{$instance}.arrendasoft.co/service/v2/public/invoices/register-payment";

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($paymentData));
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 "HTTP Status Code: " . $http_code . "\n";
    echo "Response: " . $response . "\n";
    
    // Procesar la respuesta
    $result = json_decode($response, true);
    
    if ($result['success']) {
        echo "Pago registrado exitosamente.\n";
        echo "Factura: " . $result['body']['factura_id'] . "\n";
        echo "Pago ID: " . $result['body']['pago_id'] . "\n";
        echo "Recibo ID: " . $result['body']['recibo_id'] . "\n";
        echo "Documento Contable ID: " . $result['body']['documento_contable_id'] . "\n";
        echo "Monto pagado: " . $result['body']['monto_pagado'] . "\n";
        echo "Forma de pago: " . $result['body']['forma_pago'] . "\n";
        echo "Saldo anterior: " . $result['body']['saldo_anterior'] . "\n";
        echo "Saldo actual: " . $result['body']['saldo_actual'] . "\n";
        echo "Estado factura: " . $result['body']['estado_factura'] . "\n";
    } else {
        echo "Error: " . $result['message'] . "\n";
        if (isset($result['errors'])) {
            foreach ($result['errors'] as $error) {
                echo "- " . $error . "\n";
            }
        }
    }
}
curl_close($ch);

?>
JavaScript Fetch
const instance = 'your_instance'; // Reemplace con su instancia actual
const token = 'YOUR_AUTHENTICATION_TOKEN'; // Reemplace con el token obtenido

const paymentData = {
    factura_id: 366,
    monto: 50000,
    fecha_pago: '2026-02-05 14:30:00',
    n_comprobante: 'REF123456'
};

fetch(`https://${instance}.arrendasoft.co/service/v2/public/invoices/register-payment`, {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${token}`
    },
    body: JSON.stringify(paymentData)
})
.then(response => response.json())
.then(data => {
    if (data.success) {
        console.log('Pago registrado exitosamente');
        console.log('Factura:', data.body.factura_id);
        console.log('Pago ID:', data.body.pago_id);
        console.log('Recibo ID:', data.body.recibo_id);
        console.log('Documento Contable ID:', data.body.documento_contable_id);
        console.log('Monto pagado:', data.body.monto_pagado);
        console.log('Forma de pago:', data.body.forma_pago);
        console.log('Saldo anterior:', data.body.saldo_anterior);
        console.log('Saldo actual:', data.body.saldo_actual);
        console.log('Estado factura:', data.body.estado_factura);
    } else {
        console.error('Error:', data.message);
        if (data.errors) {
            data.errors.forEach(error => console.error('-', error));
        }
    }
})
.catch(error => console.error('Error de conexión:', error));

Facturas

Listar Formas de Pago

Permite obtener las formas de pago configuradas de la inmobiliaria. Solo devuelve las formas de pago que tengan una cuenta contable (PUC) relacionada.

Endpoint: https://{{instancia}}.arrendasoft.co/service/v2/public/invoices/payment-methods

{{instancia}}: Hace referencia a la instancia de cada inmobiliaria.

Petición

Método GET
Content-Type application/json
Authorization Bearer token, Token obtenido al consumir el servicio Login
Parámetros
Parámetro Tipo Obligatorio Valor por defecto Descripción
codigo_dian string No - Filtra formas de pago por el código DIAN del medio de pago (ej: 42 para Consignación bancaria).
cuenta_puc string No - Filtra formas de pago por código de cuenta PUC. La búsqueda es por prefijo (ej: 1110 retorna todas las cuentas que inicien con ese código).

Ejemplos de peticiones

https://{{instancia}}.arrendasoft.co/service/v2/public/invoices/payment-methods
https://{{instancia}}.arrendasoft.co/service/v2/public/invoices/payment-methods?codigo_dian=42
https://{{instancia}}.arrendasoft.co/service/v2/public/invoices/payment-methods?cuenta_puc=1110
https://{{instancia}}.arrendasoft.co/service/v2/public/invoices/payment-methods?codigo_dian=42&cuenta_puc=1110

Respuesta

Lista de formas de pago configuradas con información del medio de pago DIAN y cuenta contable asociada.

{
    "success": true,
    "status": 200,
    "message": null,
    "body": [
        {
            "formaPagoId": 1,
            "nombre": "Consignación Bancolombia",
            "cuentaPuc": "11100501",
            "codigoDian": "42",
            "medioPago": "Consignación bancaria"
        },
        {
            "formaPagoId": 2,
            "nombre": "Transferencia Davivienda",
            "cuentaPuc": "11100502",
            "codigoDian": "31",
            "medioPago": "Transferencia débito bancaria"
        },
        {
            "formaPagoId": 3,
            "nombre": "Pago con tarjeta de crédito",
            "cuentaPuc": "11100503",
            "codigoDian": "48",
            "medioPago": "Tarjeta de crédito"
        }
    ],
    "filters_applied": null
}
Claves y Descripciones del JSON de Respuesta

Esta tabla enumera las claves presentes en el JSON principal de la respuesta y proporciona una breve descripción de cada una.

Clave Tipo Descripción
success Booleano Indica si la operación fue exitosa (true) o fallida (false).
status Entero Código HTTP de la respuesta: 200 para exitoso, 500 para error interno.
message Texto Mensaje descriptivo. Es nulo cuando hay resultados, o contiene un mensaje informativo cuando no se encontraron formas de pago.
body Array Contiene el listado de formas de pago. Es un array vacío si no hay resultados.
filters_applied Objeto Contiene los filtros que fueron aplicados en la consulta. Es nulo si no se aplicaron filtros.
Cuerpo

Cada elemento dentro de la lista body tiene las siguientes claves:

Clave Tipo Descripción
formaPagoId Entero Identificador único de la forma de pago. Use este valor para el parámetro `forma_pago_id` al registrar un pago.
nombre Texto Nombre descriptivo de la forma de pago configurada por la inmobiliaria.
cuentaPuc Texto Código de la cuenta contable (PUC) asociada a la forma de pago.
codigoDian Texto Código del medio de pago según la clasificación DIAN.
medioPago Texto Nombre del medio de pago según la clasificación DIAN.
Filtros Aplicados

El objeto filters_applied contiene los filtros que fueron utilizados en la consulta. Solo se incluye en la respuesta cuando se aplican filtros. Las posibles claves son:

Clave Tipo Descripción
codigo_dian Texto Código DIAN del medio de pago utilizado como filtro.
cuenta_puc Texto Código de cuenta PUC utilizado como filtro (búsqueda por prefijo).

Respuesta con Filtros Aplicados

{
    "success": true,
    "status": 200,
    "message": null,
    "body": [
        {
            "formaPagoId": 1,
            "nombre": "Consignación Bancolombia",
            "cuentaPuc": "11100501",
            "codigoDian": "42",
            "medioPago": "Consignación bancaria"
        }
    ],
    "filters_applied": {
        "codigo_dian": "42"
    }
}

Respuesta Sin Resultados

{
    "success": true,
    "status": 200,
    "message": "No se encontraron formas de pago con los criterios especificados.",
    "body": [],
    "filters_applied": {
        "codigo_dian": "99"
    }
}

Respuesta de Error

Error Interno (500)

Se retorna cuando ocurre un error inesperado en el servidor.

{
    "success": false,
    "status": 500,
    "message": "Error interno del servidor al obtener las formas de pago.",
    "body": null,
    "filters_applied": null
}

Códigos de Respuesta HTTP

Código Descripción
200 Consulta exitosa. El cuerpo de la respuesta contiene las formas de pago (puede ser un array vacío si no hay resultados).
500 Error interno del servidor.

Códigos DIAN de Medios de Pago

Referencia de códigos DIAN comunes para medios de pago:

Código Medio de Pago
10 Efectivo
31 Transferencia Débito
42 Consignación bancaria
47 Transferencia Débito Bancaria
48 Tarjeta Crédito
49 Tarjeta Débito

Para consultar el listado completo de códigos de medios de pago, visite la Documentación Técnica de Factura Electrónica - DIAN.

Notas Importantes

  1. Solo formas de pago configuradas: Este endpoint solo retorna las formas de pago que tengan una cuenta contable (PUC) asociada. Las formas de pago sin cuenta contable no aparecerán en los resultados.

  2. Uso con registro de pagos: El formaPagoId retornado puede usarse como valor del parámetro forma_pago_id en el endpoint Registrar Pago de Factura.

  3. Búsqueda por cuenta PUC: El filtro cuenta_puc realiza una búsqueda por prefijo, lo que permite filtrar por grupos de cuentas (ej: 1110 retorna todas las cuentas PUC que inicien con ese código).

Ejemplos

Curl
curl -X GET "https://{{instancia}}.arrendasoft.co/service/v2/public/invoices/payment-methods" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_AUTHENTICATION_TOKEN"

Con filtros:

curl -X GET "https://{{instancia}}.arrendasoft.co/service/v2/public/invoices/payment-methods?codigo_dian=42" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_AUTHENTICATION_TOKEN"
PHP Curl
<?php

$instance = 'your_instance'; // Reemplace con su instancia actual
$token = 'YOUR_AUTHENTICATION_TOKEN'; // Reemplace con el token obtenido desde el servicio de login

// Parámetros de filtro opcionales
$codigoDian = '42'; // Opcional: filtrar por código DIAN
$cuentaPuc = null;  // Opcional: filtrar por cuenta PUC

$url = "https://{$instance}.arrendasoft.co/service/v2/public/invoices/payment-methods";

// Agregar parámetros de filtro si existen
$queryParams = [];
if (!empty($codigoDian)) {
    $queryParams['codigo_dian'] = $codigoDian;
}
if (!empty($cuentaPuc)) {
    $queryParams['cuenta_puc'] = $cuentaPuc;
}
if (!empty($queryParams)) {
    $url .= '?' . http_build_query($queryParams);
}

$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 "HTTP Status Code: " . $http_code . "\n";
    echo "Response: " . $response . "\n";
    
    // Procesar la respuesta
    $result = json_decode($response, true);
    
    if ($result['success'] && !empty($result['body'])) {
        echo "Se encontraron " . count($result['body']) . " formas de pago.\n\n";
        
        foreach ($result['body'] as $formaPago) {
            echo "ID: " . $formaPago['formaPagoId'] . "\n";
            echo "Nombre: " . $formaPago['nombre'] . "\n";
            echo "Cuenta PUC: " . $formaPago['cuentaPuc'] . "\n";
            echo "Código DIAN: " . $formaPago['codigoDian'] . "\n";
            echo "Medio de Pago: " . $formaPago['medioPago'] . "\n";
            echo "---\n";
        }
    } else {
        echo $result['message'] ?? "No se encontraron formas de pago.\n";
    }
}
curl_close($ch);

?>
JavaScript Fetch
const instance = 'your_instance'; // Reemplace con su instancia actual
const token = 'YOUR_AUTHENTICATION_TOKEN'; // Reemplace con el token obtenido

// Parámetros de filtro opcionales
const params = new URLSearchParams();
// params.append('codigo_dian', '42'); // Opcional: descomentar para filtrar
// params.append('cuenta_puc', '1110'); // Opcional: descomentar para filtrar

const url = `https://${instance}.arrendasoft.co/service/v2/public/invoices/payment-methods${params.toString() ? '?' + params.toString() : ''}`;

fetch(url, {
    method: 'GET',
    headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${token}`
    }
})
.then(response => response.json())
.then(data => {
    if (data.success && data.body.length > 0) {
        console.log(`Se encontraron ${data.body.length} formas de pago:`);
        data.body.forEach(formaPago => {
            console.log(`- ${formaPago.nombre} (ID: ${formaPago.formaPagoId})`);
            console.log(`  Cuenta PUC: ${formaPago.cuentaPuc}`);
            console.log(`  Medio DIAN: ${formaPago.medioPago} (${formaPago.codigoDian})`);
        });
    } else {
        console.log(data.message || 'No se encontraron formas de pago.');
    }
})
.catch(error => console.error('Error de conexión:', error));

Facturas

Listar Resoluciones

Permite obtener el listado de resoluciones de facturación configuradas en la inmobiliaria. Retorna tanto las resoluciones de facturación como las de documento soporte, con soporte para paginación y múltiples filtros.

Endpoint: https://{{instancia}}.arrendasoft.co/service/v2/public/invoices/resolutions

{{instancia}}: Hace referencia a la instancia de cada inmobiliaria.

Petición

Método GET
Content-Type application/json
Authorization Bearer token, Token obtenido al consumir el servicio Login
Parámetros
Parámetro Tipo Obligatorio Valor por defecto Descripción
page integer No 1 Especifica la página de resultados que se desea recuperar al realizar la solicitud.
page_size integer No 10 Especifica el número máximo de elementos que se deben devolver en la solicitud, el límite máximo es de 1000.
activa string No - Filtra resoluciones por estado activo. Valores válidos: SI (activas) o NO (inactivas).
tipo_doc_id integer No - Filtra resoluciones por el ID del tipo de documento contable asociado.
fact_electronica string No - Filtra resoluciones por facturación electrónica. Valores válidos: SI o NO.
resolucion_para integer No - Filtra resoluciones por tipo. Valores válidos: 1 (Factura de Venta) o 2 (Documento Soporte). Si no se especifica, retorna ambos tipos.
fecha_desde string No - Fecha mínima de la resolución. Formato: YYYY-MM-DD (ej: 2025-01-01).
fecha_hasta string No - Fecha máxima de la resolución. Formato: YYYY-MM-DD (ej: 2026-12-31).
fecha_vigencia_desde string No - Fecha mínima de vigencia de la resolución. Formato: YYYY-MM-DD.
fecha_vigencia_hasta string No - Fecha máxima de vigencia de la resolución. Formato: YYYY-MM-DD.

Ejemplos de peticiones

https://{{instancia}}.arrendasoft.co/service/v2/public/invoices/resolutions
https://{{instancia}}.arrendasoft.co/service/v2/public/invoices/resolutions?page=1&page_size=50
https://{{instancia}}.arrendasoft.co/service/v2/public/invoices/resolutions?activa=SI
https://{{instancia}}.arrendasoft.co/service/v2/public/invoices/resolutions?resolucion_para=1
https://{{instancia}}.arrendasoft.co/service/v2/public/invoices/resolutions?resolucion_para=2&activa=SI
https://{{instancia}}.arrendasoft.co/service/v2/public/invoices/resolutions?fact_electronica=SI&page_size=100
https://{{instancia}}.arrendasoft.co/service/v2/public/invoices/resolutions?fecha_desde=2024-01-01&fecha_hasta=2026-12-31
https://{{instancia}}.arrendasoft.co/service/v2/public/invoices/resolutions?resolucion_para=1&activa=SI&fact_electronica=SI&page_size=50

Respuesta

Lista de resoluciones de facturación con información del tipo de documento asociado, datos de consecutivos, fechas, estado y metadatos de paginación.

{
    "status": 200,
    "message": null,
    "body": [
        {
            "resolucion_id": 4,
            "tipo_doc_id": 7,
            "tipo_doc": "Factura",
            "resolucion_numero": "18700052960",
            "consecutivo_iniciar": 1,
            "consecutivo_inicial": 1,
            "consecutivo_final": 20000,
            "fecha": "2025-07-24",
            "fecha_vigencia": "2026-07-24",
            "prefijo": "FE",
            "dias_vencimiento": 5,
            "activa": "SI",
            "codigo_barra": "NO",
            "codigo_ean": null,
            "tipo_resolucion": null,
            "creadopor": 5,
            "fechacreacion": "2025-07-24 12:00:01",
            "modificadopor": null,
            "fechamodificacion": null,
            "fact_electronica": "SI",
            "resolucion_para": 1
        },
        {
            "resolucion_id": 2,
            "tipo_doc_id": 39,
            "tipo_doc": "Documento Soporte",
            "resolucion_numero": "18760000012",
            "consecutivo_iniciar": 1,
            "consecutivo_inicial": 1,
            "consecutivo_final": 1000000,
            "fecha": "2022-09-01",
            "fecha_vigencia": "2024-05-31",
            "prefijo": "DS",
            "dias_vencimiento": 5,
            "activa": "SI",
            "codigo_barra": "NO",
            "codigo_ean": null,
            "tipo_resolucion": null,
            "creadopor": 5,
            "fechacreacion": "2024-05-02 15:01:48",
            "modificadopor": 5,
            "fechamodificacion": "2024-05-06 15:05:23",
            "fact_electronica": "SI",
            "resolucion_para": 2
        }
    ],
    "pagination": {
        "total_records": 4,
        "total_pages": 2,
        "current_page": 1,
        "page_size": 2,
        "current_page_records": 2,
        "has_next_page": true,
        "has_previous_page": false
    },
    "filters_applied": null
}
Claves y Descripciones del JSON de Respuesta

Esta tabla enumera las claves presentes en el JSON principal de la respuesta y proporciona una breve descripción de cada una.

Clave Tipo Descripción
status Entero Código del estado de la respuesta: 200 para exitoso, 400 para errores de validación, 500 para error interno.
message Texto Cuando la respuesta es exitosa, es nulo, y cuando hay error o no se encontraron resultados, contiene el mensaje descriptivo.
body Array Contiene el listado de resoluciones retornadas por la API. Es un array vacío si no hay resultados.
pagination Objeto Contiene toda la información de paginación de la consulta.
filters_applied Objeto Contiene los filtros que fueron aplicados en la consulta. Es nulo si no se aplicaron filtros.
Cuerpo

Cada elemento dentro de la lista body tiene las siguientes claves:

Clave Tipo Descripción
resolucion_id Entero Identificador único de la resolución. Use este valor para el parámetro resolucion_id al filtrar facturas en el endpoint Listar Facturas.
tipo_doc_id Entero Identificador del tipo de documento contable asociado a la resolución. Puede ser nulo.
tipo_doc Texto Nombre del tipo de documento contable (ej: "Factura", "Documento Soporte"). Puede ser nulo si no tiene tipo de documento asociado.
resolucion_numero Texto Número de la resolución asignado por la DIAN.
consecutivo_iniciar Entero Consecutivo a partir del cual se empezará a facturar. Debe estar entre el consecutivo inicial y final.
consecutivo_inicial Entero Consecutivo inicial autorizado por la DIAN.
consecutivo_final Entero Consecutivo final autorizado por la DIAN.
fecha Texto Fecha de expedición de la resolución. Formato: YYYY-MM-DD.
fecha_vigencia Texto Fecha de vigencia (vencimiento) de la resolución. Formato: YYYY-MM-DD.
prefijo Texto Prefijo asignado a la resolución (ej: "FE", "DS", "PR").
dias_vencimiento Entero Días de vencimiento configurados para las facturas generadas con esta resolución.
activa Texto Estado de la resolución: SI (activa) o NO (inactiva).
codigo_barra Texto Indica si la resolución tiene código de barras habilitado: SI o NO.
codigo_ean Texto Código EAN asociado a la resolución. Puede ser nulo si no se ha configurado.
tipo_resolucion Entero Tipo interno de la resolución. Puede ser nulo.
creadopor Entero Identificador del usuario que creó la resolución. Puede ser nulo.
fechacreacion Texto Fecha y hora de creación de la resolución. Formato: YYYY-MM-DD HH:MM:SS.
modificadopor Entero Identificador del usuario que modificó la resolución por última vez. Puede ser nulo.
fechamodificacion Texto Fecha y hora de la última modificación de la resolución. Puede ser nulo. Formato: YYYY-MM-DD HH:MM:SS.
fact_electronica Texto Indica si la resolución es de facturación electrónica: SI o NO.
resolucion_para Entero Tipo de resolución: 1 = Factura de Venta, 2 = Documento Soporte (no obligados a facturar).
Paginación

El objeto pagination tiene las siguientes claves:

Clave Tipo Descripción
total_records Numérico Total de resoluciones que coinciden con los filtros aplicados.
total_pages Numérico Cantidad de páginas, corresponde al total de registros dividido por el tamaño de la página.
current_page Numérico Página actual de la consulta.
page_size Numérico Tamaño de la página, es decir, cantidad máxima de registros por consulta.
current_page_records Numérico Cantidad de registros retornados en la página actual.
has_next_page Booleano Verdadero si hay siguientes páginas que se pueden consultar, falso en otro caso.
has_previous_page Booleano Verdadero si existen páginas previas que se pueden consultar, falso en otro caso.
Filtros Aplicados

El objeto filters_applied contiene los filtros que fueron utilizados en la consulta. Solo se incluye en la respuesta cuando se aplican filtros. Las posibles claves son:

Clave Tipo Descripción
activa Texto Estado activo utilizado como filtro: SI o NO.
tipo_doc_id Entero ID del tipo de documento contable utilizado como filtro.
fact_electronica Texto Filtro de facturación electrónica utilizado: SI o NO.
resolucion_para Entero Tipo de resolución utilizado como filtro: 1 (Factura) o 2 (Documento Soporte).
fecha_desde Texto Fecha mínima de resolución utilizada como filtro.
fecha_hasta Texto Fecha máxima de resolución utilizada como filtro.
fecha_vigencia_desde Texto Fecha mínima de vigencia utilizada como filtro.
fecha_vigencia_hasta Texto Fecha máxima de vigencia utilizada como filtro.

Respuesta con Filtros Aplicados

{
    "status": 200,
    "message": null,
    "body": [
        {
            "resolucion_id": 4,
            "tipo_doc_id": 7,
            "tipo_doc": "Factura",
            "resolucion_numero": "18700052960",
            "consecutivo_iniciar": 1,
            "consecutivo_inicial": 1,
            "consecutivo_final": 20000,
            "fecha": "2025-07-24",
            "fecha_vigencia": "2026-07-24",
            "prefijo": "FE",
            "dias_vencimiento": 5,
            "activa": "SI",
            "codigo_barra": "NO",
            "codigo_ean": null,
            "tipo_resolucion": null,
            "creadopor": 5,
            "fechacreacion": "2025-07-24 12:00:01",
            "modificadopor": null,
            "fechamodificacion": null,
            "fact_electronica": "SI",
            "resolucion_para": 1
        }
    ],
    "pagination": {
        "total_records": 3,
        "total_pages": 1,
        "current_page": 1,
        "page_size": 10,
        "current_page_records": 3,
        "has_next_page": false,
        "has_previous_page": false
    },
    "filters_applied": {
        "resolucion_para": 1,
        "activa": "SI"
    }
}

Respuesta Sin Resultados

{
    "status": 200,
    "message": "No se encontraron resoluciones con los criterios especificados.",
    "body": [],
    "pagination": {
        "total_records": 0,
        "total_pages": 0,
        "current_page": 1,
        "page_size": 10,
        "current_page_records": 0,
        "has_next_page": false,
        "has_previous_page": false
    },
    "filters_applied": {
        "activa": "NO"
    }
}

Respuesta de Error

Error de Validación (400)

Se retorna cuando se envía un parámetro con un valor no válido.

{
    "status": 400,
    "message": "El parámetro \"activa\" debe ser \"SI\" o \"NO\".",
    "body": null,
    "pagination": null,
    "filters_applied": null
}
{
    "status": 400,
    "message": "El parámetro \"resolucion_para\" debe ser 1 (Factura) o 2 (Documento Soporte).",
    "body": null,
    "pagination": null,
    "filters_applied": null
}
{
    "status": 400,
    "message": "El parámetro \"fecha_desde\" debe tener el formato Y-m-d (ej: 2026-01-15).",
    "body": null,
    "pagination": null,
    "filters_applied": null
}
Error Interno (500)

Se retorna cuando ocurre un error inesperado en el servidor.

{
    "status": 500,
    "message": "Error interno del servidor al obtener las resoluciones.",
    "body": null,
    "pagination": null,
    "filters_applied": null
}

Códigos de Respuesta HTTP

Código Descripción
200 Consulta exitosa. El cuerpo de la respuesta contiene las resoluciones (puede ser un array vacío si no hay resultados).
400 Error de validación. Algún parámetro tiene un valor no válido. El campo message indica el parámetro y los valores aceptados.
500 Error interno del servidor.

Valores de Referencia

Valores de resolucion_para
Valor Descripción
1 Factura de Venta — Resoluciones utilizadas para la emisión de facturas de venta
2 Documento Soporte — Resoluciones utilizadas para documento soporte de no obligados a facturar
Valores de activa
Valor Descripción
SI La resolución está activa y disponible para facturación
NO La resolución está inactiva y no se puede usar para facturar

Notas Importantes

  1. Relación con facturas: El resolucion_id retornado puede usarse como valor del parámetro resolucion_id en el endpoint Listar Facturas para filtrar facturas que pertenecen a una resolución específica.

  2. Tipo de resolución: El campo resolucion_para diferencia las resoluciones de facturación (1) de las de documento soporte (2). En el sistema, las resoluciones de facturación se configuran en Configuraciones > Facturación y las de documento soporte en Configuraciones > Facturas de Compra.

  3. Filtros de fecha: Los filtros fecha_desde / fecha_hasta aplican sobre la fecha de expedición de la resolución, mientras que fecha_vigencia_desde / fecha_vigencia_hasta aplican sobre la fecha de vigencia. Ambos rangos pueden combinarse en una misma consulta.

  4. Ordenamiento: Las resoluciones se retornan ordenadas por resolucion_id de forma descendente (las más recientes primero).

Ejemplos

Curl
curl -X GET "https://{{instancia}}.arrendasoft.co/service/v2/public/invoices/resolutions" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_AUTHENTICATION_TOKEN"

Con filtros:

curl -X GET "https://{{instancia}}.arrendasoft.co/service/v2/public/invoices/resolutions?resolucion_para=1&activa=SI&page_size=50" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_AUTHENTICATION_TOKEN"
PHP Curl
<?php

$instance = 'your_instance'; // Reemplace con su instancia actual
$token = 'YOUR_AUTHENTICATION_TOKEN'; // Reemplace con el token obtenido desde el servicio de login

// Parámetros de ejemplo
$page = 1;
$pageSize = 50;

// Parámetros de filtro opcionales
$resolucionPara = 1;    // Opcional: 1 = Factura, 2 = Documento Soporte
$activa = 'SI';          // Opcional: 'SI' o 'NO'
$factElectronica = null; // Opcional: 'SI' o 'NO'

$url = "https://{$instance}.arrendasoft.co/service/v2/public/invoices/resolutions";

// Construir parámetros de consulta
$queryParams = [
    'page' => $page,
    'page_size' => $pageSize
];
if (!empty($resolucionPara)) {
    $queryParams['resolucion_para'] = $resolucionPara;
}
if (!empty($activa)) {
    $queryParams['activa'] = $activa;
}
if (!empty($factElectronica)) {
    $queryParams['fact_electronica'] = $factElectronica;
}
$url .= '?' . http_build_query($queryParams);

$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 "HTTP Status Code: " . $http_code . "\n";
    echo "Response: " . $response . "\n";

    // Procesar la respuesta
    $result = json_decode($response, true);

    if ($http_code == 200 && !empty($result['body'])) {
        echo "Se encontraron " . $result['pagination']['total_records'] . " resoluciones.\n\n";

        foreach ($result['body'] as $resolucion) {
            echo "ID: " . $resolucion['resolucion_id'] . "\n";
            echo "Número: " . $resolucion['resolucion_numero'] . "\n";
            echo "Prefijo: " . $resolucion['prefijo'] . "\n";
            echo "Tipo: " . $resolucion['tipo_doc'] . "\n";
            echo "Activa: " . $resolucion['activa'] . "\n";
            echo "Vigencia: " . $resolucion['fecha_vigencia'] . "\n";
            echo "---\n";
        }
    } else {
        echo $result['message'] ?? "No se encontraron resoluciones.\n";
    }
}
curl_close($ch);

?>
JavaScript Fetch
const instance = 'your_instance'; // Reemplace con su instancia actual
const token = 'YOUR_AUTHENTICATION_TOKEN'; // Reemplace con el token obtenido

// Parámetros de filtro opcionales
const params = new URLSearchParams();
params.append('page', '1');
params.append('page_size', '50');
params.append('resolucion_para', '1'); // Opcional: 1 = Factura, 2 = Documento Soporte
params.append('activa', 'SI');          // Opcional: 'SI' o 'NO'
// params.append('fact_electronica', 'SI'); // Opcional: descomentar para filtrar

const url = `https://${instance}.arrendasoft.co/service/v2/public/invoices/resolutions?${params.toString()}`;

fetch(url, {
    method: 'GET',
    headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${token}`
    }
})
.then(response => response.json())
.then(data => {
    if (data.status === 200 && data.body.length > 0) {
        console.log(`Se encontraron ${data.pagination.total_records} resoluciones:`);
        data.body.forEach(res => {
            console.log(`- ${res.prefijo} ${res.resolucion_numero} (ID: ${res.resolucion_id})`);
            console.log(`  Tipo: ${res.tipo_doc} | Activa: ${res.activa}`);
            console.log(`  Consecutivos: ${res.consecutivo_inicial} - ${res.consecutivo_final}`);
            console.log(`  Vigencia: ${res.fecha} a ${res.fecha_vigencia}`);
        });

        // Información de paginación
        console.log(`\nPágina ${data.pagination.current_page} de ${data.pagination.total_pages}`);
    } else {
        console.log(data.message || 'No se encontraron resoluciones.');
    }
})
.catch(error => console.error('Error de conexión:', error));

Contabilidad

Bienvenido al libro contable digital de tu inmobiliaria. En este apartado centralizamos las herramientas de conexión para que tus plataformas externas consulten y sincronicen tu información financiera de forma automática.

¿Para qué sirve este módulo? El objetivo principal es eliminar los procesos manuales en la extracción de datos financieros. En lugar de descargar informes a mano, tus sistemas podrán consultar directamente el historial y los movimientos de tus cuentas contables. Podrás utilizar filtros estratégicos —como rangos de fechas o grupos de cuentas— para extraer exactamente la información que necesitas sin sobrecargar tus integraciones.

Explora el listado a continuación para descubrir cómo alimentar tus tableros de análisis y mantener tus números perfectamente organizados, auditables y sincronizados.

Contabilidad

Reporte Auxiliar General

Permite obtener el reporte contable Auxiliar General, que presenta los movimientos detallados de cada cuenta del Plan Único de Cuentas (PUC) dentro de un período y rango de cuentas. Cada elemento incluye el saldo anterior, débitos, créditos, saldo actual, base de retención, y el desglose por tercero con sus respectivos documentos contables.

¿Para qué sirve este servicio?
Úsalo para alimentar reportes contables en tu ERP, conciliar saldos con sistemas externos, generar informes de auditoría, exportar movimientos detallados a Excel o Power BI, o validar la contabilidad de un período específico.


1. El Endpoint (La dirección web)

Apunta tu sistema a la siguiente dirección. Recuerda reemplazar {{instancia}} por la dirección web completa que utilizas para ingresar a tu plataforma.

GET https://{{instancia}}/service/v2/public/accounting/general-ledger

¿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.

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

Este servicio no requiere cuerpo en la petición. Envía los encabezados requeridos y opcionalmente los parámetros de filtro en la URL:

Método GET
Content-Type application/json
Authorization Bearer token, Token obtenido al consumir el servicio Login

¿Aún no tienes tu Token de acceso?
Para consumir este servicio necesitas un Token vigente. Consulta el servicio de Login para aprender cómo obtenerlo.

Parámetros de consulta (query string):

Parámetro Tipo Requerido Por defecto Descripción
fecha_ini string No Primer día del año en curso Fecha inicial del rango a consultar. Formato: YYYY-MM-DD.
fecha_fin string No Último día del mes en curso Fecha final del rango a consultar. Formato: YYYY-MM-DD. Debe ser mayor o igual a fecha_ini.
cuenta_ini string No 1 Código inicial de cuenta PUC. Solo permite valores numéricos. Debe ser mayor o igual a 1.
cuenta_fin string No 9 Código final de cuenta PUC. Solo permite valores numéricos. Debe ser mayor o igual a cuenta_ini.

Ejemplos de petición:

GET https://mi-inmobiliaria.nuby.app/service/v2/public/accounting/general-ledger
GET https://mi-inmobiliaria.nuby.app/service/v2/public/accounting/general-ledger?fecha_ini=2025-01-01
GET https://mi-inmobiliaria.nuby.app/service/v2/public/accounting/general-ledger?fecha_ini=2025-01-01&fecha_fin=2025-06-30
GET https://mi-inmobiliaria.nuby.app/service/v2/public/accounting/general-ledger?fecha_ini=2025-01-01&fecha_fin=2025-06-30&cuenta_ini=1
GET https://mi-inmobiliaria.nuby.app/service/v2/public/accounting/general-ledger?fecha_ini=2025-01-01&fecha_fin=2025-06-30&cuenta_ini=1&cuenta_fin=4

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

Si tu Token es válido y los parámetros son correctos, el sistema te devolverá un objeto JSON con el listado de cuentas contables, sus terceros y los movimientos detallados de cada uno. La respuesta tiene una estructura jerárquica de tres niveles: Cuenta → Tercero → Detalle.

{
    "error": false,
    "message": "",
    "body": [
        {
            "cuenta": "11050501",
            "nombre_cuenta": "Caja general moneda nacional",
            "saldo_anterior": 8750320.45,
            "debitos": 12480000,
            "creditos": 9230000,
            "saldo_actual": 12000320.45,
            "base_retencion": 0,
            "terceros": {
                "42": {
                    "documento_tercero": "80213654",
                    "nombre_tercero": "CARLOS EDUARDO PINEDA VARGAS",
                    "saldo_anterior": 3250120.45,
                    "debitos": 7500000,
                    "creditos": 4230000,
                    "saldo_actual": 6520120.45,
                    "base_retencion": 0,
                    "detalles": [
                        {
                            "fecha_documento": "2025-02-05",
                            "consecutivo_documento": "RC-10450",
                            "detalle_documento": "Pago canon arrendamiento febrero Apto 501",
                            "debitos": 2850000,
                            "creditos": 0,
                            "base_retencion": 0
                        },
                        {
                            "fecha_documento": "2025-03-03",
                            "consecutivo_documento": "RC-10512",
                            "detalle_documento": "Pago canon arrendamiento marzo Apto 501",
                            "debitos": 2850000,
                            "creditos": 0,
                            "base_retencion": 0
                        },
                        {
                            "fecha_documento": "2025-03-15",
                            "consecutivo_documento": "EG-4021",
                            "detalle_documento": "Consignación propietario marzo",
                            "debitos": 0,
                            "creditos": 4230000,
                            "base_retencion": 0
                        }
                    ]
                },
                "73": {
                    "documento_tercero": "1098745231",
                    "nombre_tercero": "JULIANA PATRICIA RÍOS MENDOZA",
                    "saldo_anterior": 1500200,
                    "debitos": 4980000,
                    "creditos": 5000000,
                    "saldo_actual": 1480200,
                    "base_retencion": 0,
                    "detalles": [
                        {
                            "fecha_documento": "2025-01-10",
                            "consecutivo_documento": "RC-10389",
                            "detalle_documento": "Pago canon arrendamiento enero Local 3",
                            "debitos": 4500000,
                            "creditos": 0,
                            "base_retencion": 0
                        },
                        {
                            "fecha_documento": "2025-01-20",
                            "consecutivo_documento": "EG-3998",
                            "detalle_documento": "Consignación propietario enero",
                            "debitos": 0,
                            "creditos": 5000000,
                            "base_retencion": 0
                        }
                    ]
                }
            }
        },
        {
            "cuenta": "13050501",
            "nombre_cuenta": "Arrendamientos por cobrar",
            "saldo_anterior": 15400000,
            "debitos": 9350000,
            "creditos": 12480000,
            "saldo_actual": 12270000,
            "base_retencion": 0,
            "terceros": {
                "55": {
                    "documento_tercero": "43876123",
                    "nombre_tercero": "DIANA MARCELA OSPINA VELÁSQUEZ",
                    "saldo_anterior": 2400000,
                    "debitos": 3600000,
                    "creditos": 4800000,
                    "saldo_actual": 1200000,
                    "base_retencion": 0,
                    "detalles": [
                        {
                            "fecha_documento": "2025-01-01",
                            "consecutivo_documento": "FV-8901",
                            "detalle_documento": "Factura arrendamiento enero Cll 23 # 56 - 78",
                            "debitos": 1200000,
                            "creditos": 0,
                            "base_retencion": 0
                        },
                        {
                            "fecha_documento": "2025-01-15",
                            "consecutivo_documento": "RC-10401",
                            "detalle_documento": "Recibo de caja pago enero",
                            "debitos": 0,
                            "creditos": 1200000,
                            "base_retencion": 0
                        },
                        {
                            "fecha_documento": "2025-02-01",
                            "consecutivo_documento": "FV-8950",
                            "detalle_documento": "Factura arrendamiento febrero Cll 23 # 56 - 78",
                            "debitos": 1200000,
                            "creditos": 0,
                            "base_retencion": 0
                        },
                        {
                            "fecha_documento": "2025-02-10",
                            "consecutivo_documento": "RC-10465",
                            "detalle_documento": "Recibo de caja pago febrero",
                            "debitos": 0,
                            "creditos": 1200000,
                            "base_retencion": 0
                        }
                    ]
                }
            }
        },
        {
            "cuenta": "24080501",
            "nombre_cuenta": "Retención en la fuente arrendamientos 3.5%",
            "saldo_anterior": -875000,
            "debitos": 0,
            "creditos": 249375,
            "saldo_actual": -1124375,
            "base_retencion": 7125000,
            "terceros": {
                "65": {
                    "documento_tercero": "900456789",
                    "nombre_tercero": "INVERSIONES HORIZONTE S.A.S.",
                    "saldo_anterior": -875000,
                    "debitos": 0,
                    "creditos": 249375,
                    "saldo_actual": -1124375,
                    "base_retencion": 7125000,
                    "detalles": [
                        {
                            "fecha_documento": "2025-01-31",
                            "consecutivo_documento": "EG-3985",
                            "detalle_documento": "Retención arrendamiento enero Local 3",
                            "debitos": 0,
                            "creditos": 157500,
                            "base_retencion": 4500000
                        },
                        {
                            "fecha_documento": "2025-02-28",
                            "consecutivo_documento": "EG-4050",
                            "detalle_documento": "Retención arrendamiento febrero Local 3",
                            "debitos": 0,
                            "creditos": 91875,
                            "base_retencion": 2625000
                        }
                    ]
                }
            }
        }
    ]
}
Estructura principal de la respuesta
Campo Tipo Descripción
error boolean Estado de la respuesta. false para exitoso, true cuando ocurre un error.
message string Cadena vacía cuando la respuesta es exitosa. Si no hay resultados, contiene un mensaje informativo. Si hay error, describe el problema presentado.
body array | null Listado de cuentas contables con sus movimientos. null cuando no hay resultados o hay un error.
Campos de cada cuenta (body)

Cada elemento dentro del arreglo body representa una cuenta contable y contiene las siguientes claves:

Campo Tipo Descripción
cuenta string Código numérico de la cuenta en el Plan Único de Cuentas (PUC).
nombre_cuenta string Nombre descriptivo de la cuenta PUC.
saldo_anterior number Saldo acumulado de la cuenta antes de la fecha inicial del rango consultado. Puede ser negativo.
debitos number Suma total de los débitos de la cuenta en el período consultado.
creditos number Suma total de los créditos de la cuenta en el período consultado.
saldo_actual number Saldo resultante de la cuenta al final del período. El cálculo varía según la clase de cuenta: para activos, gastos y costos (clases 1, 5 y 6) es saldo_anterior + débitos - créditos; para las demás clases es saldo_anterior + créditos - débitos. Puede ser negativo.
base_retencion number Valor acumulado de la base de retención de la cuenta en el período.
terceros object Objeto que contiene los terceros vinculados a la cuenta. Cada clave del objeto es el tercero_id del sistema (o "sin_tercero" si el movimiento no tiene tercero asociado).
Campos de cada tercero (terceros)

Cada entrada dentro del objeto terceros contiene las siguientes claves:

Campo Tipo Descripción
documento_tercero string Número de documento de identidad del tercero. Si no tiene tercero asociado, muestra "Sin tercero".
nombre_tercero string Nombre completo del tercero. Si no tiene tercero asociado, muestra "Sin tercero".
saldo_anterior number Saldo acumulado del tercero en esta cuenta antes de la fecha inicial. Puede ser negativo.
debitos number Suma total de los débitos del tercero en esta cuenta durante el período.
creditos number Suma total de los créditos del tercero en esta cuenta durante el período.
saldo_actual number Saldo resultante del tercero en esta cuenta al final del período. Mismo criterio de cálculo que el saldo de la cuenta.
base_retencion number Valor acumulado de la base de retención del tercero en esta cuenta.
detalles array Listado de documentos contables (movimientos individuales) del tercero en esta cuenta durante el período.
Campos de cada detalle (detalles)

Cada elemento dentro del arreglo detalles representa un documento contable individual:

Campo Tipo Descripción
fecha_documento string Fecha del documento contable en formato YYYY-MM-DD.
consecutivo_documento string Consecutivo del documento contable con su prefijo, en formato PREFIJO-NÚMERO (ej. RC-10450, FV-8901, EG-4021).
detalle_documento string Descripción u observaciones del documento contable.
debitos number Valor del débito del documento contable.
creditos number Valor del crédito del documento contable.
base_retencion number Valor de la base de retención del documento contable.

Nota sobre resultados vacíos
Si no existen movimientos contables para los parámetros indicados, la respuesta tendrá HTTP 200 con error: false, body: null y un message informativo: "No se encontraron registros con los parámetros indicados."

Nota sobre el cálculo de saldos
El cálculo del saldo_actual depende de la clase contable de la cuenta (primer dígito del código PUC):
Clases 1 (Activos), 5 (Gastos) y 6 (Costos): saldo_anterior + débitos - créditos
Clases 2 (Pasivos), 3 (Patrimonio), 4 (Ingresos) y demás: saldo_anterior + créditos - débitos
Este comportamiento puede variar según la configuración del sistema (parámetro interno de la plataforma).


4. Seguridad y Posibles Errores

¡Tu pase tiene fecha de caducidad!

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 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:

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

Si alguno de los parámetros no cumple con las validaciones, el sistema devolverá un error 400. Por ejemplo:

{
    "error": true,
    "message": "La fecha inicial no tiene un formato válido (Y-m-d) o no es una fecha válida.",
    "body": null
}

Posibles errores:

Código HTTP Descripción
400 Token faltante o inválido. Posibles causas:
— No se envió el encabezado Authorization. Mensaje: "JWT Token required."
— El encabezado no tiene el formato Bearer {token}. Mensaje: "JWT Token not send."
— El token no fue encontrado en el sistema. Mensaje: "JWT Token not found."

Parámetros inválidos. Posibles causas:
fecha_ini no tiene formato YYYY-MM-DD válido. Mensaje: "La fecha inicial no tiene un formato válido (Y-m-d) o no es una fecha válida."
fecha_fin no tiene formato YYYY-MM-DD válido. Mensaje: "La fecha final no tiene un formato válido (Y-m-d) o no es una fecha válida."
fecha_ini es posterior a fecha_fin. Mensaje: "La fecha inicial debe ser menor o igual que la fecha final."
cuenta_ini no es numérico. Mensaje: "La cuenta inicial debe ser un valor numérico."
cuenta_fin no es numérico. Mensaje: "La cuenta final debe ser un valor numérico."
cuenta_ini es mayor que cuenta_fin. Mensaje: "La cuenta inicial debe ser menor o igual que la cuenta final."
cuenta_ini es menor que 1. Mensaje: "La cuenta inicial debe ser mayor o igual que 1."
401 El token ha expirado. Debes generar uno nuevo consumiendo el servicio de Login. Mensaje: "JWT Token expired."
403 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}'."
500 Error interno del servidor al procesar la consulta del auxiliar general. Mensaje: "Ocurrió un error al tratar de obtener el auxiliar general."

5. Ejemplos de integración

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

cURL
# Consultar auxiliar general con parámetros por defecto (año actual, todas las cuentas)
curl -X GET "https://{{instancia}}/service/v2/public/accounting/general-ledger" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer TU_TOKEN_AQUI"

# Consultar auxiliar general de enero a junio 2025, cuentas de activos y pasivos (1 a 2)
curl -X GET "https://{{instancia}}/service/v2/public/accounting/general-ledger?fecha_ini=2025-01-01&fecha_fin=2025-06-30&cuenta_ini=1&cuenta_fin=2" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer TU_TOKEN_AQUI"
PHP
<?php

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

// Parámetros de consulta
$fecha_ini = '2025-01-01';
$fecha_fin = '2025-06-30';
$cuenta_ini = '1';
$cuenta_fin = '4';

$queryParams = http_build_query([
    'fecha_ini' => $fecha_ini,
    'fecha_fin' => $fecha_fin,
    'cuenta_ini' => $cuenta_ini,
    'cuenta_fin' => $cuenta_fin
]);

$url = "https://{$instance}/service/v2/public/accounting/general-ledger?{$queryParams}";

$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";

    $info = json_decode($response, true);
    $body = $info['body'] ?? [];

    if ($http_code === 200 && !empty($body)) {
        echo "Se consultaron " . count($body) . " cuentas contables.\n\n";

        foreach ($body as $cuenta) {
            echo "Cuenta: {$cuenta['cuenta']} - {$cuenta['nombre_cuenta']}\n";
            echo "  Saldo anterior: $" . number_format($cuenta['saldo_anterior'], 2) . "\n";
            echo "  Débitos: $" . number_format($cuenta['debitos'], 2) . "\n";
            echo "  Créditos: $" . number_format($cuenta['creditos'], 2) . "\n";
            echo "  Saldo actual: $" . number_format($cuenta['saldo_actual'], 2) . "\n";

            foreach ($cuenta['terceros'] as $terceroId => $tercero) {
                echo "    Tercero: {$tercero['documento_tercero']} - {$tercero['nombre_tercero']}\n";
                echo "      Movimientos: " . count($tercero['detalles']) . "\n";
            }
            echo "\n";
        }
    } else {
        echo "Mensaje: " . ($info['message'] ?? 'Sin resultados') . "\n";
    }
}
curl_close($ch);

?>
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 Login

# 2. Prepara la dirección y los parámetros
url = f"https://{instancia}/service/v2/public/accounting/general-ledger"

params = {
    "fecha_ini": "2025-01-01",
    "fecha_fin": "2025-06-30",
    "cuenta_ini": "1",
    "cuenta_fin": "4"
}

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, params=params, headers=headers)

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

    if response.status_code == 200:
        info = response.json()
        body = info.get('body') or []

        if body:
            print(f"Cuentas encontradas: {len(body)}\n")
            for cuenta in body:
                print(f"Cuenta: {cuenta['cuenta']} - {cuenta['nombre_cuenta']}")
                print(f"  Saldo anterior: ${cuenta['saldo_anterior']:,.2f}")
                print(f"  Débitos: ${cuenta['debitos']:,.2f}")
                print(f"  Créditos: ${cuenta['creditos']:,.2f}")
                print(f"  Saldo actual: ${cuenta['saldo_actual']:,.2f}")

                for tercero_id, tercero in cuenta['terceros'].items():
                    print(f"    Tercero [{tercero_id}]: {tercero['documento_tercero']} - {tercero['nombre_tercero']}")
                    print(f"      Movimientos: {len(tercero['detalles'])}")
                print()
        else:
            print(f"Mensaje: {info.get('message', 'Sin resultados')}")
    else:
        print("Error al consultar el auxiliar general.")
        print(f"Detalle del error: {response.text}")

except Exception as e:
    print(f"Ocurrió un error de conexión: {e}")
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 Login

// 2. Prepara la dirección con parámetros
const params = new URLSearchParams({
    fecha_ini: '2025-01-01',
    fecha_fin: '2025-06-30',
    cuenta_ini: '1',
    cuenta_fin: '4'
});

const url = `https://${instancia}/service/v2/public/accounting/general-ledger?${params}`;

// 3. Función para consultar el auxiliar general
async function consultarAuxiliarGeneral() {
    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 info = await response.json();
            const body = info.body || [];

            if (body.length > 0) {
                console.log(`Cuentas encontradas: ${body.length}\n`);
                body.forEach(cuenta => {
                    console.log(`Cuenta: ${cuenta.cuenta} - ${cuenta.nombre_cuenta}`);
                    console.log(`  Saldo anterior: $${cuenta.saldo_anterior.toLocaleString()}`);
                    console.log(`  Débitos: $${cuenta.debitos.toLocaleString()}`);
                    console.log(`  Créditos: $${cuenta.creditos.toLocaleString()}`);
                    console.log(`  Saldo actual: $${cuenta.saldo_actual.toLocaleString()}`);

                    for (const [terceroId, tercero] of Object.entries(cuenta.terceros)) {
                        console.log(`    Tercero [${terceroId}]: ${tercero.documento_tercero} - ${tercero.nombre_tercero}`);
                        console.log(`      Movimientos: ${tercero.detalles.length}`);
                    }
                    console.log('');
                });
            } else {
                console.log(`Mensaje: ${info.message || 'Sin resultados'}`);
            }
        } else {
            console.log('Error al consultar el auxiliar general.');
            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
consultarAuxiliarGeneral();
Power Query M (Excel / Power BI)
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 Login

    // 2. Prepara la dirección con parámetros
    url = "https://" & instancia & "/service/v2/public/accounting/general-ledger?fecha_ini=2025-01-01&fecha_fin=2025-06-30&cuenta_ini=1&cuenta_fin=4",

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

    // 4. Decodifica la respuesta JSON
    jsonResponse = Json.Document(response),
    body = jsonResponse[body],

    // 5. Convierte el listado de cuentas en tabla
    tablaCuentas = Table.FromList(body, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
    expandidoCuentas = Table.ExpandRecordColumn(tablaCuentas, "Column1",
        {"cuenta", "nombre_cuenta", "saldo_anterior", "debitos", "creditos", "saldo_actual", "base_retencion", "terceros"},
        {"Cuenta", "NombreCuenta", "SaldoAnterior", "Debitos", "Creditos", "SaldoActual", "BaseRetencion", "Terceros"}),

    // 6. (Opcional) Expandir terceros para obtener detalle por tercero
    // Nota: La estructura de terceros es un objeto con claves dinámicas.
    // Para un análisis más detallado, es recomendable procesar los terceros
    // con Record.FieldValues y luego expandir los detalles.
    tercerosList = Table.AddColumn(expandidoCuentas, "TercerosLista", each Record.FieldValues([Terceros])),
    expandidoTerceros = Table.ExpandListColumn(tercerosList, "TercerosLista"),
    expandidoTercerosCampos = Table.ExpandRecordColumn(expandidoTerceros, "TercerosLista",
        {"documento_tercero", "nombre_tercero", "saldo_anterior", "debitos", "creditos", "saldo_actual", "base_retencion"},
        {"DocTercero", "NombreTercero", "SaldoAntTercero", "DebitosTercero", "CreditosTercero", "SaldoActTercero", "BaseRetTercero"})
in
    expandidoTercerosCampos

Contratos

Bienvenido al archivador legal digital de tu inmobiliaria. En esta sección agrupamos todas las opciones de conexión para que tus plataformas externas interactúen con los acuerdos de arrendamiento.

¿Cuál es el propósito de este módulo? Facilitar la sincronización de tu ecosistema. Aquí encontrarás las herramientas necesarias para que tus sistemas consulten y extraigan automáticamente los detalles de cualquier contrato, eliminando por completo la necesidad de realizar búsquedas manuales o revisar documentos físicos en nuestra plataforma.

Explora el listado de abajo para descubrir cómo consultar términos, información financiera, estados y fechas de tus inmuebles alquilados.

Contratos

Listar Contratos

Permite obtener la lista paginada de todos los contratos de arrendamiento registrados en el sistema. Cada elemento incluye la información completa del contrato: propiedad asociada, propietarios, inquilinos, valores económicos, fechas, estado y observaciones.

¿Para qué sirve este servicio?
Úsalo para sincronizar el inventario de contratos con tu sistema externo, generar reportes de gestión inmobiliaria, alimentar dashboards con información contractual o consultar el estado general de los contratos administrados.


1. El Endpoint (La dirección web)

Apunta tu sistema a la siguiente dirección. Recuerda reemplazar {{instancia}} por la dirección web completa que utilizas para ingresar a tu plataforma.

GET https://{{instancia}}/service/v2/public/contracts/list

¿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.

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

Este servicio no requiere cuerpo en la petición. Envía los encabezados requeridos y opcionalmente los parámetros de paginación en la URL:

Método GET
Content-Type application/json
Authorization Bearer token, Token obtenido al consumir el servicio Login

¿Aún no tienes tu Token de acceso?
Para consumir este servicio necesitas un Token vigente. Consulta el servicio de Login para aprender cómo obtenerlo.

Parámetros de consulta (query string):

Parámetro Tipo Requerido Por defecto Descripción
page integer No 1 Número de página de resultados que se desea recuperar. Debe ser un número positivo.
page_size integer No 10 Número máximo de contratos por página. Debe ser un número positivo. Valor máximo permitido: 1000.

Ejemplos de petición:

GET https://mi-inmobiliaria.nuby.app/service/v2/public/contracts/list
GET https://mi-inmobiliaria.nuby.app/service/v2/public/contracts/list?page=2
GET https://mi-inmobiliaria.nuby.app/service/v2/public/contracts/list?page_size=50
GET https://mi-inmobiliaria.nuby.app/service/v2/public/contracts/list?page=3&page_size=100

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

Si tu Token es válido, el sistema te devolverá un objeto JSON con el estado de la respuesta, el listado de contratos y la información de paginación. La respuesta se verá similar a esta:

{
    "status": 200,
    "message": null,
    "body": [
        {
            "contrato_id": 45,
            "consecutivo": "45",
            "propiedad_id": 312,
            "propiedad": "312 - Cll 78 # 12 - 34 Apto 501",
            "estrato_propiedad": "Cuatro",
            "propietario": "[1] 52498731 - ANDREA MILENA CASTRO ROJAS",
            "propietarios_id": "18",
            "inquilino": "[1] 80213654 - CARLOS EDUARDO PINEDA VARGAS",
            "inquilinos_id": "42",
            "valor_canon_individual": "2850000",
            "canon_total": 2850000,
            "porcentaje_comision": "10.00 %",
            "periodicidad": "Mensual",
            "escenario": "CANON DE ARRENDAMIENTO SIN IVA, CON RETEFUENTE 3.5%, SIN RETEIVA, SIN RETEICA",
            "estado": "Activo",
            "estado_id": 1,
            "fecha_inicio": "2024-06-01",
            "fecha_fin": "2025-05-31",
            "fecha_terminacion": null,
            "observaciones": "Contrato renovado automáticamente por un año adicional.",
            "uso": "Vivienda",
            "fecha_creacion": "2024-05-28 14:32:10",
            "creado_por": "Sandra"
        },
        {
            "contrato_id": 46,
            "consecutivo": "46",
            "propiedad_id": 589,
            "propiedad": "589 - Cra 45 # 90 - 12 Local 3",
            "estrato_propiedad": "Comercial",
            "propietario": "[1] 900456789 - INVERSIONES HORIZONTE S.A.S.",
            "propietarios_id": "65",
            "inquilino": "[1] 1098745231 - JULIANA PATRICIA RÍOS MENDOZA",
            "inquilinos_id": "73",
            "valor_canon_individual": "4500000",
            "canon_total": 4500000,
            "porcentaje_comision": "8.50 %",
            "periodicidad": "Mensual",
            "escenario": "CANON DE ARRENDAMIENTO CON IVA 19%, CON RETEFUENTE 3.5%, CON RETEIVA 15%, SIN RETEICA",
            "estado": "Activo",
            "estado_id": 1,
            "fecha_inicio": "2023-09-01",
            "fecha_fin": "2025-08-31",
            "fecha_terminacion": null,
            "observaciones": null,
            "uso": "Comercial",
            "fecha_creacion": "2023-08-25 09:15:44",
            "creado_por": "Administrador"
        },
        {
            "contrato_id": 12,
            "consecutivo": "12",
            "propiedad_id": 104,
            "propiedad": "104 - Cll 23 # 56 - 78",
            "estrato_propiedad": "Tres",
            "propietario": "[1] 71654321 - HÉCTOR FABIO MORENO AGUILAR",
            "propietarios_id": "31",
            "inquilino": "[1] 43876123 - DIANA MARCELA OSPINA VELÁSQUEZ",
            "inquilinos_id": "55",
            "valor_canon_individual": "1200000",
            "canon_total": 1200000,
            "porcentaje_comision": "12.00 %",
            "periodicidad": "Mensual",
            "escenario": "CANON DE ARRENDAMIENTO SIN IVA, SIN RETEFUENTE, SIN RETEIVA, SIN RETEICA",
            "estado": "Terminado",
            "estado_id": 2,
            "fecha_inicio": "2022-01-15",
            "fecha_fin": "2023-01-14",
            "fecha_terminacion": "2022-11-30",
            "observaciones": "Terminación anticipada por mutuo acuerdo.",
            "uso": "Vivienda",
            "fecha_creacion": "2021-12-20 16:40:33",
            "creado_por": "Sandra"
        }
    ],
    "pagination": {
        "total_records": 347,
        "total_pages": 116,
        "current_page": 1,
        "page_size": 3,
        "current_page_records": 3,
        "has_next_page": true,
        "has_previous_page": false
    }
}
Estructura principal de la respuesta
Campo Tipo Descripción
status integer Código del estado de la respuesta. 200 para exitoso, 400 para error de validación, 500 para error interno.
message string | null Cuando la respuesta es exitosa vale null. Si no se encuentran contratos, contiene el mensaje informativo. Si hay error, describe el problema.
body array Listado de contratos devueltos. Arreglo vacío [] si no hay resultados.
pagination object Información de paginación para recorrer los resultados.
Campos de cada contrato (body)

Cada elemento dentro del arreglo body contiene las siguientes claves:

Campo Tipo Descripción
contrato_id integer Identificador único del contrato en el sistema.
consecutivo string Número consecutivo interno del contrato.
propiedad_id integer Identificador de la propiedad asociada al contrato.
propiedad string Etiqueta descriptiva de la propiedad en formato {id} - {dirección}.
estrato_propiedad string Estrato socioeconómico asignado a la propiedad (ej. "Tres", "Cuatro", "Comercial").
propietario string Cadena con el consecutivo del detalle, documento y nombre completo del propietario o propietarios. Formato: [n] documento - NOMBRE. Si hay varios, van separados por coma.
propietarios_id string ID(s) del/los propietario(s) en el sistema. Si hay varios, van separados por coma.
inquilino string Cadena con el consecutivo del detalle, documento y nombre completo del inquilino o inquilinos. Mismo formato que propietario.
inquilinos_id string ID(s) del/los inquilino(s) en el sistema. Si hay varios, van separados por coma.
valor_canon_individual string Valor del canon por cada detalle del contrato. Si hay varios detalles, los valores van separados por coma.
canon_total number | null Valor total del canon de arrendamiento del contrato.
porcentaje_comision string Porcentaje de comisión de la inmobiliaria con formato "X.XX %".
periodicidad string Frecuencia de pago del canon (ej. "Mensual").
escenario string Descripción del escenario tributario y de facturación aplicado al contrato.
estado string Estado textual del contrato. Valores posibles: Activo, Terminado, En Construcción.
estado_id integer Identificador numérico del estado: 1 = Activo, 2 = Terminado, 3 = En Construcción.
fecha_inicio string Fecha de inicio del contrato en formato YYYY-MM-DD.
fecha_fin string Fecha de finalización prevista del contrato en formato YYYY-MM-DD.
fecha_terminacion string | null Fecha de terminación efectiva del contrato (si aplica). null si el contrato sigue vigente.
observaciones string | null Observaciones o notas asociadas al contrato. null si no hay.
uso string Tipo de uso de la propiedad: Vivienda o Comercial.
fecha_creacion string Fecha y hora de creación del registro en formato YYYY-MM-DD HH:MM:SS.
creado_por string Nombre del usuario que creó el contrato en el sistema.
Campos de paginación (pagination)

El objeto pagination contiene las siguientes claves:

Campo Tipo Descripción
total_records integer Total de contratos registrados en el sistema.
total_pages integer Cantidad total de páginas disponibles (total de registros dividido por el tamaño de página).
current_page integer Número de la página actual consultada.
page_size integer Tamaño de la página (cantidad de registros solicitados por consulta).
current_page_records integer Cantidad de registros efectivamente devueltos en la página actual.
has_next_page boolean true si existen páginas posteriores que se pueden consultar.
has_previous_page boolean true si existen páginas anteriores que se pueden consultar.

Nota sobre contratos sin resultados
Si no existen contratos registrados en el sistema, la respuesta tendrá HTTP 200 con body vacío ([]), un message informativo y los valores de paginación en cero.


4. Seguridad y Posibles Errores

¡Tu pase tiene fecha de caducidad!

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 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:

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

Si alguno de los parámetros de paginación no cumple con las validaciones, el sistema devolverá un error 400 con la estructura estándar. Por ejemplo:

{
    "status": 400,
    "message": "El parámetro \"page_size\" debe ser un número positivo.",
    "body": null,
    "pagination": null
}

Posibles errores:

Código HTTP Descripción
400 Token faltante o inválido. Posibles causas:
— No se envió el encabezado Authorization. Mensaje: "JWT Token required."
— El encabezado no tiene el formato Bearer {token}. Mensaje: "JWT Token not send."
— El token no fue encontrado en el sistema. Mensaje: "JWT Token not found."

Parámetros inválidos. Posibles causas:
page no es numérico o no es positivo.
page_size no es numérico o no es positivo.
401 El token ha expirado. Debes generar uno nuevo consumiendo el servicio de Login. Mensaje: "JWT Token expired."
403 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}'."
500 Error interno del servidor al procesar la consulta de contratos.

5. Ejemplos de integración

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

cURL
# Listar contratos con paginación por defecto
curl -X GET "https://{{instancia}}/service/v2/public/contracts/list" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer TU_TOKEN_AQUI"

# Listar contratos página 3 con 100 registros por página
curl -X GET "https://{{instancia}}/service/v2/public/contracts/list?page=3&page_size=100" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer TU_TOKEN_AQUI"
PHP
<?php

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

// Parámetros de paginación
$page = 1;
$page_size = 50;

$queryParams = http_build_query([
    'page' => $page,
    'page_size' => $page_size
]);

$url = "https://{$instance}/service/v2/public/contracts/list?{$queryParams}";

$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";

    $info = json_decode($response, true);
    $body = $info['body'] ?? [];

    if ($http_code === 200 && !empty($body)) {
        $pagination = $info['pagination'];
        echo "Contratos encontrados: {$pagination['total_records']} (página {$pagination['current_page']} de {$pagination['total_pages']})\n";

        foreach ($body as $contrato) {
            echo "  [{$contrato['consecutivo']}] {$contrato['propiedad']} - {$contrato['estado']} - Canon: \${$contrato['canon_total']}\n";
        }
    } else {
        echo "Mensaje: " . ($info['message'] ?? 'Sin resultados') . "\n";
    }
}
curl_close($ch);

?>
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 Login

# 2. Prepara la dirección y los parámetros
url = f"https://{instancia}/service/v2/public/contracts/list"

params = {
    "page": 1,
    "page_size": 50
}

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, params=params, headers=headers)

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

    if response.status_code == 200:
        info = response.json()
        body = info.get('body', [])
        pagination = info.get('pagination', {})

        if body:
            print(f"Contratos: {pagination['total_records']} total (página {pagination['current_page']} de {pagination['total_pages']})")
            for contrato in body:
                print(f"  [{contrato['consecutivo']}] {contrato['propiedad']} - {contrato['estado']} - Canon: ${contrato['canon_total']}")
        else:
            print(f"Mensaje: {info.get('message', 'Sin resultados')}")
    else:
        print("Error al consultar los contratos.")
        print(f"Detalle del error: {response.text}")

except Exception as e:
    print(f"Ocurrió un error de conexión: {e}")
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 Login

// 2. Prepara la dirección con parámetros
const params = new URLSearchParams({
    page: 1,
    page_size: 50
});

const url = `https://${instancia}/service/v2/public/contracts/list?${params}`;

// 3. Función para consultar los contratos
async function consultarContratos() {
    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 info = await response.json();
            const body = info.body || [];
            const pagination = info.pagination || {};

            if (body.length > 0) {
                console.log(`Contratos: ${pagination.total_records} total (página ${pagination.current_page} de ${pagination.total_pages})`);
                body.forEach(contrato => {
                    console.log(`  [${contrato.consecutivo}] ${contrato.propiedad} - ${contrato.estado} - Canon: $${contrato.canon_total}`);
                });
            } else {
                console.log(`Mensaje: ${info.message || 'Sin resultados'}`);
            }
        } else {
            console.log('Error al consultar los contratos.');
            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
consultarContratos();
Power Query M (Excel / Power BI)
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 Login

    // 2. Prepara la dirección de la petición con parámetros
    url = "https://" & instancia & "/service/v2/public/contracts/list?page=1&page_size=1000",

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

    // 4. Decodifica la respuesta JSON
    jsonResponse = Json.Document(response),
    body = jsonResponse[body],

    // 5. Convierte el listado en tabla
    tabla = Table.FromList(body, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
    expandido = Table.ExpandRecordColumn(tabla, "Column1",
        {"contrato_id", "consecutivo", "propiedad", "estrato_propiedad", "propietario", "inquilino", "canon_total", "porcentaje_comision", "periodicidad", "estado", "fecha_inicio", "fecha_fin", "fecha_terminacion", "uso", "creado_por"},
        {"ContratoID", "Consecutivo", "Propiedad", "Estrato", "Propietario", "Inquilino", "Canon", "Comision", "Periodicidad", "Estado", "FechaInicio", "FechaFin", "FechaTerminacion", "Uso", "CreadoPor"})
in
    expandido