Saltar al contenido principal

Exportar artículos BETA

Endpoint en beta

Puede cambiar de contrato, comportamiento o ser retirado antes de su release definitivo.

Devuelve el catálogo de artículos paginado, con lo que GetData no trae: el costo y de qué está compuesto (si lleva IVA adentro y de dónde salió), el stock (el mismo número que GetData, y si lo pedís desglosado por depósito) y los últimos precios de venta y de compra. Sirve para dos usos:

  • Recorrer el catálogo ordenado, de a 100 por página (modo normal).
  • Mantenerlo sincronizado sin volver a bajar todo: pedís solo lo que cambió desde la última vez (modo incremental, de a 500 por página).
Requiere "Datos extendidos"

Este endpoint solo responde si el administrador del ERP habilitó Datos extendidos en Configuración › Canales › tu integración. Sin eso responde 403. Por defecto está apagado.

También exige sucursales habilitadas, igual que el resto de las lecturas de Exportaciones: sin ninguna, 403. Consultá las tuyas en GET /config → sucursalesExportacion.

GETBETA/integraciones/terceros/exportar/articulos/paginado

Query parameters​

ParámetroTipoRequeridoDescripción
sucursalIdnumberNoEl stock pasa a ser el de todos los depósitos de esa sucursal, y los últimos precios se acotan a ella. Debe estar habilitada. Ver Stock
depositoIdnumberNoEl stock pasa a ser el de ese depósito. Su sucursal debe estar habilitada (y coincidir con sucursalId, si lo mandás)
pagenumberNoModo normal. Página, empieza en 1 (default 1)
pageSizenumberNoRegistros por página (default 25). Máximo 100 en modo normal y 500 en modo incremental; un valor mayor, o 0 o negativo, se recorta al máximo
ordenstringNoModo normal. codigo (default), descripcion, modificado o articuloId. Los empates se resuelven por articuloId, así el orden es estable
dirstringNoModo normal. asc (default) o desc
incluirEliminadosbooleanNoModo normal. Incluye los artículos dados de baja (eliminado: true)
incluirStockPorDepositobooleanNoSuma el detalle stock.depositos
incluirUltimosPreciosbooleanNoSuma ultimaVenta y ultimaCompra
versionMayornumberNoActiva el modo incremental. Trae los artículos con version mayor a este valor (-1 = desde el principio)
desdeArticuloIdnumberNoModo incremental. Para continuar un recorrido: se manda junto a versionMayor con los valores de siguiente

Un parámetro inválido (un orden que no existe, un page menor a 1, un versionMayor que no es un número) responde 400 con el motivo en texto plano.

El universo es el mismo que GetData: los artículos publicados en web (y, si tu integración trabaja por canal, los activos en tu canal).

Respuesta​

export interface ArticulosPaginadoResult {
items: ArticuloPaginado[];
totalRegistros: number | null; // solo modo normal
totalPaginas: number | null; // solo modo normal
paginaActual: number | null; // solo modo normal
pageSize: number;
versionActual: number | null; // solo modo incremental
siguiente: { // solo modo incremental; null = no hay más
versionMayor: number;
desdeArticuloId: number;
} | null;
}

export interface ArticuloPaginado {
articuloId: number;
codigo: string;
descripcion: string;
codigoBarras: string | null;
marcaId: number | null;
monedaId: number; // moneda de los precios del artículo (1 = pesos)
iva: number; // alícuota de IVA de VENTA, en %
eliminado: boolean;
costo: CostoArticulo;
precios: { listaPrecioId: number; precio: number }[]; // listas 1 a 5
stock: {
origen: 'canal' | 'sucursal' | 'deposito'; // de dónde sale el stock, ver abajo
unidades: number;
reservado: number;
depositos: { depositoId: number; nombre: string; unidades: number; reservado: number }[] | null;
};
ultimaVenta: UltimoPrecio | null; // solo con incluirUltimosPrecios
ultimaCompra: UltimoPrecio | null; // solo con incluirUltimosPrecios
version: number;
modificado: string; // "dd/MM/yyyy HH:mm:ss", como el resto de las exportaciones
}

