Ir al contenido principal

Catálogos de Facturación [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.

Estos servicios devuelven los catálogos que necesitas para crear facturas y notas en nuby: resoluciones de venta, conceptos de nota, productos con sus impuestos y estados de factura. Así evitas escribir identificadores fijos en tu plataforma.

Los cuatro son de solo lectura: no crean, no modifican y no consumen referencias de idempotencia.

¿Para qué sirve este servicio?
Úsalos cuando necesites traducir los identificadores de nuby a datos legibles, o al revés, sin mantener copias propias de la configuración. Los casos de uso más frecuentes son:

  • Elegir la resolución de venta que vas a enviar en resolucion_id al crear o editar una factura.
  • Obtener el concepto_id de las notas de crédito y de las notas débito que vas a crear.
  • Tomar los impuestos del producto (tipo_iva_id, por_iva y sus equivalentes de retención y reteICA) y enviarlos en items[] de una factura o de una nota.
  • Traducir el estado_id de una factura al significado que ves en la interfaz de nuby.
  • Evitar identificadores fijos en tu plataforma: los conceptos y productos dependen de la configuración de tu instancia.

1. El Endpoint (La dirección web)

Método y direcciones
Método Recurso Catálogo que devuelve
GET /invoices/sales/resolutions Resoluciones de venta
GET /masters/note-concepts Conceptos de nota
GET /masters/products Productos e impuestos
GET /masters/invoice-statuses Estados de factura

Ninguno de los cuatro recibe cuerpo en la petición ni exige referencia_externa: no son idempotentes y no escriben en la base.

GET https://{{instancia}}/service/v2/public/invoices/sales/resolutions
GET https://{{instancia}}/service/v2/public/masters/note-concepts
GET https://{{instancia}}/service/v2/public/masters/products
GET https://{{instancia}}/service/v2/public/masters/invoice-statuses
¿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, sin https:// y sin barras diagonales al final. Si entras a nuby escribiendo inmobiliaria.nuby.app en el navegador, esa es tu instancia.

Importante: no incluyas https:// ni barras diagonales (/) al final. La dirección se compone así: https:// + tu instancia + /service/v2/public/ + la ruta del catálogo.

Encabezados requeridos
Encabezado Valor
Authorization Bearer <token>, con el token obtenido en el servicio Login.

Los cuatro servicios exigen el encabezado Authorization.

Permiso requerido (scope): catalogs:read

Los cuatro servicios exigen el permiso catalogs:read. Si falta, la respuesta es 403 con RECURSO_NO_AUTORIZADO.

¿Por qué catalogs:read y no un permiso de facturas? Las lecturas de la API usan catalogs:read porque el cliente nuby-clientes no tiene un scope de lectura de facturas y exigirlo dejaría los endpoints inutilizables. En tu cliente OAuth los permisos de consulta disponibles son catalogs:read, invoices:create, invoices:update, notes:create y third-parties:create; leer se autoriza con catalogs:read.

Si aún no tienes un token, consulta la página Login del libro API nuby V2.

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

Los catálogos se consultan con GET y sin cuerpo: lo único que puedes enviar son parámetros de consulta en la dirección. Todos son opcionales; si no envías ninguno, el servicio devuelve la primera página del catálogo completo.

Resoluciones de venta — GET /invoices/sales/resolutions
GET https://{{instancia}}/service/v2/public/invoices/sales/resolutions

Devuelve las resoluciones de facturación de venta, es decir, las que puedes enviar en resolucion_id al crear o editar una factura. Las resoluciones reservadas para facturas de contrato (inquilino y propietario) no aparecen en esta lista.

Usa este servicio, no el anterior. El endpoint GET /invoices/resolutions sigue existiendo por compatibilidad, pero puede devolver resoluciones de contrato, y la API de venta las rechaza con 422 RESOLUCION_CONTRATO_NO_PERMITIDA.

Parámetros de consulta
Parámetro Tipo Requerido Descripción
activa texto No SI o NO.
tipo_doc_id entero No Tipo de documento de la resolución.
fact_electronica texto No SI o NO.
resolucion_para entero No 1 factura o 2 documento soporte.
fecha_desde / fecha_hasta fecha No Rango sobre la fecha de la resolución (AAAA-MM-DD).
fecha_vigencia_desde / fecha_vigencia_hasta fecha No Rango sobre la vigencia (AAAA-MM-DD).
page entero No Número de página, empezando en 1. Por defecto 1.
page_size entero No Registros por página. Por defecto 10. Máximo 1000.
Conceptos de nota — GET /masters/note-concepts
GET https://{{instancia}}/service/v2/public/masters/note-concepts?target=2

Devuelve los conceptos que puedes enviar en concepto_id al crear una nota. El campo target indica el tipo: 1 = nota crédito y 2 = nota débito.

Parámetro Tipo Requerido Descripción
target entero No 1 nota crédito o 2 nota débito. Sin filtro devuelve todos.
page entero No Número de página, empezando en 1. Por defecto 1.
page_size entero No Registros por página. Por defecto 50. Máximo 1000.
Productos e impuestos — GET /masters/products
GET https://{{instancia}}/service/v2/public/masters/products?search=plan&estado=1

Devuelve los productos que puedes usar en items[] de una factura o nota, con los porcentajes de IVA, retención en la fuente, reteIVA y reteICA configurados.

Parámetro Tipo Requerido Descripción
search texto No Busca coincidencias en el nombre del producto y en su código.
estado entero No 1 activos, 0 inactivos. Sin filtro devuelve todos.
page entero No Número de página, empezando en 1. Por defecto 1.
page_size entero No Registros por página. Por defecto 50. Máximo 1000.
Estados de factura — GET /masters/invoice-statuses
GET https://{{instancia}}/service/v2/public/masters/invoice-statuses

Devuelve el significado de cada estado_id que aparece en las respuestas de factura. No recibe parámetros: entrega el catálogo completo.

Parámetros inválidos: si page, page_size, activa, tipo_doc_id, fact_electronica, resolucion_para, una fecha, target o estado no tienen un valor válido, la respuesta es 400 con VALIDATION_ERROR. page y page_size deben ser enteros mayores que cero.

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

Los cuatro catálogos responden con el mismo envelope de las lecturas de la API: el estado, el mensaje, el cuerpo con los registros y el bloque de paginación.

Estructura principal de la respuesta
Campo Tipo Descripción
status integer Código del estado de la respuesta. 200 cuando la consulta fue exitosa.
message string null cuando la consulta fue exitosa.
body array Registros del catálogo consultado. En un error, este campo no existe.
pagination object Resumen de la página: total_records, total_pages, current_page, page_size, current_page_records, has_next_page y has_previous_page.
filters_applied object Filtros que aplicó el servicio (por ejemplo {"target": 2}). Llega en null cuando la consulta no llevaba filtros.
Resoluciones de venta

Cada elemento de body describe una resolución de venta:

{
  "status": 200,
  "message": null,
  "body": [
    {
      "resolucion_id": 1,
      "tipo_doc_id": 1,
      "tipo_doc": "Factura electronica de venta",
      "resolucion_numero": "18760000001",
      "consecutivo_iniciar": 1,
      "consecutivo_inicial": 1,
      "consecutivo_final": 5000,
      "fecha": "2026-01-01",
      "fecha_vigencia": "2027-01-01",
      "prefijo": "FE",
      "dias_vencimiento": 30,
      "activa": "SI",
      "fact_electronica": "SI",
      "resolucion_para": 1
    }
  ],
  "pagination": {
    "total_records": 1,
    "total_pages": 1,
    "current_page": 1,
    "page_size": 10,
    "current_page_records": 1,
    "has_next_page": false,
    "has_previous_page": false
  },
  "filters_applied": null
}

El prefijo y el dias_vencimiento son los que nuby usa al crear la factura si no envías fecha_vencimiento.

Conceptos de nota

Cada elemento de body trae el id que se envía en concepto_id, su tipo (target), el código y el nombre:

{
  "status": 200,
  "message": null,
  "body": [
    { "id": 9, "target": 2, "codigo": "2", "nombre": "Gastos por cobrar", "estado": 1 },
    { "id": 10, "target": 2, "codigo": "4", "nombre": "Otros", "estado": 1 }
  ],
  "pagination": { "total_records": 2, "total_pages": 1, "current_page": 1, "page_size": 50, "current_page_records": 2, "has_next_page": false, "has_previous_page": false },
  "filters_applied": { "target": 2 }
}

Si no envías concepto_id al crear una nota, nuby aplica el concepto por defecto del tipo. Envíalo solo cuando necesites un concepto específico.

Productos e impuestos

Cada elemento de body describe un producto con sus datos y los porcentajes configurados:

{
  "producto_id": 159,
  "producto": "Plan X",
  "descripcion": "Plan administrativo",
  "codigo": "PLAN-X",
  "valor_unitario": 100000,
  "tipo_iva_id": 1,
  "por_iva": 19,
  "tipo_retencion_id": 1,
  "por_retencion": 2.5,
  "tipo_reteiva_id": null,
  "por_reteiva": null,
  "tipo_reteica_id": null,
  "por_reteica": null,
  "estado": 1
}

Los porcentajes no se calculan solos. Al crear la factura o la nota envía tipo_iva_id y por_iva (y sus equivalentes de retención) tomados de este catálogo. Si el producto trae null, envía null y el impuesto no se aplica.

Estados de factura

Cada elemento de body empareja el estado_id con su nombre, ordenado por estado_id:

estado_id Estado Qué significa
1 Facturado Emitida con consecutivo y enviada a la DIAN.
2 Anulado Anulada.
3 Pagada Saldo en cero.
4 Contabilizada Contabilidad cerrada.
5 Borrador Creada por la API, editable, aún sin número legal.
6 Anulada por nota crédito Una nota crédito total la dejó en saldo cero.
7 Anulado por nota ajuste Anulada por un ajuste.

Puedes consultar este catálogo una vez y guardarlo en tu sistema: los estados son fijos.

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 sistema te bloquea el acceso con un error 401 y tu sistema debe volver a consumir el servicio de Login para pedir un pase nuevo.

Las causas de rechazo de los catálogos ya documentadas son estas:

Código HTTP error_code Cuándo ocurre
400 VALIDATION_ERROR Un parámetro tiene un valor inválido (por ejemplo page=0, target=3 o una fecha mal formada).
401 — Falta el encabezado Authorization o el token no es válido.
403 RECURSO_NO_AUTORIZADO El token no tiene el permiso catalogs:read.
500 INTERNAL_ERROR Fallo interno al consultar la base. Reintenta más tarde.

Un parámetro inválido rechaza la consulta completa con 400 VALIDATION_ERROR. Corrige el valor y repite la petición.

Así se ve el rechazo por permisos:

{
  "success": false,
  "status": 403,
  "message": "El consumidor no tiene habilitado el recurso solicitado.",
  "error_code": "RECURSO_NO_AUTORIZADO"
}

5. Ejemplos de integración

Los ejemplos consultan el catálogo de resoluciones de venta; la misma forma de llamada sirve para los otros tres catálogos, cambiando solo la ruta. Tratan el caso feliz, el rechazo por parámetro inválido (400 VALIDATION_ERROR) y el rechazo por permisos (403 RECURSO_NO_AUTORIZADO).

cURL
TOKEN="TU_TOKEN_AQUI"
INSTANCIA="mi-inmobiliaria.nuby.app"

# 1. Primera página de resoluciones activas
curl --silent --show-error --write-out "\nHTTP %{http_code}\n" \
  "https://${INSTANCIA}/service/v2/public/invoices/sales/resolutions?activa=SI&page=1&page_size=10" \
  -H "Authorization: Bearer ${TOKEN}"

# 2. Un parámetro inválido devuelve 400 VALIDATION_ERROR
curl --silent --show-error --write-out "\nHTTP %{http_code}\n" \
  "https://${INSTANCIA}/service/v2/public/invoices/sales/resolutions?page=0" \
  -H "Authorization: Bearer ${TOKEN}"
PHP
<?php

$instancia = 'mi-inmobiliaria.nuby.app'; // Tu dirección web completa
$token     = 'TU_TOKEN_AQUI';            // Token obtenido del servicio Login

$query = http_build_query([
    'activa'    => 'SI',
    'page'      => 1,
    'page_size' => 10,
]);

$url = "https://{$instancia}/service/v2/public/invoices/sales/resolutions?{$query}";

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    "Authorization: Bearer {$token}",
]);

