Saltar al contenido principal

Webhooks

Los webhooks permiten que NinoxNet notifique cambios de artículos hacia tu integración sin depender solamente de consultas periódicas.

Cuándo conviene usarlos

  • reducir polling
  • mantener stock y precios más actualizados
  • acelerar sincronizaciones incrementales
Recomendación

Para una integración nueva, conviene implementar primero la lectura de catálogo y después sumar webhooks como mecanismo de actualización incremental.

Configuración por API BETA

Endpoints en beta

Pueden cambiar de contrato, comportamiento o ser retirados antes de su release definitivo.

Podés administrar tus propios webhooks sin coordinar cada cambio con NinoxNet: alta, edición y baja se hacen con el mismo token de la integración.

Reglas generales:

  • un solo webhook por topic
  • el único topic disponible hoy es articulos
  • el id lo asigna NinoxNet: es de solo lectura y no cambia nunca. Si lo mandás en el cuerpo del request, se ignora
  • los cuatro endpoints devuelven la lista completa actualizada

El objeto webhook

export interface Webhook {
id: number; // asignado por NinoxNet, solo lectura
url: string; // absoluta, http o https
topic: string; // "articulos"
activo: boolean;
extra: string | null; // null | "objeto" | "curva" — ver Eventos contemplados
headers: WebhookHeader[];
}

export interface WebhookHeader {
key: string;
value: string;
}

Al crear o editar mandás el mismo objeto sin id:

export interface WebhookGuardar {
url: string; // requerida
topic: string; // requerido
activo?: boolean; // default true
extra?: string | null;
headers?: WebhookHeader[];
}

Listar los webhooks configurados

GETBETA/integraciones/terceros/config/webhooks

Devuelve Webhook[], o [] si no hay ninguno configurado.

curl --request GET \
--url 'https://api.test-ninox.com.ar/integraciones/terceros/config/webhooks' \
--header 'X-NX-TOKEN: {TU_TOKEN}'

Crear un webhook

POSTBETA/integraciones/terceros/config/webhooks
curl --request POST \
--url 'https://api.test-ninox.com.ar/integraciones/terceros/config/webhooks' \
--header 'X-NX-TOKEN: {TU_TOKEN}' \
--header 'Content-Type: application/json' \
--data '{
"url": "https://test.com",
"topic": "articulos",
"activo": true,
"extra": "objeto",
"headers": [ { "key": "X-API-Key", "value": "test" } ]
}'

Respuesta:

[
{
"id": 1,
"url": "https://test.com",
"topic": "articulos",
"activo": true,
"extra": "objeto",
"headers": [ { "key": "X-API-Key", "value": "test" } ]
}
]

Si ya tenés un webhook para ese topic, el alta se rechaza: editá el existente o eliminalo.

Editar un webhook

POSTBETA/integraciones/terceros/config/webhooks/{id}

El id va en la URL. El cuerpo es el mismo de la creación.

curl --request POST \
--url 'https://api.test-ninox.com.ar/integraciones/terceros/config/webhooks/1' \
--header 'X-NX-TOKEN: {TU_TOKEN}' \
--header 'Content-Type: application/json' \
--data '{ "url": "https://test.com/v2", "topic": "articulos", "activo": true, "extra": "objeto" }'

Eliminar un webhook

DELETEBETA/integraciones/terceros/config/webhooks/{id}
curl --request DELETE \
--url 'https://api.test-ninox.com.ar/integraciones/terceros/config/webhooks/1' \
--header 'X-NX-TOKEN: {TU_TOKEN}'
No es idempotente

Eliminar un id que no existe devuelve 400, no un 200 vacío. Si reintentás un DELETE después de un timeout de red y recibís 400, revisá con un GET antes de asumir que falló.

Validaciones

CampoRegla
urlRequerida. Absoluta, http o https. Máximo 500 caracteres
topicRequerido. Sólo articulos
extranull, "objeto" o "curva"
headersMáximo 10
headers[].keyRequerida, máximo 100 caracteres, sin espacios ni caracteres especiales. No se admiten keys repetidas, aunque difieran en mayúsculas
headers[].valueRequerido, máximo 500 caracteres, sin saltos de línea

