Webhooks: Listar Productos
Descripción General
El webhook Listar Productos permite que Talk2sync recupere tu catálogo de productos completo. Talk2sync solicitará periódicamente tu endpoint de productos para sincronizar datos de productos incluyendo detalles, precios, disponibilidad, imágenes y atributos personalizados.
Requisitos del Endpoint
Debes crear un endpoint GET que acepte parámetros de paginación y ordenamiento de Talk2sync.
Formato de Solicitud
Talk2sync enviará solicitudes GET a tu endpoint de productos configurado con los siguientes parámetros:
Paginación por Offset Numérico (Recomendado)
GET https://www.example.com/your/endpoint/url?offset=0&sortorder=desc&jobid=123
T2SKey: {{API_KEY}}
Paginación por Cursor (Alternativa)
Si la paginación por offset numérico no es viable para tu sistema, puedes implementar paginación basada en cursor:
GET https://www.example.com/your/endpoint/url?next=YXNkaWhhc3BvZGhpYXM&sortorder=desc&jobid=123
T2SKey: {{API_KEY}}
Parámetros de Solicitud
| Parámetro | Tipo | Descripción | Obligatorio |
|---|---|---|---|
offset | integer | Posición de inicio para paginación numérica (basada en 0) | Si se usa paginación numérica |
next | string | Cursor codificado en Base64 para paginación basada en cursor | Si se usa paginación por cursor |
sortorder | string | Dirección de ordenamiento: asc (ascendente) o desc (descendente) | ✓ Sí |
jobid | integer | Identificador único para este trabajo de sincronización (para seguimiento) | ✓ Sí |
T2SKey | header | Tu clave de seguridad proporcionada por Talk2sync | ✓ Sí |
Autenticación
La clave de seguridad debe incluirse en el encabezado T2SKey (no en el encabezado Authorization para este endpoint):
T2SKey: tu_clave_generada_aqui
Formato de Respuesta
Tu endpoint debe devolver una respuesta JSON con la siguiente estructura:
{
"paging": {
"pageSize": 20,
"itemsTotal": 2,
"offset": 0
},
"products": [
{
"_id": "100004777",
"sku": "100004777",
"last_updated": 1517360038797,
"title": "EON618S JBL SUBWOOFER 18\" AMPLIFICADO",
"url": "",
"brand": "",
"mpn": "",
"model": "",
"description": "JBL Premium Transducers",
"variations": [
{
"availabilities": [
{
"tag": "default",
"quantity": 50
}
],
"prices": [
{
"tag": "default",
"currency": "USD",
"number": 1060.51
}
],
"images": [
{
"url": "https://www.example.com/13080-thickbox_default/eon618s-jbl-subwoofer-18-amplificado-.jpg"
}
],
"videos": [
{
"url": ""
}
],
"barcode": "",
"size": "",
"color": "",
"variationid": ""
}
],
"properties": [
{
"extraattributes": {
"promociones": "",
"status": "",
"condicion_venta": "",
"peso": "",
"relacionados": "",
"custom_01": "",
"custom_02": "1",
"custom_03": ""
}
}
]
}
]
}
Estructura de Respuesta
Objeto de Paginación
| Campo | Tipo | Descripción |
|---|---|---|
pageSize | integer | Número de elementos devueltos en esta página |
itemsTotal | integer | Número total de productos en tu sistema |
offset | integer | Posición de offset actual (solo para paginación numérica) |
next | string | Cursor codificado en Base64 para la siguiente página (solo para paginación por cursor) |
Objeto de Producto
| Campo | Tipo | Descripción |
|---|---|---|
_id | string | Identificador único del producto (requerido) |
sku | string | SKU/código del producto |
last_updated | integer | Timestamp Unix (milisegundos) de la última modificación |
title | string | Nombre/título del producto |
url | string | URL del producto en tu tienda |
brand | string | Marca del producto |
mpn | string | Número de Parte del Fabricante |
model | string | Modelo del producto |
description | string | Descripción detallada del producto |
variations | array | Array de variaciones del producto (ver abajo) |
properties | array | Array de propiedades/atributos personalizados |
Objeto de Variación
| Campo | Tipo | Descripción |
|---|---|---|
variationid | string | Identificador único de la variación |
size | string | Atributo de tamaño |
color | string | Atributo de color |
barcode | string | Código de barras/EAN |
availabilities | array | Información de inventario por ubicación/almacén |
prices | array | Información de precios por moneda/región |
images | array | Imágenes del producto |
videos | array | Videos del producto |
Objeto de Disponibilidad
| Campo | Tipo | Descripción |
|---|---|---|
tag | string | Identificador de ubicación (p.ej., "default", "warehouse_1") |
quantity | integer | Cantidad disponible en esta ubicación |
Objeto de Precio
| Campo | Tipo | Descripción |
|---|---|---|
tag | string | Identificador de nivel de precio (p.ej., "default", "wholesale") |
currency | string | Código de moneda ISO 4217 (p.ej., "USD", "MXN") |
number | number | Valor del precio |
Objeto de Imagen
| Campo | Tipo | Descripción |
|---|---|---|
url | string | URL completa a la imagen del producto |
Objeto de Atributos Extras
Los campos personalizados pueden incluirse en el objeto extraattributes. Ejemplos comunes:
| Campo | Tipo | Descripción |
|---|---|---|
promociones | string | Información de promociones |
status | string | Estado del producto (activo, inactivo, etc.) |
condicion_venta | string | Condición de venta |
peso | string | Peso del producto |
relacionados | string | Productos relacionados |
custom_01 a custom_03 | string | Campos personalizados |
Ejemplo de Implementación (Node.js/Express)
app.get('/api/products', (req, res) => {
const { offset = 0, next, sortorder = 'desc', jobid } = req.query;
const apiKey = req.headers['t2skey'];
// Validar clave de API
if (apiKey !== process.env.TALK2SYNC_KEY) {
return res.status(401).json({ error: 'No autorizado' });
}
try {
// Obtener productos de tu base de datos
const allProducts = fetchProductsFromDatabase(sortorder);
// Implementar paginación (ejemplo con offset numérico)
const pageSize = 20;
const startIndex = parseInt(offset) || 0;
const paginatedProducts = allProducts.slice(startIndex, startIndex + pageSize);
// Construir respuesta
const response = {
paging: {
pageSize: paginatedProducts.length,
itemsTotal: allProducts.length,
offset: startIndex
},
products: paginatedProducts.map(product => ({
_id: product.id,
sku: product.sku,
last_updated: new Date(product.updatedAt).getTime(),
title: product.name,
url: product.url,
brand: product.brand,
mpn: product.mpn,
model: product.model,
description: product.description,
variations: product.variations.map(v => ({
variationid: v.id,
size: v.size || "",
color: v.color || "",
barcode: v.barcode || "",
availabilities: v.stocks.map(s => ({
tag: s.location || "default",
quantity: s.quantity
})),
prices: v.prices.map(p => ({
tag: p.tier || "default",
currency: p.currency || "USD",
number: p.value
})),
images: v.images.map(img => ({ url: img })),
videos: v.videos.map(vid => ({ url: vid }))
})),
properties: [{
extraattributes: product.customFields || {}
}]
}))
};
res.json(response);
} catch (error) {
console.error('Error al obtener productos:', error);
res.status(500).json({ error: 'Error Interno del Servidor' });
}
});
Códigos de Estado de Respuesta
| Estado | Significado | Acción |
|---|---|---|
200 OK | Productos recuperados exitosamente | Talk2sync procesa los datos |
400 Bad Request | Parámetros inválidos | Verifica tus parámetros de solicitud |
401 Unauthorized | Clave de API inválida o faltante | Verifica tu clave de seguridad |
500 Internal Server Error | Error del servidor | Revisa los registros de tu servidor |
Guías de Paginación
Estrategia de Offset Numérico
Mejor para: Conjuntos de datos pequeños a medianos (< 100,000 elementos)
- Devuelve elementos desde
offsethastaoffset + pageSize - Incrementa
offsetporpageSizepara cada solicitud - Incluye
offseten la respuesta de paginación
Estrategia de Cursor
Mejor para: Conjuntos de datos grandes o datos que cambian frecuentemente
- Codifica el punto de inicio de la siguiente página como un cursor en base64
- Devuelve el cursor en la respuesta como
next - Usa el parámetro
nextpara solicitudes posteriores - Más eficiente para conjuntos de datos grandes
Sincronización y Frecuencia
- Talk2sync solicitará productos según el programa de sincronización configurado en los ajustes de tu conexión
- El parámetro
jobidte ayuda a rastrear qué trabajo de sincronización inició cada solicitud - Cada solicitud debe procesarse y devolver una respuesta dentro de 1 minuto
Buenas Prácticas
✓ Haz:
- Devuelve datos ordenados consistentemente (usa el parámetro
sortorder) - Incluye timestamps de
last_updatedprecisos - Valida la clave de API en cada solicitud
- Implementa paginación para manejar catálogos grandes
- Prueba con varios tamaños de página
- Monitorea los tiempos de respuesta de API
✗ No hagas:
- Incluyas información sensible en respuestas
- Devuelvas el mismo producto múltiples veces
- Ignores el parámetro de ordenamiento
- Devuelvas respuestas mayores a 10MB por página