Listar Notas [BETA]
Funcionalidad en desarrollo y pruebas: este servicio está disponible en el ambiente de pruebas y todavía no debe usarse en producción. El funcionamiento, los campos y los mensajes de error pueden cambiar antes del despliegue definitivo.
Este servicio devuelve una lista paginada de notas de crédito y débito registradas en nuby, con sus datos principales. Puedes filtrar por factura, por tipo de nota y por rango de fechas.
Úsalo para conciliar las notas de una factura con tu plataforma, para construir un historial de ajustes o para verificar qué notas se crearon en un período.
¿Para qué sirve este servicio?
Úsalo cuando necesites recorrer las notas registradas en nuby. Los casos de uso más frecuentes son:
- Conciliar las notas de una factura con tu plataforma, filtrando por
factura_id. - Construir un historial de ajustes separando las notas de crédito de las de débito con
tipo. - Cerrar un período contable revisando las notas creadas entre dos fechas con
desdeyhasta. - Recorrer resultados largos por páginas con
pageypage_size. - Obtener el
nota_idpara consultar el detalle solo de las notas que vas a mostrar.
1. El Endpoint (La dirección web)
Método y dirección
| Dato | Valor |
|---|---|
| Método | GET |
| Recurso | /notes/list |
| Cuerpo de la petición | No se envía cuerpo |
GET https://{{instancia}}/service/v2/public/notes/list
¿Qué debo colocar en {{instancia}}?
La dirección web principal con la que ingresas a tu plataforma, incluyendo la terminación .nuby.app o .arrendasoft.co.
Importante: no incluyas https:// ni barras diagonales (/) al final. La dirección se compone así: https:// + tu instancia + /service/v2/public/notes/list.
Encabezados requeridos
| Encabezado | Valor |
|---|---|
Authorization |
Bearer <token>, con el token obtenido en el servicio Login. |
Permiso requerido (scope): catalogs:read
Este servicio es de solo lectura y exige el permiso catalogs:read. Si falta, la respuesta es 403 con RECURSO_NO_AUTORIZADO.
Si aún no tienes un token, consulta la página Login del libro API nuby V2.
2. La Petición (¿Qué debes enviarnos?)
Todos son opcionales y se envían en la dirección web. Sin filtros, recibes la primera página con las últimas 50 notas.
| Parámetro | Tipo | Requerido | Default | Descripción |
|---|---|---|---|---|
factura_id |
entero | No | — | Devuelve solo las notas de esa factura. |
tipo |
texto | No | — | credito o debito. |
desde |
fecha | No | — | Fecha inicial en formato AAAA-MM-DD (inclusive). |
hasta |
fecha | No | — | Fecha final en formato AAAA-MM-DD (inclusive). |
page |
entero | No | 1 |
Número de página, empezando en 1. |
page_size |
entero | No | 50 |
Registros por página. Máximo 1000. |
Importante: page, page_size y factura_id deben ser enteros positivos; desde no puede ser mayor que hasta. Un valor inválido produce 400.
Los filtros se combinan. Si envías factura_id y tipo, deben cumplirse ambos.
Ejemplos de dirección
GET /notes/list?factura_id=456
GET /notes/list?tipo=credito&desde=2026-10-01&hasta=2026-10-31
GET /notes/list?page=2&page_size=20
Validaciones de parámetros
Los parámetros se validan antes de ejecutar la consulta. Si uno no cumple su regla, la respuesta es 400 VALIDATION_ERROR y no se devuelve ningún dato:
| Parámetro | Regla | Mensaje 400 |
|---|---|---|
page |
Entero positivo. 0, valores negativos o texto no son válidos. |
El parámetro "page" debe ser un número positivo. |
page_size |
Entero positivo, con 1000 como máximo. |
El parámetro "page_size" debe ser un número positivo. |
factura_id |
Entero positivo. Si apunta a una factura de contrato, la respuesta es 409 FACTURA_CONTRATO_NO_SOPORTADA. |
VALIDATION_ERROR con el mensaje del parámetro. |
tipo |
Solo admite credito o debito. |
VALIDATION_ERROR: el valor no está permitido. |
desde, hasta |
Fecha en formato AAAA-MM-DD. |
VALIDATION_ERROR con el mensaje del parámetro. |
| Rango de fechas | desde no puede ser mayor que hasta. |
VALIDATION_ERROR por rango inválido. |
Cuándo usar cada filtro
| Filtro | Caso de uso | Precisión |
|---|---|---|
factura_id |
Conciliar todas las notas de una factura concreta. | Exacta: devuelve solo las notas de esa factura. |
tipo |
Separar los ajustes que reducen el saldo de los que lo aumentan. | Exacta: credito o debito. |
desde / hasta |
Cerrar un período contable o revisar los ajustes de un mes. | Por rango de fechas, con ambos extremos incluidos. |
factura_id + tipo |
Ver solo las notas de crédito o solo las de débito de una factura. | Exacta: los filtros se combinan con AND. |
page / page_size |
Recorrer un resultado largo sin traer todo de una vez. | No filtra: solo controla el tamaño y la posición de la página. |
3. La Respuesta (¿Qué te entregaremos?)
{
"status": 200,
"message": null,
"body": [
{
"nota_id": 789,
"factura_id": 456,
"tipo": "credito",
"consecutivo": 1024,
"fecha": "2026-10-21",
"valor_total": 59500,
"estado_id": 5,
"clasificacion": 1,
"concepto_id": 6,
"observaciones": "Ajuste acordado"
}
],
"pagination": {
"page": 1,
"page_size": 50,
"total": 1,
"total_pages": 1
},
"filters_applied": {
"factura_id": 456,
"tipo": "credito"
}
}
Variantes de respuesta
El envelope cambia según los filtros enviados y según haya o no coincidencias. Estos son los tres casos que debes manejar en tu integración:
Con filtros
{
"status": 200,
"message": null,
"body": [
{
"nota_id": 789,
"factura_id": 456,
"tipo": "credito",
"consecutivo": 1024,
"fecha": "2026-10-21",
"valor_total": 59500,
"estado_id": 5,
"clasificacion": 1,
"concepto_id": 6,
"observaciones": "Ajuste acordado"
}
],
"pagination": { "page": 1, "page_size": 50, "total": 1, "total_pages": 1 },
"filters_applied": { "factura_id": 456, "tipo": "credito" }
}
Sin filtros
Cuando no envías ningún filtro, filters_applied es null y recibes la primera página de todas las notas de venta, ordenadas por fecha descendente.
{
"status": 200,
"message": null,
"body": [
{
"nota_id": 789,
"factura_id": 456,
"tipo": "credito",
"consecutivo": 1024,
"fecha": "2026-10-21",
"valor_total": 59500,
"estado_id": 5,
"clasificacion": 1,
"concepto_id": 6,
"observaciones": "Ajuste acordado"
},
{
"nota_id": 790,
"factura_id": 457,
"tipo": "debito",
"consecutivo": 1025,
"fecha": "2026-10-20",
"valor_total": 20000,
"estado_id": 5,
"clasificacion": 1,
"concepto_id": 8,
"observaciones": "Cargo adicional"
}
],
"pagination": { "page": 1, "page_size": 50, "total": 2, "total_pages": 1 },
"filters_applied": null
}
Lista vacía
No es un error: el servicio responde 200, body vacío y un mensaje informativo. En este ejemplo sí se enviaron filtros, por eso filters_applied no es null.
{
"status": 200,
"message": "No se encontraron notas con los filtros aplicados.",
"body": [],
"pagination": { "page": 1, "page_size": 50, "total": 0, "total_pages": 0 },
"filters_applied": {
"tipo": "debito",
"desde": "2026-09-01",
"hasta": "2026-09-30"
}
}
Campos de cada nota
| Campo | Descripción |
|---|---|
nota_id |
Identificador interno de la nota. Úsalo para consultar el detalle. |
factura_id |
Factura anotada. |
tipo |
credito o debito. |
consecutivo |
Número de la nota. |
fecha |
Fecha de la nota. |
valor_total |
Valor total de la nota. |
estado_id |
5 = borrador. |
clasificacion |
1 = vinculante. |
concepto_id |
Concepto aplicado a la nota. |
observaciones |
Observaciones registradas. |
Campos de paginación
| Campo | Significado | Caso sin resultados |
|---|---|---|
page |
Número de página devuelta, empezando en 1. |
Conserva la página solicitada (1 por defecto). |
page_size |
Cantidad de registros por página efectivamente aplicada. | Conserva el tamaño solicitado (50 por defecto). |
total |
Total de notas que cumplen los filtros. | 0. |
total_pages |
Total de páginas disponibles para ese resultado. | 0. Úsalo como condición de fin al recorrer páginas. |
filters_applied y message
- Sin filtros,
filters_appliedesnull. - Con filtros, es un objeto con los filtros usados.
- Con resultados,
messageesnull. - Sin resultados,
messageesNo se encontraron notas con los filtros aplicados.ybodyes[].
Campos del envelope
| Campo | Contenido | Cuándo cambia |
|---|---|---|
status |
200 en una lectura exitosa. |
Los errores usan su propio código HTTP y agregan error_code. |
message |
Texto informativo o null. |
Deja de ser null cuando la lista viene vacía. |
body |
Arreglo de notas con los campos del listado. | Es [] cuando no hay coincidencias. |
pagination |
Objeto con page, page_size, total y total_pages. |
total y total_pages pasan a 0 sin resultados. |
filters_applied |
Objeto con los filtros usados, o null. |
Es null solo cuando no enviaste ningún filtro. |
Una lista vacía no es un error. Se responde 200; revisa pagination.total para confirmar que no hay coincidencias.
Cómo interpretar el resultado
| Señal en la respuesta | Qué significa | Qué hacer |
|---|---|---|
body con notas y message: null |
La consulta encontró coincidencias. | Procesa cada nota y, si hay más páginas, avanza con page. |
body: [] y total: 0 |
Ninguna nota cumple los filtros enviados. | Revisa los filtros; no lo trates como un fallo técnico. |
filters_applied: null |
No se aplicó ningún filtro. | Confirma que enviaste los parámetros en la dirección web. |
400 VALIDATION_ERROR |
Un parámetro no cumple su regla y la consulta no se ejecutó. | Corrige el parámetro que indica el mensaje y repite. |
409 FACTURA_CONTRATO_NO_SOPORTADA |
El factura_id pertenece a una factura de contrato. |
Gestiona esas notas desde el flujo de contratos; no reintentes igual. |
Orden: las notas se devuelven por fecha descendente y, a igualdad de fecha, por identificador descendente. El orden es estable entre páginas.
4. Seguridad y Posibles Errores
Reglas y exclusiones
La API solo expone notas de facturas de venta:
- El listado nunca incluye notas de facturas de contrato, aunque no envíes
factura_id. - Si filtras por una factura de contrato, la respuesta es
409 FACTURA_CONTRATO_NO_SOPORTADAconwarnings[].
La nota se devuelve con el estado que tiene en nuby. Las notas creadas por la API están en borrador hasta que un usuario las emite en la interfaz.
Errores del contrato de la operación
| HTTP | error_code |
Cuándo ocurre y cómo resolverlo |
|---|---|---|
400 |
VALIDATION_ERROR |
Algún parámetro tiene un valor inválido. Revisa page, page_size, factura_id, tipo, desde o hasta. |
401 |
— | Falta el token o expiró. Vuelve a consumir Login. |
403 |
RECURSO_NO_AUTORIZADO |
Al cliente OAuth le falta catalogs:read. |
409 |
FACTURA_CONTRATO_NO_SOPORTADA |
Filtraste por una factura de contrato. Incluye warnings[]. |
500 |
INTERNAL_ERROR |
Fallo interno al consultar. Reintenta; si persiste, contacta a soporte. |
Errores frecuentes al paginar
| Situación | Qué ocurre | Cómo corregir |
|---|---|---|
Envías page=0 o page=abc |
400 VALIDATION_ERROR; la consulta no se ejecuta. |
Usa un entero desde 1. |
Envías page_size=0 o un valor negativo |
400 VALIDATION_ERROR. |
Usa un entero positivo, con 1000 como máximo. |
| Recorres páginas hasta recibir una vacía | Puedes hacer una petición de más o detenerte antes de tiempo. | Recorre hasta pagination.total_pages. |
Esperas que una lista vacía traiga filters_applied: null |
filters_applied refleja los filtros enviados, no el resultado. |
Revisa body y pagination.total para detectar la lista vacía. |
Atención: una factura de contrato no es un error de parámetro: el servicio la rechaza explícitamente para no exponer notas de ese flujo.
5. Ejemplos de integración
cURL
TOKEN="TU_TOKEN_AQUI"
INSTANCIA="tu-inmobiliaria.nuby.app"
# Notas de una factura
curl -G "https://${INSTANCIA}/service/v2/public/notes/list" \
--data-urlencode "factura_id=456" \
-H "Authorization: Bearer ${TOKEN}"
# Notas de crédito de octubre, página 1 de 20
curl -G "https://${INSTANCIA}/service/v2/public/notes/list" \
--data-urlencode "tipo=credito" \
--data-urlencode "desde=2026-10-01" \
--data-urlencode "hasta=2026-10-31" \
--data-urlencode "page=1" \
--data-urlencode "page_size=20" \
-H "Authorization: Bearer ${TOKEN}"
PHP
<?php
$instancia = 'tu-inmobiliaria.nuby.app';
$token = 'TU_TOKEN_AQUI';
$query = http_build_query([
'factura_id' => 456,
'page' => 1,
'page_size' => 50,
]);
$url = "https://{$instancia}/service/v2/public/notes/list?{$query}";
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer {$token}",
]);
$respuesta = curl_exec($ch);
$codigo = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$datos = json_decode($respuesta, true);
echo "HTTP: {$codigo}\n";
echo "Total: " . ($datos['pagination']['total'] ?? 0) . "\n";
foreach ($datos['body'] as $nota) {
echo $nota['nota_id'] . ' - ' . $nota['tipo'] . ' - ' . $nota['valor_total'] . "\n";
}
Python
import requests
instancia = "tu-inmobiliaria.nuby.app"
token = "TU_TOKEN_AQUI"
url = f"https://{instancia}/service/v2/public/notes/list"
headers = {
"Authorization": f"Bearer {token}",
}
pagina = 1
total_paginas = 1
while pagina <= total_paginas:
respuesta = requests.get(
url,
headers=headers,
params={"tipo": "credito", "desde": "2026-10-01", "hasta": "2026-10-31",
"page": pagina, "page_size": 50},
timeout=30,
)
if respuesta.status_code != 200:
print(respuesta.status_code, respuesta.json())
break
datos = respuesta.json()
total_paginas = datos["pagination"]["total_pages"]
for nota in datos["body"]:
print(nota["nota_id"], nota["tipo"], nota["valor_total"])
pagina += 1
JavaScript (Fetch API)
const instancia = 'tu-inmobiliaria.nuby.app';
const token = 'TU_TOKEN_AQUI';
const params = new URLSearchParams({
factura_id: '456',
page: '1',
page_size: '50'
});
const url = `https://${instancia}/service/v2/public/notes/list?${params}`;
const respuesta = await fetch(url, {
headers: { 'Authorization': `Bearer ${token}` }
});
const data = await respuesta.json();
if (respuesta.ok) {
console.log(`Página ${data.pagination.page} de ${data.pagination.total_pages}`);
data.body.forEach(n => console.log(n.nota_id, n.tipo, n.valor_total));
} else {
console.error(`${respuesta.status} ${data.error_code}: ${data.message}`);
}
Power Query M (Excel / Power BI)
Power Query consulta una página por vez. El paso pagination te permite parametrizar la página y combinar varias con Table.Combine si necesitas el historial completo.
let
// 1. Configura tus datos de acceso
instancia = "tu-inmobiliaria.nuby.app",
token = "TU_TOKEN_AQUI",
// 2. Prepara la dirección con los filtros y la página
url = "https://" & instancia & "/service/v2/public/notes/list?factura_id=456&page=1&page_size=1000",
// 3. Envía la petición GET
response = Web.Contents(url, [
Headers = [
#"Authorization" = "Bearer " & token
]
]),
// 4. Decodifica el envelope
jsonResponse = Json.Document(response),
body = jsonResponse[body],
pagination = jsonResponse[pagination],
// 5. Convierte el listado en tabla
tabla = Table.FromList(body, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
expandido = Table.ExpandRecordColumn(tabla, "Column1",
{"nota_id", "factura_id", "tipo", "consecutivo", "fecha", "valor_total",
"estado_id", "clasificacion", "concepto_id", "observaciones"},
{"NotaID", "FacturaID", "Tipo", "Consecutivo", "Fecha", "ValorTotal",
"EstadoID", "Clasificacion", "ConceptoID", "Observaciones"}),
tipos = Table.TransformColumnTypes(expandido, {
{"NotaID", Int64.Type},
{"FacturaID", Int64.Type},
{"Consecutivo", Int64.Type},
{"Fecha", type date},
{"ValorTotal", type number}
}),
totalPaginas = pagination[total_pages]
in
tipos
6. Buenas prácticas y límites conocidos
- Filtra por
factura_idcuando busques las notas de un documento concreto. - Usa
desdeyhastaen lugar de paginar meses completos. - Recorre hasta
total_pages, no hasta una página vacía. - No uses la lista como detalle: los ítems y el saldo de la factura están en la página Buscar Nota por Código.
- Guarda el
nota_idpara evitar búsquedas repetidas.
Límites del listado
- Solo expone notas de facturas de venta; las de contrato nunca aparecen.
- No devuelve los ítems ni el saldo de la factura: eso está en el detalle de la nota.
- El estado corresponde al que tiene la nota en nuby; las creadas por la API están en borrador.
Si necesitas crear una nota, revisa la página Crear Nota.