$respuesta = curl_exec($ch);
$httpCode  = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

$datos = json_decode($respuesta, true);

if ($httpCode === 200) {
    foreach ($datos['body'] as $resolucion) {
        echo "{$resolucion['prefijo']} {$resolucion['resolucion_numero']} - "
            . "{$resolucion['consecutivo_inicial']} a {$resolucion['consecutivo_final']}\n";
    }

    echo "Total: {$datos['pagination']['total_records']}\n";
} elseif ($httpCode === 400) {
    echo "Parámetro inválido ({$datos['error_code']}): {$datos['message']}\n";
} elseif ($httpCode === 403) {
    echo "Sin permiso catalogs:read ({$datos['error_code']}): {$datos['message']}\n";
} else {
    echo "Error HTTP {$httpCode}: {$datos['message']}\n";
}
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. Envía la petición con los filtros como parámetros
url = f"https://{instancia}/service/v2/public/invoices/sales/resolutions"
headers = {"Authorization": f"Bearer {token}"}
params = {"activa": "SI", "page": 1, "page_size": 10}

respuesta = requests.get(url, headers=headers, params=params, timeout=30)

# 3. Procesa la respuesta
if respuesta.status_code == 200:
    datos = respuesta.json()
    for resolucion in datos["body"]:
        print(resolucion["prefijo"], resolucion["resolucion_numero"])
    print(f"Total: {datos['pagination']['total_records']}")