export interface CostoArticulo {
precioCosto: number;
precioCompra: number;
precioCostoModificado: string | null; // cuándo se tocó el costo por última vez
precioCostoIva: number | null; // ver abajo
precioCostoOrigen: number | null; // TipoOrigenCosto
precioCostoOrigenTexto: string | null;
}

export interface UltimoPrecio {
fecha: string;
precio: number; // precio unitario final del renglón, en la moneda del comprobante
monedaId: number;
comprobanteId: number;
}

Ejemplo (modo normal, con las opciones de stock por depósito y últimos precios):

{
"items": [
{
"articuloId": 1204,
"codigo": "REM-001",
"descripcion": "Remera algodón",
"codigoBarras": "7790001234567",
"marcaId": 12,
"monedaId": 1,
"iva": 21,
"eliminado": false,
"costo": {
"precioCosto": 5200.00,
"precioCompra": 5200.00,
"precioCostoModificado": "28/10/2026 14:03:11",
"precioCostoIva": 0,
"precioCostoOrigen": 1,
"precioCostoOrigenTexto": "COMPRA"
},
"precios": [
{ "listaPrecioId": 1, "precio": 9800.00 },
{ "listaPrecioId": 2, "precio": 8900.00 },
{ "listaPrecioId": 3, "precio": 0.00 },
{ "listaPrecioId": 4, "precio": 0.00 },
{ "listaPrecioId": 5, "precio": 0.00 }
],
"stock": {
"origen": "canal",
"unidades": 34,
"reservado": 2,
"depositos": [
{ "depositoId": 3, "nombre": "Depósito central", "unidades": 30, "reservado": 2 },
{ "depositoId": 7, "nombre": "Local Centro", "unidades": 4, "reservado": 0 }
]
},
"ultimaVenta": { "fecha": "08/11/2026 00:00:00", "precio": 9800.00, "monedaId": 1, "comprobanteId": 48211 },
"ultimaCompra": { "fecha": "28/10/2026 00:00:00", "precio": 5200.00, "monedaId": 1, "comprobanteId": 47012 },
"version": 18423,
"modificado": "02/11/2026 10:15:00"
}
],
"totalRegistros": 1840,
"totalPaginas": 19,
"paginaActual": 1,
"pageSize": 100,
"versionActual": null,
"siguiente": null
}

Costo y su composición fiscal​

precioCosto solo no dice si el número trae impuestos adentro. Los dos campos que lo acompañan sí:

CampoQué dice
precioCostoIvaLa alícuota de IVA contenida en precioCosto. null = no se sabe (artículos cuyo costo se cargó antes de que el ERP registrara este dato). 0 = el costo es neto. 21 = el costo trae 21 % adentro: el neto es precioCosto / 1,21.
precioCostoOrigenDe dónde salió el costo vigente. Mide cuánto confiar en él. Valores en Enums y códigos › TipoOrigenCosto.

precioCompra es el último precio de compra. En la práctica se mueve junto con precioCosto; difieren si alguien los edita por separado en la ficha del artículo.

Stock​

Por defecto el stock es el mismo que devuelve GetData: la suma de los depósitos configurados en tu integración (el depósito principal, o los depósitos de tu integración si trabaja con varios), con la misma cuenta. El mismo artículo da el mismo número en los dos endpoints. Podés cambiar de dónde sale con depositoId o sucursalId, y la respuesta lo dice en stock.origen:

Qué mandásstock.origenDe dónde sale el stock
nada (ni depositoId ni sucursalId)canalLos depósitos configurados en tu integración, como GetData
sucursalIdsucursalTodos los depósitos de esa sucursal
depositoIddepositoEse depósito

stock.reservado es lo reservado en esos mismos depósitos. Con incluirStockPorDeposito=true, stock.depositos lista un renglón por depósito con existencias; sin la opción viene null. Un artículo sin existencias trae unidades: 0.

