Integraciones

YUBASync Link

Conecta lo que ya tienes.

118 conectores publicados, una API REST con contrato OpenAPI, webhooks firmados con HMAC y autoridad por campo entre tu ERP y cada canal.

curl · suite.yubasync.com/api/v2 200 OK
$ curl -G https://suite.yubasync.com/api/v2/items \
     -H 'Authorization: Bearer $TOKEN' \
     -d max=2

{
  "data": [
    { "code": "ARR-500", "description": "Arroz premium 500 g",
      "totalQuantity": 1284, "existenciesOnRoutes": 96, "price": 24500 },
    { "code": "PAN-024", "description": "Panela cuadrada x24",
      "totalQuantity": 340, "existenciesOnRoutes": 0, "price": 18900 }
  ],
  "pagination": { "page": 1, "pageSize": 2, "totalPages": 1642, "totalRecords": 3283 }
}
118
conectores publicados
10 + global
países con conector local
100 req/min
límite por credencial
90 días
vigencia del token
500
tope de registros por página
1m · 5m · 30m
reintentos de cada webhook

Catálogo

El que ya usas probablemente está.

Esta es la lista completa de conectores publicados, no una selección de logos. Búscalo por nombre o filtra por tipo. Si el tuyo no aparece, no está: preferimos decirlo antes de la reunión.

Los conectores marcados con un país tienen lógica fiscal o de negocio propia de ese país; los marcados «global» funcionan igual en cualquiera. Ninguno se cobra aparte.


El contrato

Una API que puedes leer antes de llamarnos.

REST sobre HTTPS, JSON en los dos sentidos, token Bearer y un OpenAPI público que puedes cargar en tu propio Swagger. El identificador de empresa viaja firmado dentro del token: no hay ningún parámetro de compañía que un cliente pueda manipular.

api/v2 · ejemplos
$ curl -X POST https://suite.yubasync.com/api/login/authenticate \
     -H 'Content-Type: application/json' \
     -d '{"username":"acme_prod","password":"••••••••••"}'

{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0eXAiOiJiYXQtYXBpIiwi…"
}

# El token dura 90 días; renovarlo es volver a llamar este endpoint.
# Máximo 10 intentos por minuto. Usuario inexistente y clave incorrecta
# devuelven exactamente la misma respuesta — a propósito.
# Revocar la credencial corta el acceso YA, sin esperar al vencimiento.
Superficie pública de la API
Método Ruta Qué devuelve
POST/api/login/authenticateEmite el Bearer Token de 90 días a partir del usuario técnico.
GET/api/v2/salesOrderPedidos de venta con sus líneas, totales, GPS y estado de exportación.
GET/api/v2/customersClientes. Alias equivalente: /api/v2/customer.
GET/api/v2/itemsExistencias por producto, ya consolidadas entre bodegas y rutas. Alias: /api/v2/inventory.
GET/api/v2/priceListListas de precios vigentes por producto.
GET/api/v2/deliveryBalanceCartera: saldos pendientes por cliente y documento. Alias: /api/v2/cartera.
GET/api/v2/visitsVisitas y agenda del vendedor. Alias: /api/v2/calendarEvent.
GET/api/v2/usersUsuarios de la compañía. Alias: /api/v2/user.
GET/api/v2/openapi.jsonEl contrato OpenAPI completo. Público a propósito: se lee sin token.

Paginación siempre explícita

Toda lista responde con data y pagination. Nunca hay que deducir el final por «me llegaron menos de los que pedí» — que falla justo cuando el total es múltiplo exacto del tamaño de página.

El tope recorta, no falla

Pedir max=5000 no devuelve un 400: se recorta a 500 y el valor realmente aplicado viene en pagination.pageSize.

Ventana incremental

start y end en dd/MM/yyyy, interpretadas en UTC-05:00. Un end sin hora se completa a las 23:59:59 para que el último día quede incluido.

La empresa va en el token

El identificador de compañía sale del JWT firmado, jamás de un parámetro. Una credencial no sirve para leer otra compañía aunque se conozca su código.

Errores con código estable

Siempre { errorCode, message }, con details sólo cuando aporta. El mensaje crudo de una excepción no sale nunca: podría filtrar nombres de tabla.

ERPs que sólo hablan por VPN

Para los sistemas legacy que no publican nada a internet hay un agente on-premise: se instala del lado del cliente y abre un puente cifrado y auditable hacia el hub.


Eventos

Webhooks que puedes verificar.

Cada entrega va firmada con HMAC SHA-256 sobre el cuerpo crudo más una marca de tiempo. Tu extremo puede comprobar que el mensaje salió de nosotros y que no es la repetición de uno viejo — sin confiar en la IP de origen.