elif respuesta.status_code in (400, 403):
    error = respuesta.json()
    print(f"Rechazo {error['error_code']}: {error['message']}")
else:
    print(f"Error HTTP {respuesta.status_code}: {respuesta.text}")
JavaScript (Fetch API)
// 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. Función que consulta el catálogo de resoluciones de venta
async function listarResoluciones(filtros = {}) {
  const params = new URLSearchParams({
    activa: 'SI',
    page: '1',
    page_size: '10',
    ...filtros,
  });

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

  const response = await fetch(url, {
    headers: { 'Authorization': `Bearer ${token}` },
  });

  const datos = await response.json().catch(() => ({}));

  if (!response.ok) {
    console.error(`Error HTTP ${response.status} ${datos.error_code ?? ''}: ${datos.message ?? ''}`);
    return [];
  }

  console.log(`Total de resoluciones: ${datos.pagination.total_records}`);
  return datos.body;
}

// 3. Consume el catálogo
listarResoluciones().then((resoluciones) => {
  resoluciones.forEach((r) => console.log(`${r.prefijo} ${r.resolucion_numero}`));
});

Los otros tres catálogos se consumen igual, con el mismo encabezado Authorization y el mismo permiso catalogs:read; solo cambia la ruta: GET https://{{instancia}}/service/v2/public/masters/note-concepts para los conceptos de nota (con el filtro opcional target), GET https://{{instancia}}/service/v2/public/masters/products para los productos e impuestos (con search y estado) y GET https://{{instancia}}/service/v2/public/masters/invoice-statuses para los estados de factura (sin parámetros).

6. Buenas prácticas y límites conocidos

Recomendaciones
  • Consulta los catálogos una vez y guárdalos. Cambian poco y son de solo lectura.
  • Usa /invoices/sales/resolutions para elegir la resolución de una factura de venta; el endpoint anterior puede devolver resoluciones de contrato.
  • Toma los impuestos de /masters/products y envíalos en items[]; nuby no los adivina.
  • Recorre hasta total_pages, no hasta una página vacía.
  • No envíes page_size mayor a 1000: el servidor lo recorta.
Límites
  • Los catálogos solo devuelven datos de facturas de venta.
  • No exponen datos de contacto de terceros ni información contable.
  • Los estados de factura son fijos; los conceptos y productos dependen de la configuración de tu instancia.

Si necesitas crear una factura, revisa la página Crear Factura Borrador.

¿Necesita ayuda adicional?

Nuestro equipo de soporte está disponible para asistirle:

Escríbenos a nuestro correo:

📞 (604) 444-7417 Opción 2

📧 soporte@nuby.ai

Escríbenos a nuestra línea de Whatsapp:

Whatsapp

Síguenos en nuestras redes sociales: