Eventos
Cómo registrar un endpoint, verificar entregas y leer cada evento.
Hay 39 eventos en 6 categorías. El cuerpo JSON de cada entrega es el modelo del evento, sin sobre común.
Configurar el endpoint
Registra un endpoint con POST /. Al crearlo se envía un evento webhook.endpoint.test a la URL, y el endpoint se guarda solo si responde 2xx.
| Requisito | Valor |
|---|---|
| URL | HTTPS, pública y de hasta 2048 caracteres. No puede resolver a una red privada o local. |
| Unicidad | Una URL por tienda (y por vendedor, si el token es de un vendedor) |
| Respuesta correcta | Cualquier 2xx |
| Tiempo límite | 15 segundos |
Cabeceras de entrega
| Cabecera | Contenido |
|---|---|
X-Ecomiq-Event | Tipo de evento, por ejemplo catalog.product.created |
X-Ecomiq-Delivery | UUID de la entrega |
X-Ecomiq-Timestamp | Momento del intento, en segundos Unix |
X-Ecomiq-Signature | sha256=<hmac>, si el endpoint tiene secret |
Verificar la firma
Con un secret configurado, cada entrega lleva el HMAC-SHA256 del cuerpo crudo en hexadecimal minúscula. Calcúlalo sobre el cuerpo tal como llega, antes de leer el JSON, y descarta el evento si no coincide.
import { createHmac, timingSafeEqual } from "node:crypto"
export function isValidSignature(rawBody: string, header: string, secret: string) {
const expected = createHmac("sha256", secret).update(rawBody).digest("hex")
const received = header.replace(/^sha256=/, "")
const a = Buffer.from(expected, "hex")
const b = Buffer.from(received, "hex")
return a.length === b.length && timingSafeEqual(a, b)
}Autenticación adicional
Con auth, cada entrega incluye credenciales en Authorization. Con headers, agrega cabeceras fijas.
auth.type | auth.config |
|---|---|
basic | Username y Password |
bearer | Token |
oAuth2 | TokenUrl HTTPS pública, ClientId y ClientSecret; opcionales Scope y TokenProperty (por defecto access_token) |
Entrega y reintentos
Responde 2xx dentro de 15 segundos y procesa después. Otro estado o un timeout se reintenta con el mismo X-Ecomiq-Delivery, así que un evento puede llegar más de una vez: procésalo de forma idempotente.
Cada respuesta correcta reinicia el contador de fallos. Tras 10 fallos consecutivos el endpoint se pausa; corrige el receptor y llama a POST /.
Para reenviar una entrega fallida, usa POST /. El reenvío conserva el cuerpo y lleva un X-Ecomiq-Delivery nuevo.
Eventos disponibles
Catálogo
| Evento | Modelo |
|---|---|
catalog.product.created | ProductChangedWebhookModel |
catalog.product.updated | ProductChangedWebhookModel |
catalog.product.deleted | ProductDeletedWebhookModel |
catalog.product.status_changed | ProductStatusChangedWebhookModel |
catalog.stock.changed | StockChangedWebhookModel |
catalog.inventory.batch_processed | InventoryBatchProcessedWebhookModel |
catalog.price.changed | PriceChangedWebhookModel |
catalog.brand.created | BrandWebhookModel |
catalog.brand.updated | BrandWebhookModel |
catalog.brand.deleted | BrandDeletedWebhookModel |
catalog.category.created | CategoryWebhookModel |
catalog.category.updated | CategoryWebhookModel |
catalog.category.deleted | CategoryDeletedWebhookModel |
catalog.collection.created | CollectionWebhookModel |
catalog.collection.updated | CollectionWebhookModel |
catalog.collection.deleted | CollectionDeletedWebhookModel |
Canales
| Evento | Modelo |
|---|---|
channel.listing.published | ListingPublishedWebhookModel |
channel.listing.price_changed | ListingPriceChangedWebhookModel |
channel.created | ChannelCreatedWebhookModel |
channel.sales.enabled | ChannelStateWebhookModel |
channel.deleted | ChannelDeletedWebhookModel |
Operaciones
| Evento | Modelo |
|---|---|
operation.finished | OperationWebhookModel |
Clientes
| Evento | Modelo |
|---|---|
customer.created | CustomerWebhookModel |
Carritos
| Evento | Modelo |
|---|---|
cart.created | CartCreatedWebhookModel |
cart.updated | CartUpdatedWebhookModel |
cart.completed | CartCompletedWebhookModel |
cart.item_added | CartItemWebhookModel |
cart.item_removed | CartItemWebhookModel |
Pedidos
| Evento | Modelo |
|---|---|
order.created | OrderWebhookModel |
order.confirmed | OrderWebhookModel |
order.invoiced | OrderWebhookModel |
order.in_progress | OrderWebhookModel |
order.ready_to_pick_up | OrderWebhookModel |
order.in_transit | OrderWebhookModel |
order.delivered | OrderWebhookModel |
order.cancelled | OrderWebhookModel |
order.returned | OrderWebhookModel |
order.closed | OrderWebhookModel |
order.invalidated | OrderWebhookModel |
Campos del cuerpo
Los campos usan camelCase. Los IDs son strings: guárdalos tal cual, sin convertirlos a número.
ProductChangedWebhookModel
Eventos: catalog.product.created · catalog.product.updated
| Campo | Tipo JSON | Puede ser null | Descripción |
|---|---|---|---|
tenantId | string | No | Identificador de la organización. |
storeId | string | No | Identificador de la tienda. |
sellerId | string | Sí | Identificador del vendedor propietario del producto. |
productId | string | No | Identificador del producto. |
product | object | No | Datos del producto. |
occurredOn | string (date-time) | No | Fecha y hora en que ocurrió el evento. |
targetChannelIds | string[] | No | Identificadores de los canales a los que se dirige el evento. |
changeType | string | No | Indica si el producto se creó o actualizó. |
ProductDeletedWebhookModel
Eventos: catalog.product.deleted
| Campo | Tipo JSON | Puede ser null | Descripción |
|---|---|---|---|
productId | string | No | Identificador del producto. |
tenantId | string | No | Identificador de la organización. |
storeId | string | No | Identificador de la tienda. |
sellerId | string | No | Identificador del vendedor. |
occurredOn | string (date-time) | No | Fecha y hora en que ocurrió el evento. |
ProductStatusChangedWebhookModel
Eventos: catalog.product.status_changed
| Campo | Tipo JSON | Puede ser null | Descripción |
|---|---|---|---|
tenantId | string | No | Identificador de la organización. |
storeId | string | No | Identificador de la tienda. |
productId | string | No | Identificador del producto. |
sellerId | string | No | Identificador del vendedor. |
isActive | boolean | No | Indica si el producto está activo. |
occurredOn | string (date-time) | No | Fecha y hora en que ocurrió el evento. |
StockChangedWebhookModel
Eventos: catalog.stock.changed
| Campo | Tipo JSON | Puede ser null | Descripción |
|---|---|---|---|
tenantId | string | No | Identificador de la organización. |
storeId | string | No | Identificador de la tienda. |
productId | string | No | Identificador del producto. |
variantId | string | No | Identificador de la variante. |
locationId | string | No | Identificador de la ubicación. |
availableQuantity | integer | No | Cantidad de stock disponible. |
occurredOn | string (date-time) | No | Fecha y hora en que ocurrió el evento. |
InventoryBatchProcessedWebhookModel
Eventos: catalog.inventory.batch_processed
| Campo | Tipo JSON | Puede ser null | Descripción |
|---|---|---|---|
tenantId | string | No | Identificador de la organización. |
storeId | string | No | Identificador de la tienda. |
mode | string | No | Modo aplicado al lote de ajustes. |
adjustmentsCount | integer | No | Cantidad de líneas de inventario ajustadas. |
productsCount | integer | No | Cantidad de productos afectados. |
variantsCount | integer | No | Cantidad de variantes afectadas. |
locationsCount | integer | No | Cantidad de ubicaciones afectadas. |
lines | array | No | Líneas de inventario ajustadas. |
occurredOn | string (date-time) | No | Fecha y hora en que ocurrió el evento. |
PriceChangedWebhookModel
Eventos: catalog.price.changed
| Campo | Tipo JSON | Puede ser null | Descripción |
|---|---|---|---|
tenantId | string | No | Identificador de la organización. |
storeId | string | No | Identificador de la tienda. |
productId | string | No | Identificador del producto. |
sellerId | string | No | Identificador del vendedor. |
price | number (decimal) | No | Precio actual del producto. |
compareAtPrice | number (decimal) | Sí | Precio de comparación original. |
currency | string | No | Código de moneda. |
occurredOn | string (date-time) | No | Fecha y hora en que ocurrió el evento. |
BrandWebhookModel
Eventos: catalog.brand.created · catalog.brand.updated
| Campo | Tipo JSON | Puede ser null | Descripción |
|---|---|---|---|
brandId | string | No | Identificador de la marca. |
tenantId | string | No | Identificador de la organización. |
storeId | string | No | Identificador de la tienda. |
name | string | No | Nombre de la marca. |
slug | string | No | Slug de la marca. |
isActive | boolean | Sí | Indica si la marca está activa. |
occurredOn | string (date-time) | No | Fecha y hora en que ocurrió el evento. |
BrandDeletedWebhookModel
Eventos: catalog.brand.deleted
| Campo | Tipo JSON | Puede ser null | Descripción |
|---|---|---|---|
brandId | string | No | Identificador de la marca. |
tenantId | string | No | Identificador de la organización. |
storeId | string | No | Identificador de la tienda. |
occurredOn | string (date-time) | No | Fecha y hora en que ocurrió el evento. |
CategoryWebhookModel
Eventos: catalog.category.created · catalog.category.updated
| Campo | Tipo JSON | Puede ser null | Descripción |
|---|---|---|---|
categoryId | string | No | Identificador de la categoría. |
tenantId | string | No | Identificador de la organización. |
storeId | string | No | Identificador de la tienda. |
name | string | No | Nombre de la categoría. |
slug | string | No | Slug de la categoría. |
parentId | string | Sí | Identificador de la categoría superior. |
isActive | boolean | Sí | Indica si la categoría está activa. |
occurredOn | string (date-time) | No | Fecha y hora en que ocurrió el evento. |
CategoryDeletedWebhookModel
Eventos: catalog.category.deleted
| Campo | Tipo JSON | Puede ser null | Descripción |
|---|---|---|---|
categoryId | string | No | Identificador de la categoría. |
tenantId | string | No | Identificador de la organización. |
storeId | string | No | Identificador de la tienda. |
occurredOn | string (date-time) | No | Fecha y hora en que ocurrió el evento. |
CollectionWebhookModel
Eventos: catalog.collection.created · catalog.collection.updated
| Campo | Tipo JSON | Puede ser null | Descripción |
|---|---|---|---|
collectionId | string | No | Identificador de la colección. |
tenantId | string | No | Identificador de la organización. |
storeId | string | No | Identificador de la tienda. |
name | string | No | Nombre de la colección. |
slug | string | No | Slug de la colección. |
description | string | Sí | Descripción de la colección. |
status | string | No | Estado de la colección. |
type | string | No | Tipo de colección. |
dynamicOperator | string | No | Operador de las reglas dinámicas. |
validFrom | string (date-time) | Sí | Fecha de inicio de la colección. |
validTo | string (date-time) | Sí | Fecha de finalización de la colección. |
imageUrl | string | Sí | URL de la imagen de la colección. |
occurredOn | string (date-time) | No | Fecha y hora en que ocurrió el evento. |
CollectionDeletedWebhookModel
Eventos: catalog.collection.deleted
| Campo | Tipo JSON | Puede ser null | Descripción |
|---|---|---|---|
collectionId | string | No | Identificador de la colección. |
tenantId | string | No | Identificador de la organización. |
storeId | string | No | Identificador de la tienda. |
occurredOn | string (date-time) | No | Fecha y hora en que ocurrió el evento. |
ListingPublishedWebhookModel
Eventos: channel.listing.published
| Campo | Tipo JSON | Puede ser null | Descripción |
|---|---|---|---|
listingId | string | No | Identificador de la publicación. |
channelId | string | No | Identificador del canal. |
productId | string | No | Identificador del producto. |
externalId | string | No | Identificador externo de la publicación. |
tenantId | string | No | Identificador de la organización. |
storeId | string | No | Identificador de la tienda. |
sellerId | string | No | Identificador del vendedor. |
occurredOn | string (date-time) | No | Fecha y hora en que ocurrió el evento. |
ListingPriceChangedWebhookModel
Eventos: channel.listing.price_changed
| Campo | Tipo JSON | Puede ser null | Descripción |
|---|---|---|---|
listingId | string | No | Identificador de la publicación. |
tenantId | string | No | Identificador de la organización. |
storeId | string | No | Identificador de la tienda. |
sellerId | string | No | Identificador del vendedor. |
channelId | string | No | Identificador del canal. |
productId | string | No | Identificador del producto. |
externalId | string | Sí | Identificador externo de la publicación. |
oldPrice | number (decimal) | No | Precio anterior de la publicación. |
newPrice | number (decimal) | No | Nuevo precio de la publicación. |
occurredOn | string (date-time) | No | Fecha y hora en que ocurrió el evento. |
ChannelCreatedWebhookModel
Eventos: channel.created
| Campo | Tipo JSON | Puede ser null | Descripción |
|---|---|---|---|
channelId | string | No | Identificador del canal. |
tenantId | string | No | Identificador de la organización. |
storeId | string | No | Identificador de la tienda. |
sellerId | string | Sí | Identificador del vendedor. |
name | string | No | Nombre del canal. |
integrationId | string | No | Identificador del proveedor. |
channelType | string | No | Tipo de canal. |
isPrincipal | boolean | No | Indica si es el canal principal. |
occurredOn | string (date-time) | No | Fecha y hora en que ocurrió el evento. |
ChannelStateWebhookModel
Eventos: channel.sales.enabled
| Campo | Tipo JSON | Puede ser null | Descripción |
|---|---|---|---|
channelId | string | No | Identificador del canal. |
tenantId | string | No | Identificador de la organización. |
storeId | string | No | Identificador de la tienda. |
sellerId | string | Sí | Identificador del vendedor. |
occurredOn | string (date-time) | No | Fecha y hora en que ocurrió el evento. |
ChannelDeletedWebhookModel
Eventos: channel.deleted
| Campo | Tipo JSON | Puede ser null | Descripción |
|---|---|---|---|
channelId | string | No | Identificador del canal. |
tenantId | string | No | Identificador de la organización. |
storeId | string | No | Identificador de la tienda. |
sellerId | string | Sí | Identificador del vendedor. |
connectionId | string | No | Identificador de la conexión. |
providerId | string | No | Identificador del proveedor. |
occurredOn | string (date-time) | No | Fecha y hora en que ocurrió el evento. |
OperationWebhookModel
Eventos: operation.finished
| Campo | Tipo JSON | Puede ser null | Descripción |
|---|---|---|---|
id | string | No | Identificador de la operación. |
type | string | No | Tipo de operación. |
resource | string | No | Recurso. |
status | string | No | Estado final. |
totalRows | integer | No | Total de filas. |
succeededRows | integer | No | Filas procesadas correctamente. |
failedRows | integer | No | Filas rechazadas. |
completedOn | string (date-time) | No | Fecha de finalización. |
CustomerWebhookModel
Eventos: customer.created
| Campo | Tipo JSON | Puede ser null | Descripción |
|---|---|---|---|
tenantId | string | No | Identificador de la organización. |
storeId | string | No | Identificador de la tienda. |
customerId | string | No | Identificador del cliente. |
email | string | Sí | Correo electrónico del cliente. |
firstName | string | Sí | Nombre del cliente. |
lastName | string | Sí | Apellido del cliente. |
customerType | string | No | Tipo de cliente. |
customerStatus | string | No | Estado del cliente. |
occurredOn | string (date-time) | No | Fecha y hora en que ocurrió el evento. |
CartCreatedWebhookModel
Eventos: cart.created
| Campo | Tipo JSON | Puede ser null | Descripción |
|---|---|---|---|
cartId | string | No | Identificador del carrito. |
tenantId | string | No | Identificador de la organización. |
storeId | string | No | Identificador de la tienda. |
currencyCode | string | No | Código de moneda. |
createdBy | string (uuid) | No | Identificador UUID del actor que creó el carrito. |
occurredOn | string (date-time) | No | Fecha y hora en que ocurrió el evento. |
CartUpdatedWebhookModel
Eventos: cart.updated
| Campo | Tipo JSON | Puede ser null | Descripción |
|---|---|---|---|
cartId | string | No | Identificador del carrito. |
tenantId | string | No | Identificador de la organización. |
storeId | string | No | Identificador de la tienda. |
updatedBy | string (uuid) | No | Identificador UUID del actor que actualizó el carrito. |
occurredOn | string (date-time) | No | Fecha y hora en que ocurrió el evento. |
CartCompletedWebhookModel
Eventos: cart.completed
| Campo | Tipo JSON | Puede ser null | Descripción |
|---|---|---|---|
cartId | string | No | Identificador del carrito. |
tenantId | string | No | Identificador de la organización. |
storeId | string | No | Identificador de la tienda. |
totalAmount | number (decimal) | No | Importe total del carrito. |
currencyCode | string | No | Código de moneda. |
completedBy | string (uuid) | No | Identificador UUID del actor que completó el carrito. |
occurredOn | string (date-time) | No | Fecha y hora en que ocurrió el evento. |
CartItemWebhookModel — cart.item_added
Eventos: cart.item_added
| Campo | Tipo JSON | Puede ser null | Descripción |
|---|---|---|---|
cartId | string | No | Identificador del carrito. |
tenantId | string | No | Identificador de la organización. |
storeId | string | No | Identificador de la tienda. |
cartItemId | string | No | Identificador del artículo del carrito. |
productId | string | No | Identificador del producto. |
variantId | string | No | Identificador de la variante. |
quantity | integer | No | Cantidad agregada. |
unitPrice | number (decimal) | No | Precio unitario. |
actorId | string (uuid) | Sí | Identificador UUID del actor que ejecutó la operación. |
occurredOn | string (date-time) | No | Fecha y hora en que ocurrió el evento. |
CartItemWebhookModel — cart.item_removed
Eventos: cart.item_removed
| Campo | Tipo JSON | Puede ser null | Descripción |
|---|---|---|---|
cartId | string | No | Identificador del carrito. |
tenantId | string | No | Identificador de la organización. |
storeId | string | No | Identificador de la tienda. |
cartItemId | string | No | Identificador del artículo del carrito. |
productId | string | No | Identificador del producto. |
variantId | string | No | Identificador de la variante. |
quantity | integer | Sí | Siempre es null cuando se retira un artículo. |
unitPrice | number (decimal) | Sí | Siempre es null cuando se retira un artículo. |
actorId | string (uuid) | Sí | Identificador UUID del actor que ejecutó la operación. |
occurredOn | string (date-time) | No | Fecha y hora en que ocurrió el evento. |
OrderWebhookModel
Eventos: order.created · order.confirmed · order.invoiced · order.in_progress · order.ready_to_pick_up · order.in_transit · order.delivered · order.cancelled · order.returned · order.closed · order.invalidated
| Campo | Tipo JSON | Puede ser null | Descripción |
|---|---|---|---|
orderId | string | No | Identificador del pedido. |
tenantId | string | No | Identificador de la organización. |
storeId | string | No | Identificador de la tienda. |
sellerId | string | Sí | Identificador del vendedor al que pertenece el pedido. |
customerId | string | Sí | Identificador del cliente. |
orderNumber | string | No | Número del pedido. |
orderGroup | string | Sí | Identificador del grupo de pedidos. |
state | string | No | Estado actual del ciclo de vida del pedido. |
fulfillmentStatus | string | No | Estado actual de preparación y entrega. |
returnStatus | string | No | Estado actual de la devolución. |
currencyCode | string | No | Código de moneda. |
subTotal | number (decimal) | No | Subtotal del pedido. |
shipping | number (decimal) | No | Importe del envío. |
tax | number (decimal) | No | Importe de impuestos. |
total | number (decimal) | No | Total del pedido. |
email | string | Sí | Correo electrónico del cliente. |
firstName | string | Sí | Nombre del cliente. |
lastName | string | Sí | Apellido del cliente. |
cancelReason | string | Sí | Motivo de la cancelación. |
trackingCode | string | Sí | Número de seguimiento. |
trackingUrl | string | Sí | URL de seguimiento. |
carrierName | string | Sí | Nombre del transportista. |
orderDate | string (date-time) | No | Fecha del pedido. |
occurredOn | string (date-time) | No | Fecha y hora en que ocurrió el evento. |
Última actualización: