# Listar Notas [BETA]

<p class="callout warning">**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.</p>

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.

<p class="callout info">**¿Para qué sirve este servicio?**  
Úsalo cuando necesites **recorrer las notas registradas en nuby**. Los casos de uso más frecuentes son:</p>

<div class="page-content" dir="auto" id="bkmrk-conciliar-las-notas-"><div dir="auto">- **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 `desde` y `hasta`.
- **Recorrer resultados largos por páginas** con `page` y `page_size`.
- **Obtener el `nota_id`** para consultar el detalle solo de las notas que vas a mostrar.

---

  </div></div>#### **1. El Endpoint (La dirección web)**

##### **Método y dirección**

<div class="page-content" dir="auto" id="bkmrk-dato-valor-m%C3%A9todo-ge"><div dir="auto"><table style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 23%;"></col><col style="width: 77%;"></col></colgroup><thead><tr><th>Dato</th><th>Valor</th></tr></thead><tbody><tr><td>Método</td><td>`GET`</td></tr><tr><td>Recurso</td><td>`/notes/list`</td></tr><tr><td>Cuerpo de la petición</td><td>No se envía cuerpo</td></tr></tbody></table>

</div></div>```http
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`.

<p class="callout warning">**Importante:** no incluyas `https://` ni barras diagonales (`/`) al final. La dirección se compone así: `https://` + tu instancia + `/service/v2/public/notes/list`.</p>

##### **Encabezados requeridos**

<div class="page-content" dir="auto" id="bkmrk-encabezado-valor-aut"><div dir="auto"><table style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 22%;"></col><col style="width: 78%;"></col></colgroup><thead><tr><th>Encabezado</th><th>Valor</th></tr></thead><tbody><tr><td>`Authorization`</td><td>`Bearer <token>`, con el token obtenido en el servicio **Login**.</td></tr></tbody></table>

</div></div>##### **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`.