En cualquiera de los tres casos los depósitos tienen que estar en sucursales habilitadas. Si los depósitos de tu integración no lo están (o tu integración no tiene depósitos configurados), el stock por defecto no se puede calcular y el endpoint responde 403 con el motivo: en ese caso pedí sucursalId o depositoId, o que corrijan la configuración.

Últimos precios​

Con incluirUltimosPrecios=true, ultimaVenta y ultimaCompra traen el último comprobante que incluyó el artículo (facturas de venta y de compra; se saltean las anuladas), buscando en la sucursalId que pediste o, si no mandaste ninguna, en todas tus sucursales habilitadas. Si nunca se vendió o compró ahí, vienen en null. El precio está en la moneda del comprobante (monedaId).

Modo normal: recorrer ordenado​

Sin versionMayor. Se pagina con page y pageSize y la respuesta trae el total.

curl --request GET \
--url 'https://api.test-ninox.com.ar/integraciones/terceros/exportar/articulos/paginado?page=1&pageSize=100&orden=descripcion&dir=asc' \
--header 'X-NX-TOKEN: {TU_TOKEN}'

Si el catálogo se modifica mientras lo recorrés, las páginas reflejan el estado de cada momento. Para una copia consistente usá el modo incremental.

Modo incremental: sincronizar solo lo que cambió​

Se activa con versionMayor. Cada artículo tiene una version que crece cada vez que se modifica. El recorrido va siempre ordenado por (version, articuloId) (no admite otro orden, porque con otro no se podría saber hasta dónde llegaste) y trae también los artículos dados de baja (eliminado: true), para que puedas quitarlos de tu lado. No calcula totales.

  1. Primera sincronización: versionMayor=-1.
  2. Procesá la página y, mientras siguiente no sea null, pedí la próxima mandando sus dos valores: versionMayor={siguiente.versionMayor}&desdeArticuloId={siguiente.desdeArticuloId}.
  3. Cuando siguiente es null terminaste: guardá versionActual y usalo como versionMayor en la próxima sincronización (sin desdeArticuloId).
# Primera vez: todo, de a 500
curl --request GET \
--url 'https://api.test-ninox.com.ar/integraciones/terceros/exportar/articulos/paginado?versionMayor=-1&pageSize=500' \
--header 'X-NX-TOKEN: {TU_TOKEN}'

# Continuación, con lo que devolvió "siguiente"
curl --request GET \
--url 'https://api.test-ninox.com.ar/integraciones/terceros/exportar/articulos/paginado?versionMayor=18423&desdeArticuloId=1204&pageSize=500' \
--header 'X-NX-TOKEN: {TU_TOKEN}'
{
"items": [ /* ... */ ],
"totalRegistros": null,
"totalPaginas": null,
"paginaActual": null,
"pageSize": 500,
"versionActual": 18433,
"siguiente": { "versionMayor": 18433, "desdeArticuloId": 1288 }
}
La versión cambia cuando cambia el artículo, no su stock

version sube cuando se modifica la ficha del artículo (precios, costo, descripción, baja...). Mover stock no la cambia. Para mantener el stock al día usá los webhooks o exportar/stock; este endpoint te da una foto del stock al momento de cada consulta.

Un artículo que sale de tu canal

Si el comercio deja de publicar un artículo en web (o en tu canal), no se informa como baja: simplemente deja de aparecer. Las bajas (eliminado: true) son artículos dados de baja en el ERP.

Rate limiting​

Ventana propia y corta: 10 segundos en producción, 3 segundos en test. No comparte la ventana de 10 minutos de las exportaciones masivas ni la de los paginados de comprobante, así que podés recorrer el catálogo de corrido respetando ese intervalo. Si consultás antes, 403 Forbidden.

Errores​

CódigoCuándo
403Datos extendidos no habilitados · sin sucursales habilitadas · sucursalId o depositoId fuera de las sucursales habilitadas · depósitos de la integración fuera de las sucursales habilitadas, o sin depósitos configurados (Stock) · ventana de frecuencia
400Parámetro inválido (el cuerpo dice cuál)

Detalle en Errores comunes.

Ver también​