Exportar artículos 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).
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.
/integraciones/terceros/exportar/articulos/paginadoQuery parameters
| Parámetro | Tipo | Requerido | Descripción |
|---|---|---|---|
sucursalId | number | No | El 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 |
depositoId | number | No | El stock pasa a ser el de ese depósito. Su sucursal debe estar habilitada (y coincidir con sucursalId, si lo mandás) |
page | number | No | Modo normal. Página, empieza en 1 (default 1) |
pageSize | number | No | Registros 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 |
orden | string | No | Modo normal. codigo (default), descripcion, modificado o articuloId. Los empates se resuelven por articuloId, así el orden es estable |
dir | string | No | Modo normal. asc (default) o desc |
incluirEliminados | boolean | No | Modo normal. Incluye los artículos dados de baja (eliminado: true) |
incluirStockPorDeposito | boolean | No | Suma el detalle stock.depositos |
incluirUltimosPrecios | boolean | No | Suma ultimaVenta y ultimaCompra |
versionMayor | number | No | Activa el modo incremental. Trae los artículos con version mayor a este valor (-1 = desde el principio) |
desdeArticuloId | number | No | Modo 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í:
| Campo | Qué dice |
|---|---|
precioCostoIva | La 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. |
precioCostoOrigen | De 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ás | stock.origen | De dónde sale el stock |
|---|---|---|
nada (ni depositoId ni sucursalId) | canal | Los depósitos configurados en tu integración, como GetData |
sucursalId | sucursal | Todos los depósitos de esa sucursal |
depositoId | deposito | Ese 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.
- Primera sincronización:
versionMayor=-1. - Procesá la página y, mientras
siguienteno seanull, pedí la próxima mandando sus dos valores:versionMayor={siguiente.versionMayor}&desdeArticuloId={siguiente.desdeArticuloId}. - Cuando
siguienteesnullterminaste: guardáversionActualy usalo comoversionMayoren la próxima sincronización (sindesdeArticuloId).
# 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 }
}
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.
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ódigo | Cuándo |
|---|---|
403 | Datos 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 |
400 | Parámetro inválido (el cuerpo dice cuál) |
Detalle en Errores comunes.
Ver también
- Catálogo —
GetData/GetDataCurva, el volcado completo del catálogo. - Exportar stock — snapshot de stock por depósito.
- Enums y códigos —
TipoOrigenCosto.