<p class="callout info">Si aún no tienes un token, consulta la página [*<span class="tw-font-bold tw-text-arrBlue hover:tw-text-nubyBlue tw-cursor-pointer">Login</span>*](https://docs.nuby.ai/books/api-nuby-v2/page/login) del libro **API nuby V2**.</p>

<div class="page-content" dir="auto" id="bkmrk-"><div dir="auto">  </div></div>#### **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.

<div class="page-content" dir="auto" id="bkmrk-par%C3%A1metro-tipo-reque"><div dir="auto"><table style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 22%;"></col><col style="width: 8%;"></col><col style="width: 9%;"></col><col style="width: 10%;"></col><col style="width: 51%;"></col></colgroup><thead><tr><th>Parámetro</th><th>Tipo</th><th>Requerido</th><th>Default</th><th>Descripción</th></tr></thead><tbody><tr><td>`factura_id`</td><td>entero</td><td>No</td><td>—</td><td>Devuelve solo las notas de esa factura.</td></tr><tr><td>`tipo`</td><td>texto</td><td>No</td><td>—</td><td>`credito` o `debito`.</td></tr><tr><td>`desde`</td><td>fecha</td><td>No</td><td>—</td><td>Fecha inicial en formato `AAAA-MM-DD` (inclusive).</td></tr><tr><td>`hasta`</td><td>fecha</td><td>No</td><td>—</td><td>Fecha final en formato `AAAA-MM-DD` (inclusive).</td></tr><tr><td>`page`</td><td>entero</td><td>No</td><td>`1`</td><td>Número de página, empezando en 1.</td></tr><tr><td>`page_size`</td><td>entero</td><td>No</td><td>`50`</td><td>Registros por página. Máximo `1000`.</td></tr></tbody></table>

</div></div><p class="callout warning">**Importante:** `page`, `page_size` y `factura_id` deben ser enteros positivos; `desde` no puede ser mayor que `hasta`. Un valor inválido produce `400`.</p>

<p class="callout info">**Los filtros se combinan.** Si envías `factura_id` y `tipo`, deben cumplirse ambos.</p>

##### **Ejemplos de dirección**

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

<div class="page-content" dir="auto" id="bkmrk-par%C3%A1metro-regla-mens"><div dir="auto"><table style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 22%;"></col><col style="width: 14%;"></col><col style="width: 64%;"></col></colgroup><thead><tr><th>Parámetro</th><th>Regla</th><th>Mensaje `400`</th></tr></thead><tbody><tr><td>`page`</td><td>Entero positivo. `0`, valores negativos o texto no son válidos.</td><td>`El parámetro "page" debe ser un número positivo.`</td></tr><tr><td>`page_size`</td><td>Entero positivo, con `1000` como máximo.</td><td>`El parámetro "page_size" debe ser un número positivo.`</td></tr><tr><td>`factura_id`</td><td>Entero positivo. Si apunta a una factura de contrato, la respuesta es `409 FACTURA_CONTRATO_NO_SOPORTADA`.</td><td>`VALIDATION_ERROR` con el mensaje del parámetro.</td></tr><tr><td>`tipo`</td><td>Solo admite `credito` o `debito`.</td><td>`VALIDATION_ERROR`: el valor no está permitido.</td></tr><tr><td>`desde`, `hasta`</td><td>Fecha en formato `AAAA-MM-DD`.</td><td>`VALIDATION_ERROR` con el mensaje del parámetro.</td></tr><tr><td>Rango de fechas</td><td>`desde` no puede ser mayor que `hasta`.</td><td>`VALIDATION_ERROR` por rango inválido.</td></tr></tbody></table>

</div></div>##### **Cuándo usar cada filtro**

<div class="page-content" dir="auto" id="bkmrk-filtro-caso-de-uso-p"><div dir="auto"><table style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 22%;"></col><col style="width: 14%;"></col><col style="width: 64%;"></col></colgroup><thead><tr><th>Filtro</th><th>Caso de uso</th><th>Precisión</th></tr></thead><tbody><tr><td>`factura_id`</td><td>Conciliar todas las notas de una factura concreta.</td><td>Exacta: devuelve solo las notas de esa factura.</td></tr><tr><td>`tipo`</td><td>Separar los ajustes que reducen el saldo de los que lo aumentan.</td><td>Exacta: `credito` o `debito`.</td></tr><tr><td>`desde` / `hasta`</td><td>Cerrar un período contable o revisar los ajustes de un mes.</td><td>Por rango de fechas, con ambos extremos incluidos.</td></tr><tr><td>`factura_id` + `tipo`</td><td>Ver solo las notas de crédito o solo las de débito de una factura.</td><td>Exacta: los filtros se combinan con `AND`.</td></tr><tr><td>`page` / `page_size`</td><td>Recorrer un resultado largo sin traer todo de una vez.</td><td>No filtra: solo controla el tamaño y la posición de la página.</td></tr></tbody></table>

  </div></div>#### **3. La Respuesta (¿Qué te entregaremos?)**

```json
{
  "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**

```json
{
  "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.

```json
{
  "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`.

```json
{
  "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**

<div class="page-content" dir="auto" id="bkmrk-campo-descripci%C3%B3n-no"><div dir="auto"><table style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 22%;"></col><col style="width: 78%;"></col></colgroup><thead><tr><th>Campo</th><th>Descripción</th></tr></thead><tbody><tr><td>`nota_id`</td><td>Identificador interno de la nota. Úsalo para consultar el detalle.</td></tr><tr><td>`factura_id`</td><td>Factura anotada.</td></tr><tr><td>`tipo`</td><td>`credito` o `debito`.</td></tr><tr><td>`consecutivo`</td><td>Número de la nota.</td></tr><tr><td>`fecha`</td><td>Fecha de la nota.</td></tr><tr><td>`valor_total`</td><td>Valor total de la nota.</td></tr><tr><td>`estado_id`</td><td>`5` = borrador.</td></tr><tr><td>`clasificacion`</td><td>`1` = vinculante.</td></tr><tr><td>`concepto_id`</td><td>Concepto aplicado a la nota.</td></tr><tr><td>`observaciones`</td><td>Observaciones registradas.</td></tr></tbody></table>

</div></div>##### **Campos de paginación**

<div class="page-content" dir="auto" id="bkmrk-campo-significado-ca"><div dir="auto"><table style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 22%;"></col><col style="width: 14%;"></col><col style="width: 64%;"></col></colgroup><thead><tr><th>Campo</th><th>Significado</th><th>Caso sin resultados</th></tr></thead><tbody><tr><td>`page`</td><td>Número de página devuelta, empezando en `1`.</td><td>Conserva la página solicitada (`1` por defecto).</td></tr><tr><td>`page_size`</td><td>Cantidad de registros por página efectivamente aplicada.</td><td>Conserva el tamaño solicitado (`50` por defecto).</td></tr><tr><td>`total`</td><td>Total de notas que cumplen los filtros.</td><td>`0`.</td></tr><tr><td>`total_pages`</td><td>Total de páginas disponibles para ese resultado.</td><td>`0`. Úsalo como condición de fin al recorrer páginas.</td></tr></tbody></table>

</div></div>##### **`filters_applied` y `message`**

<div class="page-content" dir="auto" id="bkmrk-sin-filtros%2C-filters"><div dir="auto">- Sin filtros, `filters_applied` es `null`.
- Con filtros, es un objeto con los filtros usados.
- Con resultados, `message` es `null`.
- Sin resultados, `message` es `No se encontraron notas con los filtros aplicados.` y `body` es `[]`.

</div></div>##### **Campos del envelope**

<div class="page-content" dir="auto" id="bkmrk-campo-contenido-cu%C3%A1n"><div dir="auto"><table style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 22%;"></col><col style="width: 14%;"></col><col style="width: 64%;"></col></colgroup><thead><tr><th>Campo</th><th>Contenido</th><th>Cuándo cambia</th></tr></thead><tbody><tr><td>`status`</td><td>`200` en una lectura exitosa.</td><td>Los errores usan su propio código HTTP y agregan `error_code`.</td></tr><tr><td>`message`</td><td>Texto informativo o `null`.</td><td>Deja de ser `null` cuando la lista viene vacía.</td></tr><tr><td>`body`</td><td>Arreglo de notas con los campos del listado.</td><td>Es `[]` cuando no hay coincidencias.</td></tr><tr><td>`pagination`</td><td>Objeto con `page`, `page_size`, `total` y `total_pages`.</td><td>`total` y `total_pages` pasan a `0` sin resultados.</td></tr><tr><td>`filters_applied`</td><td>Objeto con los filtros usados, o `null`.</td><td>Es `null` solo cuando no enviaste ningún filtro.</td></tr></tbody></table>

</div></div><p class="callout info">**Una lista vacía no es un error.** Se responde `200`; revisa `pagination.total` para confirmar que no hay coincidencias.</p>

##### **Cómo interpretar el resultado**

<div class="page-content" dir="auto" id="bkmrk-se%C3%B1al-en-la-respuest"><div dir="auto"><table style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 34%;"></col><col style="width: 14%;"></col><col style="width: 52%;"></col></colgroup><thead><tr><th>Señal en la respuesta</th><th>Qué significa</th><th>Qué hacer</th></tr></thead><tbody><tr><td>`body` con notas y `message: null`</td><td>La consulta encontró coincidencias.</td><td>Procesa cada nota y, si hay más páginas, avanza con `page`.</td></tr><tr><td>`body: []` y `total: 0`</td><td>Ninguna nota cumple los filtros enviados.</td><td>Revisa los filtros; no lo trates como un fallo técnico.</td></tr><tr><td>`filters_applied: null`</td><td>No se aplicó ningún filtro.</td><td>Confirma que enviaste los parámetros en la dirección web.</td></tr><tr><td>`400 VALIDATION_ERROR`</td><td>Un parámetro no cumple su regla y la consulta no se ejecutó.</td><td>Corrige el parámetro que indica el mensaje y repite.</td></tr><tr><td>`409 FACTURA_CONTRATO_NO_SOPORTADA`</td><td>El `factura_id` pertenece a una factura de contrato.</td><td>Gestiona esas notas desde el flujo de contratos; no reintentes igual.</td></tr></tbody></table>

</div></div><p class="callout warning">**Orden:** las notas se devuelven por fecha descendente y, a igualdad de fecha, por identificador descendente. El orden es estable entre páginas.</p>

<div class="page-content" dir="auto" id="bkmrk--1"><div dir="auto">  </div></div>#### **4. Seguridad y Posibles Errores**

##### **Reglas y exclusiones**

La API solo expone notas de **facturas de venta**:

<div class="page-content" dir="auto" id="bkmrk-el-listado-nunca-inc"><div dir="auto">- 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_SOPORTADA` con `warnings[]`.

</div></div>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**

<div class="page-content" dir="auto" id="bkmrk-http-error_code-cu%C3%A1n"><div dir="auto"><table style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 22%;"></col><col style="width: 14%;"></col><col style="width: 64%;"></col></colgroup><thead><tr><th>HTTP</th><th>`error_code`</th><th>Cuándo ocurre y cómo resolverlo</th></tr></thead><tbody><tr><td>`400`</td><td>`VALIDATION_ERROR`</td><td>Algún parámetro tiene un valor inválido. Revisa `page`, `page_size`, `factura_id`, `tipo`, `desde` o `hasta`.</td></tr><tr><td>`401`</td><td>—</td><td>Falta el token o expiró. Vuelve a consumir **Login**.</td></tr><tr><td>`403`</td><td>`RECURSO_NO_AUTORIZADO`</td><td>Al cliente OAuth le falta `catalogs:read`.</td></tr><tr><td>`409`</td><td>`FACTURA_CONTRATO_NO_SOPORTADA`</td><td>Filtraste por una factura de contrato. Incluye `warnings[]`.</td></tr><tr><td>`500`</td><td>`INTERNAL_ERROR`</td><td>Fallo interno al consultar. Reintenta; si persiste, contacta a soporte.</td></tr></tbody></table>

</div></div>##### **Errores frecuentes al paginar**

<div class="page-content" dir="auto" id="bkmrk-situaci%C3%B3n-qu%C3%A9-ocurre"><div dir="auto"><table style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 34%;"></col><col style="width: 14%;"></col><col style="width: 52%;"></col></colgroup><thead><tr><th>Situación</th><th>Qué ocurre</th><th>Cómo corregir</th></tr></thead><tbody><tr><td>Envías `page=0` o `page=abc`</td><td>`400 VALIDATION_ERROR`; la consulta no se ejecuta.</td><td>Usa un entero desde `1`.</td></tr><tr><td>Envías `page_size=0` o un valor negativo</td><td>`400 VALIDATION_ERROR`.</td><td>Usa un entero positivo, con `1000` como máximo.</td></tr><tr><td>Recorres páginas hasta recibir una vacía</td><td>Puedes hacer una petición de más o detenerte antes de tiempo.</td><td>Recorre hasta `pagination.total_pages`.</td></tr><tr><td>Esperas que una lista vacía traiga `filters_applied: null`</td><td>`filters_applied` refleja los filtros enviados, no el resultado.</td><td>Revisa `body` y `pagination.total` para detectar la lista vacía.</td></tr></tbody></table>

</div></div><p class="callout danger">**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.</p>

<div class="page-content" dir="auto" id="bkmrk--2"><div dir="auto">  ---

</div></div>#### **5. Ejemplos de integración**

<div class="page-content" dir="auto" id="bkmrk-curl-token%3D%22tu_token"><div dir="auto"><details><summary>cURL</summary>

```bash
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}"
```

</details><details><summary>PHP</summary>

```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";
}
```

</details><details><summary>Python</summary>

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

</details><details><summary>JavaScript (Fetch API)</summary>

```javascript
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}`);
}
```

</details><details><summary>Power Query M (Excel / Power BI)</summary>

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.

```m
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
```

</details></div></div>#### **6. Buenas prácticas y límites conocidos**

<div class="page-content" dir="auto" id="bkmrk-filtra-por-factura_i"><div dir="auto">- **Filtra por `factura_id`** cuando busques las notas de un documento concreto.
- **Usa `desde` y `hasta` en 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 [*<span class="tw-font-bold tw-text-arrBlue hover:tw-text-nubyBlue tw-cursor-pointer">Buscar Nota por Código</span>*](https://docs.nuby.ai/books/api-nuby-v2/page/buscar-nota-por-codigo).
- **Guarda el `nota_id`** para evitar búsquedas repetidas.

</div></div>##### **Límites del listado**

<div class="page-content" dir="auto" id="bkmrk-solo-expone-notas-de"><div dir="auto">- 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.

</div></div><p class="callout info">Si necesitas crear una nota, revisa la página [*<span class="tw-font-bold tw-text-arrBlue hover:tw-text-nubyBlue tw-cursor-pointer">Crear Nota</span>*](https://docs.nuby.ai/books/api-nuby-v2/page/crear-nota).</p>