Cualquier validación que falle devuelve 400 con el detalle en mensajes.

Rate limiting

La consulta usa una ventana de 10 segundos en producción (3 en test). Las escrituras —alta, edición y baja— comparten una ventana de 30 segundos en producción (3 en test), porque cada guardado se propaga a toda la infraestructura.

Requisitos del endpoint receptor

Tu endpoint debe:

  • aceptar requests POST
  • procesar JSON
  • responder 200 OK cuando reciba correctamente el evento
  • responder rápido
Timeout

Si el endpoint no responde dentro de 10 segundos, el envío puede considerarse fallido.

Eventos contemplados

Cambio de artículo

Informa cambios de stock, precios, propiedades del artículo, variantes y clasificación comercial. El payload puede enviarse en dos formatos, y el que manda es el campo extra del webhook.

Formato plano — extra: "curva" o null

ArticuloConCurva[]

Es el formato más práctico para la mayoría de las integraciones: cada variante llega como un registro independiente. Es el comportamiento por defecto.

Formato agrupado — extra: "objeto"

Articulo

Conserva la curva y los tags dentro de un único objeto de artículo.

Cambiar de formato

El formato se cambia editando el webhook: ver Configuración por API.

Stock por depósito (multidepósito informativo)

Si tu integración administra varios depósitos o locales, el canal puede configurarse en modo multidepósito informativo. En ese modo cada evento de artículo incluye, además del stock habitual, el detalle de cada depósito:

export interface StockDeposito {
depositoId: number;
unidades: number;
}

stockDepositos aparece tanto en el formato plano (por variante) como en el agrupado:

{
"articuloId": 123,
"codigo": "REM-01",
"unidades": 14,
"stockDepositos": [
{ "depositoId": 3, "unidades": 14 },
{ "depositoId": 7, "unidades": 6 },
{ "depositoId": 9, "unidades": 0 }
]
}
unidades no es la suma de stockDepositos

En este modo unidades es el stock del depósito principal, no el total. El principal además aparece como un item más del array. Si necesitás el total, sumalo vos a partir de stockDepositos.

Los depósitos con cero también se informan: es la señal de que el artículo se agotó en ese local. La lista trae siempre un item por cada depósito configurado en la integración, así que podés mapearla directo contra tus sucursales sin adivinar ausencias.

Para saber si tu integración está en este modo, consultá GET /integraciones/terceros/config: si flujoDeposito vale 3, vas a recibir stockDepositos, y depositos te dice de qué depósitos se trata. Con cualquier otro valor el campo no viaja.

Cómo se activa

Lo configura NinoxNet en el canal, no se activa por API. Requiere plan Corporativo. Si lo necesitás, escribinos por el Chat de Ayuda.

Artículo desactivado

Cuando un artículo deja de participar en la integración, el webhook informa la baja lógica:

{
articuloId: number;
eliminado: true;
}

Recomendaciones de implementación

activo no corta el envío

Hoy el campo activo se guarda pero no detiene el envío del topic articulos. Si necesitás dejar de recibir eventos, eliminá el webhook.

  • validar autenticidad del request según la configuración acordada
  • registrar cada evento recibido
  • procesar de forma idempotente
  • desacoplar recepción y procesamiento con una cola o tarea interna, si el volumen lo justifica
  • mantener una resincronización completa periódica como mecanismo de respaldo

Estrategia sugerida

sync inicial (GetData) → caché local → updates por webhook → resync completa periódica de respaldo
  1. sincronización inicial con GetData
  2. almacenamiento local del catálogo
  3. actualización incremental por webhook
  4. resincronización completa periódica respetando la frecuencia mínima de consulta

Relación con el resto de la integración

Los webhooks complementan la integración, pero no reemplazan el alta inicial ni el modelado del catálogo. El punto de entrada general es Integración de terceros y la referencia de tipos está en Esquema de datos.