POST · tu-endpoint HMAC
X-Yuba-Event:       shipment.delivered
X-Yuba-Delivery-Id: 6f1c1a9e-4b02-4f4e-9a31-2c0e7d5a11b8
X-Yuba-Webhook-Id:  0b2d94c7-1f88-4a55-bb10-8e6f0a7c3d21
X-Yuba-Signature:   t=1779023011,v1=9f3c…c1
User-Agent:         YubaWebhook/1.0

{ "id": "6f1c1a9e-…", "event": "shipment.delivered",
  "ts": "2026-05-18T14:23:31.482Z", "data": {  } }


// Verificación del lado del receptor — la firma se calcula sobre `${t}.${body}`
import crypto from "node:crypto";

export function verificar(rawBody, header, secret) {
  const { t, v1 } = Object.fromEntries(header.split(",").map(p => p.split("=")));

  // Anti-replay: fuera de ±300 s se descarta aunque la firma cuadre.
  if (Math.abs(Date.now() / 1000 - Number(t)) > 300) return false;

  const esperado = crypto
    .createHmac("sha256", secret)
    .update(`${t}.${rawBody}`)
    .digest("hex");

  // Comparación en tiempo constante: un `===` filtra información por timing.
  return crypto.timingSafeEqual(Buffer.from(esperado), Buffer.from(v1));
}

Reintentos acotados

Tres intentos con espera creciente: 1 minuto, 5 minutos y 30 minutos. Después la entrega queda marcada como fallida y visible — no se reintenta para siempre contra un endpoint caído.

Identificador de entrega

Cada envío trae su X-Yuba-Delivery-Id. Si un reintento llega dos veces, tu lado lo descarta con una comprobación de una línea.

Firma sobre el cuerpo crudo

Hay que verificar antes de parsear el JSON: reserializar el cuerpo cambia los espacios y rompe la firma. Es el fallo más común al integrar webhooks firmados.

Catálogo de eventos publicables

shipment.created shipment.in_transit shipment.delivered shipment.exception tender.posted tender.accepted tender.declined tender.expired driver.checked_in driver.checked_out invoice.received invoice.reconciled alert.fired feedback.received

Un evento que no esté en esta lista no se puede suscribir: el emisor valida el nombre contra el catálogo antes de encolar, así una errata de tipeo falla en el registro y no seis meses después en silencio.


La tesis

La autoridad no es de un sistema: es de un campo.

Cuando el mismo producto vive en el ERP, en la tienda y en dos marketplaces, «¿quién manda?» no tiene una respuesta, tiene una por campo. El stock lo manda el ERP porque es la única verdad de existencias; el precio de venta puede mandarlo la tienda; el catálogo, un PIM distinto. Declarar eso es lo que hace que dos integraciones corriendo en paralelo no se pisen.

SISTEMA DE REGISTRO SIESA · SAP · Siigo World Office · Odoo QuickBooks · Xero Agente on-premise YUBASYNC LINK Modelo canónico stock · price · catalog · status DUEÑO · DIRECCIÓN · CONFLICTO idempotente · reintentable · auditable CANALES DE VENTA Shopify · VTEX Mercado Libre Falabella · Dafiti WhatsApp · POS · B2B entra al hub (inbound) sale del hub (outbound) bidireccional, según el campo
Ejemplo de configuración de autoridad
Campo canónico Dueño Dirección Ante un cambio ajeno
stock El ERP inbound owner-winsse rechaza y queda en la traza
price El canal bidirectional last-writergana el más reciente
catalog El PIM outbound manualentra a revisión humana
status El ERP bidirectional owner-winsse rechaza y queda en la traza

El error caro no es un fallo

Es un dato aceptado que no debía aceptarse. La tienda avisa «vendí 3» y baja el stock; el ERP, que ya lo sabía por su propio flujo, lo baja otra vez. Nada se cae y nadie se entera: simplemente se deja de vender un producto que sí había.

Por defecto, conservador

Un dueño sin declarar cae en manual (que decida una persona) y una dirección sin declarar cae en inbound (escuchar antes que empujar). Ante la duda no se pisa el dato bueno.

Decisiones auditables

Cada cambio entrante queda como aceptado, rechazado o en conflicto, con su origen y su marca de tiempo. Cuando alguien pregunte por qué el precio cambió un martes, hay una respuesta.

Evalúa la integración sin agendar una llamada.

La documentación y el contrato OpenAPI son públicos: se leen, se cargan en tu Swagger y se prueban. Si después de eso quedan preguntas, hablas con quien escribió el conector — no con un comercial.

Los conectores no se cobran por unidad ni por volumen de eventos: vienen incluidos con el producto. Ver precios.