Saltar al contenido principal

Webhook

Recibe eventos de n1co business en tu punto de conexión de webhook

Escucha eventos de tu cuenta de n1co buiness en tu punto de conexión de webhook para que tu integración pueda activar reacciones automáticas a medida que ocurren eventos en tu cuenta.

Por qué usar webhooks​

Al crear integraciones con n1co Business, es posible que desees que tus aplicaciones reciban eventos a medida que ocurren en tu cuenta, para que tus sistemas de back-end puedan ejecutar las acciones necesarias.

Para habilitar los eventos de webhook, debes registrar los puntos de conexión de webhook. Después de registrarlos, n1co Business puede enviar datos de eventos en tiempo real al punto de conexión de tu aplicación cuando se produzcan eventos en tu cuenta. n1co Business utiliza HTTPS para enviar eventos de webhook a tu aplicación como una carga JSON que incluye un objeto event.

Recibir eventos de webhook es particularmente útil para escuchar eventos asincrónicos, por ejemplo, cuando se crea, paga o anula un pedido, cuando se actualiza el estado de envío de un pedido, etc.

Configuración de webhook​

Para configurar un punto de conexión de webhook, debes proporcionar una URL de punto de conexión y generar una llave secreta. La URL de punto de conexión es la URL a la que n1co Business enviará eventos de webhook. La llave secreta es una cadena utilizada para firmar los eventos de webhook que se envían a tu aplicación. Puedes utilizar la llave secreta para verificar que los eventos que recibes provienen de n1co Business.

Crear un punto de conexión de webhook​

Para crear un punto de conexión de webhook, sigue estos pasos:

  1. Inicia sesión en tu cuenta de n1co business
  2. En el menú de la parte superior derecha, haz clic en Configuración
  3. En la sección Opciones para desarrolladores, haz clic en Webhook
  4. Agrega la URL de tu punto de conexión de webhook y genera una llave secreta, luego haz clic en Guardar Cambios
  5. ¡Listo! Tu punto de conexión de webhook está listo para recibir eventos de n1co business

Eventos de webhook​

n1co Business envía eventos de webhook a tu punto de conexión en tiempo real. Cada evento de webhook incluye un objeto event que contiene información sobre el evento que se ha producido en tu cuenta de n1co Business. Los eventos de webhook se envían como cargas JSON en una solicitud HTTPS POST a tu punto de conexión.

Headers del request​

Cada entrega llega a tu endpoint con estos headers:

HeaderDescripción
X-H4B-Hmac-Sha256HMAC-SHA256 en Base64 del raw body del request, firmado con tu secret key. Ver Verificación de eventos de webhook
X-H4B-Event-IdIdentificador numérico del evento. No cambia entre reenvíos del mismo evento: deduplica por este valor
X-H4B-Event-CreatedFecha y hora UTC (ISO 8601) en que se originó el evento. Tampoco cambia entre reenvíos

El body y la firma no cambian respecto a versiones anteriores; X-H4B-Event-Id y X-H4B-Event-Created son headers adicionales.

  • Si tu comercio tiene varias URLs configuradas (separadas por ;), cada URL recibe su propio X-H4B-Event-Id para el mismo evento.
  • X-H4B-Event-Id también sirve para consultar el evento en la API: GET /api/v3/WebhookEvents/{eventId} devuelve la primera entrega del evento. Ver Recuperar eventos que no pudiste procesar.
  • Si una entrega nueva no se pudo registrar de nuestro lado (por ejemplo, durante una caída), el evento se envía igual, pero sin X-H4B-Event-Id ni X-H4B-Event-Created, y no aparecerá en el historial de entregas ni se podrá reenviar. Deduplica esas entregas por su payload.

Entrega y reintentos​

  • At-least-once, en la medida de lo posible. Una entrega se reintenta 3 veces en cuestión de segundos ante errores de conexión, respuestas 5xx y 408. Después de eso no se reintenta automáticamente. Un mismo evento puede llegar más de una vez y los eventos pueden llegar desordenados.
  • Deduplica por X-H4B-Event-Id. Guarda los identificadores que ya procesaste y descarta los repetidos; es la única forma confiable de no procesar dos veces el mismo evento.
  • Responde rápido. Devuelve un 2xx apenas hayas guardado el payload de tu lado y procésala de forma asíncrona. Cualquier otro status code marca la entrega como no entregada.
  • La API es la source of truth. Usa el webhook como señal y confirma el estado con GET /api/v3/Orders/{id} cuando sea crítico, por ejemplo antes de liberar un producto.
  • Verifica la firma sobre el raw body, antes de parsearlo, con una comparación constant-time.
  • Lo que se escape de los reintentos automáticos lo recuperas con la API de eventos de webhook.

Objeto Event​

El contract para los eventos de webhook es el siguiente:

{
"orderId": "String!",
"orderReference": "String",
"orderType": "String!",
"description": "String!",
"level": "String!",
"type": "String!",
"metadata": "Object"
}

La definición de los campos del objeto event es la siguiente:

orderId: String! -> identificador interno de la orden generado por el sistema de n1co
orderReference: String -> referencia de la orden proporcionada por el integrador
orderType: String! -> tipo de orden que originó el evento
description: String! -> mensaje descriptivo de evento
level: String! -> nivel de severidad del evento
type: String! -> tipo de evento
metadata: Object -> key-value object que contiene información adicional sobre el evento

Niveles de severidad level​

  • Info: Indica información general o eventos que no requieren atención inmediata.
  • Warning: Indica situaciones que podrían requerir atención o investigación, pero que no representan un error crítico o una falla del sistema.
  • Error: Indica un error del sistema que requiere atención.

Tipos de orden orderType​

Indica qué clase de orden originó el evento. Viene en todos los eventos y te permite, por ejemplo, separar la compra de un cupón o una giftcard de una venta normal sin consultar la API.

ValorOrden
COUPON_APPCompra de un cupón
GIFTCARDSCompra de una giftcard
FASTLINK_CHARGEEnlace de pago
FULLOrden completa
STOREFRONTTienda en línea
SUBSCRIPTIONSuscripción
MENU_APPApp de menú
EPAYEPay
SUPER_APPSuperApp
COURIEREnvío por courier
MARKETPLACEn1co plaza
type y orderType no son lo mismo

type es el tipo de evento (Created, SuccessPayment, …). orderType es el tipo de orden que lo originó. Una misma orden emite varios eventos con distinto type, pero todos con el mismo orderType.

Ten en cuenta además que las órdenes creadas desde un enlace de pago llegan como FASTLINK_CHARGE, no como FULL.

Tipos de evento type​

Created​

Este evento indica que se ha creado un nuevo pedido en n1co business.

Ejemplo:

{
"orderId": "1057",
"orderReference": "test-3",
"orderType": "FASTLINK_CHARGE",
"description": "La orden fue creada",
"metadata": null,
"level": "Info",
"type": "Created"
}
SuccessPayment​

Este evento indica que el pago de un pedido ha sido exitoso.

Ejemplo:

{
"orderId": "52544",
"orderReference": null,
"orderType": "COUPON_APP",
"description": "La orden fue pagada exitosamente autorización: 831000",
"metadata": {
"PaymentId": "3aaf6eaf-f32f-4857-8312-e63f4e497822",
"ChargeId": "af543e17-18d9-4512-b1ba-2991b6c31613",
"Status": "SUCCEEDED",
"AuthorizationCode": "831000",
"SequentialNumber": "7744791861156741504807",
"AccountId": "hugoapp.h4b",
"PaymentProcessor": "cybersource",
"PaymentProcessorReference": "7744791861156741504807",
"TransactionDate": "2026-03-25T22:53:06.6475595Z",
"PaidAmount": "8.00",
"BuyerName": "Juan Pérez",
"BuyerPhone": "+50370000000",
"BuyerEmail": "[email protected]",
"BuyerExternalId": "6x1ekkKH1a",
"CheckoutNote": "N/A",
"OrderReference": "",
"OrderTotalDetails": {
"subtotal": "8.0000",
"shippingAmount": "0",
"discountAmount": "0",
"surchargeAmount": "0",
"total": "8.00"
},
"IsManagedPaymentMethod": false,
"InvoiceName": "",
"InvoiceAddress": "",
"InvoiceTaxCode": "",
"orderDetail": [
{
"orderItemId": "13188",
"itemId": "30666",
"name": "Coconut Shrimp",
"price": "8.0000",
"promoId": null,
"promoPrice": null,
"promoName": null,
"quantity": "1",
"modifiersTotal": "0.0000",
"sku": "DL100",
"productImageUrl": "https://cdn.h4b.dev/images/.../Image1.webp",
"modifiers": [],
"note": null,
"description": "8 Camarones empanizados con coco rallado...",
"quantityAvailable": "75",
"requiresShipping": false,
"productMetadata": null,
"coupon": {
"code": "U6FWUW",
"qrCodeUrl": "https://qr.n1co.shop/?chl=U6FWUW",
"startDate": "2026-01-06T18:00:00",
"endDate": "2026-03-31T18:00:00",
"redemptionLimit": "1",
"redemptionCount": "0",
"status": "Unredeemed"
}
}
]
},
"level": "Info",
"type": "SuccessPayment"
}
Detalle de campos de metadata en SuccessPayment​
CampoTipoDescripción
PaymentIdStringIdentificador único del pago
ChargeIdStringIdentificador único del cobro
StatusStringEstado del pago (SUCCEEDED)
AuthorizationCodeStringCódigo de autorización de la transacción
SequentialNumberStringNúmero secuencial de la transacción
AccountIdStringIdentificador de la cuenta del comercio
PaymentProcessorStringProcesador de pago utilizado
PaymentProcessorReferenceStringReferencia del procesador de pago
TransactionDateStringFecha y hora de la transacción (ISO 8601)
PaidAmountStringMonto pagado
BuyerNameStringNombre del comprador
BuyerPhoneStringTeléfono del comprador
BuyerEmailStringEmail del comprador
BuyerExternalIdStringIdentificador externo del comprador
CheckoutNoteStringNota del checkout
OrderReferenceStringReferencia de la orden proporcionada por el integrador
OrderTotalDetailsObjectDesglose de totales de la orden (subtotal, shippingAmount, discountAmount, surchargeAmount, total)
IsManagedPaymentMethodBooleanIndica si el método de pago es gestionado por n1co
InvoiceNameStringNombre para facturación
InvoiceAddressStringDirección para facturación
InvoiceTaxCodeStringCódigo fiscal para facturación
orderDetailArrayDetalle de los productos de la orden (ver tabla siguiente)
Detalle de productos orderDetail​
CampoTipoDescripción
orderItemIdStringIdentificador del ítem en la orden
itemIdStringIdentificador del producto
nameStringNombre del producto
priceStringPrecio unitario del producto
promoIdString | nullIdentificador de la promoción aplicada
promoPriceString | nullPrecio promocional
promoNameString | nullNombre de la promoción
quantityStringCantidad del producto
modifiersTotalStringTotal de modificadores aplicados
skuStringSKU del producto
productImageUrlStringURL de la imagen del producto
modifiersArrayLista de modificadores aplicados al producto
noteString | nullNota del producto
descriptionStringDescripción del producto
quantityAvailableStringCantidad disponible en inventario
requiresShippingBooleanIndica si el producto requiere envío
productMetadataObject | nullMetadatos adicionales del producto
couponObject | nullCupón asociado al producto (ver tabla siguiente). Es null si el producto no tiene cupón
Objeto coupon​

Cuando un producto tiene un cupón asociado, el campo coupon contiene la información del cupón generado para esa compra.

CampoTipoDescripción
codeStringCódigo del cupón
qrCodeUrlStringURL del código QR para el cupón
startDateStringFecha de inicio de validez del cupón (ISO 8601)
endDateStringFecha de expiración del cupón (ISO 8601)
redemptionLimitStringNúmero máximo de veces que el cupón puede ser redimido
redemptionCountStringNúmero de veces que el cupón ha sido redimido
statusStringEstado actual del cupón

Estados posibles del cupón (status):

  • Unredeemed: El cupón está activo y disponible para ser redimido
  • Redeemed: El cupón ya alcanzó su límite de redenciones
  • Expired: El cupón ha expirado (la fecha actual es posterior a endDate)
  • Scheduled: El cupón aún no está activo (la fecha actual es anterior a startDate)
Cancelled​

Este evento indica que un pedido ha sido anulado.

Ejemplo:

{
"orderId": "32395",
"orderReference": null,
"description": "La orden fue cancelada, motivo: some reason",
"metadata": null,
"level": "Info",
"type": "Cancelled"
}
Finalized​

Este evento indica que el estado de un pedido ha sido finalizado.

Ejemplo:

{
"orderId": "32395",
"orderReference": null,
"description": "Se finalizó la orden.",
"metadata": null,
"level": "Info",
"type": "Finalized"
}
Updated​

Este evento indica que se ha actualizado el estado de envío de un pedido en n1co business.

Listado de estados de envío:

  • PENDING: Orden pendiente
  • ACCEPTED: Orden aceptada
  • READY: Orden lista
  • DISPATCHED: Orden despachada
  • ON_ITS_WAY: Orden en camino
  • DELIVERED: Orden entregada
  • SCHEDULED: Orden programada
  • REJECTED: Orden rechazada

Ejemplos:

Para el cambio de estado de PENDING a ACCEPTED:

{
"orderId": "13766",
"orderReference": null,
"description": "Se cambió el estado del envío de Pendiente a Aceptado",
"metadata": {
"PreparationEtaMinutes": "15",
"PreviousStatus": "PENDING",
"NewStatus": "ACCEPTED"
},
"level": "Info",
"type": "Updated"
}

Para el cambio de estado de ACCEPTED a READY:

{
"orderId": "13766",
"orderReference": null,
"description": "Se cambió el estado del envío de Aceptado a Preparado",
"metadata": {
"PreviousStatus": "ACCEPTED",
"NewStatus": "READY"
},
"level": "Info",
"type": "Updated"
}

Para el cambio de estado de READY a DISPATCHED:

{
"orderId": "13766",
"orderReference": null,
"description": "Se cambió el estado del envío de Preparado a Despachado",
"metadata": {
"PreviousStatus": "READY",
"NewStatus": "DISPATCHED"
},
"level": "Info",
"type": "Updated"
}

Para el cambio de estado de DISPATCHED a ON_ITS_WAY:

{
"orderId": "13766",
"orderReference": null,
"description": "Se cambió el estado del envío de Despachado a En Camino",
"metadata": {
"PreviousStatus": "DISPATCHED",
"NewStatus": "ON_ITS_WAY"
},
"level": "Info",
"type": "Updated"
}

Para el cambio de estado de ON_ITS_WAY a DELIVERED:

{
"orderId": "13766",
"orderReference": null,
"description": "Se cambió el estado del envío de En Camino a Entregado",
"metadata": {
"PreviousStatus": "ON_ITS_WAY",
"NewStatus": "DELIVERED"
},
"level": "Info",
"type": "Updated"
}
Deleted​

Este evento indica que un pedido ha sido eliminado.

Ejemplo:

{
"orderId": "32395",
"orderReference": null,
"description": "Se eliminó la orden",
"metadata": null,
"level": "Info",
"type": "Deleted"
}
SuccessReverse​

Este evento indica que se ha realizado una reversión exitosa de un pago.

Ejemplo:

{
"orderId": "1056",
"orderReference": null,
"description": "El pago de la orden fue revertido",
"metadata": null,
"level": "Info",
"type": "SuccessReverse"
}
ReverseError​

Este evento indica que se ha producido un error al intentar revertir un pago.

Ejemplo:

{
"orderId": "1056",
"orderReference": null,
"description": "La orden no pudo ser cancelada, no se pudo revertir el pago",
"metadata": null,
"level": "Error",
"type": "ReverseError"
}
PaymentError​

Este evento indica que se ha producido un error al intentar realizar un pago.

Ejemplo:

{
"orderId": "1056",
"orderReference": null,
"description": "El pago no fue realizado: some error",
"metadata": null,
"level": "Error",
"type": "PaymentError"
}
ThreeDSecureAuthSucceeded​

Este evento indica que la autenticación 3DS se completó correctamente para un cobro específico y por ende se puede proceder con la confirmación de la transacción utilizando el authenticationId provisto en la metadata del evento.

Ejemplo:

{
"orderId": "31833",
"orderReference": "order-integration-id",
"description": "La autenticación 3DS ha sido completada con éxito",
"metadata": {
"authenticationId": "fdedee2f-5942-47ff-83a5-cb473d0e8764"
},
"level": "Info",
"type": "ThreeDSecureAuthSucceeded"
}
ThreeDSecureAuthError​

Este evento indica que se produjo un error durante la autenticación 3DS para un cobro específico. El error puede deberse a varios motivos, como información incorrecta del titular de la tarjeta, problemas técnicos con el proveedor de autenticación 3DS o problemas de conectividad. Para más detalle se pueden consultar los atributos reason y description incluídos en la metadata del evento.

Ejemplo:

{
"orderId": "31833",
"orderReference": "order-integration-id",
"description": "Ocurrió un error en la autenticación 3DS",
"metadata": {
"authenticationId": "fdedee2f-5942-47ff-83a5-cb473d0e8764",
"reason" : "Some reason",
"description" : "Some description",
},
"level": "Error",
"type": "ThreeDSecureAuthError"
}
ThreeDSecureAuthExpired​

Este evento es un indicador de que la autenticación 3DS no se completó a tiempo y que la transacción no se puede completar en este momento. Se puede volver a intentar la transacción más tarde una vez que el titular de la tarjeta inicie una nueva solicitud de autenticación.

Ejemplo:

{
"orderId": "31833",
"orderReference": "order-integration-id",
"description": "La autenticación 3DS ha expirado",
"metadata": {
"authenticationId": "fdedee2f-5942-47ff-83a5-cb473d0e8764"
},
"level": "Info",
"type": "ThreeDSecureAuthExpired"
}
ThreeDSecureAuthFailed​

Este evento indica que hubo un fallo técnico que impidió que la autenticación 3DS se completara correctamente para un pedido específico. El fallo puede deberse a problemas con el proveedor de autenticación 3DS, problemas de integración o problemas del lado del servidor. Para más detalle se pueden consultar los atributos reason y description incluídos en la metadata del evento.

Ejemplo:

{
"orderId": "31833",
"orderReference": "order-integration-id",
"description": "Ocurrió un fallo en la autenticación 3DS",
"metadata": {
"authenticationId": "fdedee2f-5942-47ff-83a5-cb473d0e8764",
"reason" : "Some reason",
"description" : "Some description",
},
"level": "Error",
"type": "ThreeDSecureAuthFailed"
}

Verificación de eventos de webhook​

Para verificar que los eventos de webhook que recibes provienen de n1co buiness, puedes utilizar la llave secreta que generaste al configurar tu punto de conexión de webhook. Para verificar un evento de webhook, sigue estos pasos:

  1. Extrae el valor de la cabecera X-H4B-Hmac-Sha256 de la solicitud HTTP POST que contiene el evento de webhook.
  2. Calcula el HMAC SHA-256 del raw body del request HTTP POST, antes de parsearlo, utilizando el secret key generado al configurar tu endpoint de webhook.
  3. Compara el resultado en Base64 con el valor del header usando una comparación constant-time.

Ejemplo de verificación de eventos de webhook​

Node.js​
const crypto = require("crypto");
const express = require("express");

const app = express();

// Usa el raw body tal como llegó; no lo vuelvas a serializar
app.post("/webhook", express.raw({ type: "application/json" }), (req, res) => {
// Llave secreta configurada en el portal de n1co Business (Configuración → Webhook)
const API_SECRET = process.env.API_SECRET;

// Firma enviada por n1co (Base64)
const hmacHeader = req.get("X-H4B-Hmac-Sha256") || "";

// Calcular el HMAC SHA-256 del raw body y codificarlo en Base64
const hash = crypto.createHmac("sha256", API_SECRET).update(req.body).digest("base64");

// Comparación en tiempo constante
const expected = Buffer.from(hash);
const received = Buffer.from(hmacHeader);
if (expected.length !== received.length || !crypto.timingSafeEqual(expected, received)) {
console.log("Firma inválida");
return res.sendStatus(401);
}

const event = JSON.parse(req.body.toString("utf8"));
console.log("Firma válida", event.type);
res.sendStatus(200);
});
Python​
import base64
import hashlib
import hmac
import os

from flask import Flask, request, abort

app = Flask(__name__)

@app.route("/webhook", methods=["POST"])
def webhook():
# Llave secreta configurada en el portal de n1co Business (Configuración → Webhook)
api_secret = os.environ["API_SECRET"]

# Firma enviada por n1co (Base64)
hmac_header = request.headers.get("X-H4B-Hmac-Sha256", "")

# Usa el raw body tal como llegó; no lo vuelvas a serializar
raw_body = request.get_data()

# Calcular el HMAC SHA-256 del raw body y codificarlo en Base64
digest = hmac.new(api_secret.encode("utf-8"), raw_body, hashlib.sha256).digest()
expected = base64.b64encode(digest).decode("ascii")

# Comparación en tiempo constante
if not hmac.compare_digest(expected, hmac_header):
print("Firma inválida")
abort(401)

event = request.get_json()
print("Firma válida", event.get("type"))
return "", 200

if __name__ == "__main__":
app.run()
PHP​
<?php

// Llave secreta configurada en el portal de n1co Business (Configuración → Webhook)
$apiSecret = getenv("API_SECRET");

// Firma enviada por n1co (Base64)
$hmacHeader = $_SERVER["HTTP_X_H4B_HMAC_SHA256"] ?? "";

// Usa el raw body tal como llegó; no lo vuelvas a serializar
$rawBody = file_get_contents("php://input");

// Calcular el HMAC SHA-256 del raw body y codificarlo en Base64
$expected = base64_encode(hash_hmac("sha256", $rawBody, $apiSecret, true));

// Comparación en tiempo constante
if (!hash_equals($expected, $hmacHeader)) {
echo "Firma inválida";
http_response_code(401);
exit;
}

$event = json_decode($rawBody, true);
echo "Firma válida";
http_response_code(200);

Recuperar eventos que no pudiste procesar​

Si tu endpoint estuvo caído o respondió con un error, no necesitas pedirle nada al comercio: la API de integración expone el historial de entregas de tu webhook y te permite reenviarlas.

URL basehttps://api.n1co.com/api/v3
AutenticaciónEl mismo token Bearer que el resto de la API, obtenido con tus credenciales de cliente (clientId / clientSecret)
AlcanceCada llamada solo ve las entregas del comercio asociado a tus credenciales
MétodoRutaPara qué
GET/WebhookEventsListar entregas, de la más reciente a la más antigua, paginadas
GET/WebhookEvents/{id}Consultar una entrega
POST/WebhookEvents/{id}/ResendVolver a enviar el payload de una entrega, de forma síncrona

Entregas y eventos​

  • Entrega: un POST HTTP de un webhook a una URL. Cada entrega queda registrada y tiene un id. Los id solo crecen con el tiempo.
  • Evento: lo que ocurrió, por ejemplo un pago. Un evento tiene una o más entregas: la primera, más una por cada reenvío. Su eventId es el id de su primera entrega, así que GET /api/v3/WebhookEvents/{eventId} devuelve esa primera entrega.

El objeto entrega​

{
"id": 1201,
"eventId": 1201,
"eventType": "SuccessPayment",
"eventCreated": "2026-09-02T15:04:05Z",
"url": "https://example.com/n1co/webhook",
"payload": "{\"orderId\":\"123\",\"type\":\"SuccessPayment\"}",
"responseStatusCode": 503,
"delivered": false,
"created": "2026-09-02T15:04:05"
}
CampoTipoDescripciónFiltrar / ordenar
idIntegerIdentificador de esta entregaSí
eventIdIntegerIdentificador del evento, compartido por la entrega original y sus reenvíos. Es igual a id en una primera entrega y es el valor que viaja en X-H4B-Event-IdNo
eventTypeStringTipo de evento, el mismo type del objeto eventSí
eventCreatedStringFecha y hora UTC del evento original. No cambia entre reenvíosNo
urlStringURL a la que se hizo esta entregaNo
payloadStringBody exacto que se envió, como string JSONNo
responseStatusCodeIntegerStatus code HTTP con que respondió tu endpoint. 0 es una entrega que no ha terminado. 500 también cubre fallos de conexión y timeoutsSí
deliveredBooleantrue cuando tu endpoint respondió 2xxSí
createdStringFecha y hora UTC en que se registró esta entregaSí

Todas las fechas están en UTC. El signing key y los headers del request y del response nunca se devuelven.

Listar entregas​

GET /api/v3/WebhookEvents lista las entregas de tu comercio.

Valor por defecto
FiltroNinguno: todas las entregas del comercio, entregadas, fallidas, in-flight y reenvíos
OrdenDe la más reciente a la más antigua, por id descendente
page1 si se omite. Un valor menor que 1 se rechaza con 400
pageSize50 si se omite. Un valor mayor que 100 se reduce a 100. Un valor de 0 o menor se rechaza con 400

Query params, los mismos de filtrado, orden y paginación del resto de la API v3:

ParámetroEjemploNotas
filtersdelivered==false,id%3E1150La coma equivale a AND. Operadores: ==, !=, >, <, >=, <=, @= (contiene) y _= (empieza con). Aplica URL-encode al valor: un < o > sin encodear en el query string se rechaza con 404, así que id>1150 se envía como id%3E1150
sortsid o -idReemplaza el orden por defecto. El prefijo - ordena de forma descendente
page1Empieza en 1
pageSize100Máximo 100

Respuesta:

{
"webhookEvents": [ { "...": "objeto entrega" } ],
"totalCount": 1
}

totalCount cuenta todas las entregas que cumplen filters, sumando todas las páginas.

Uso recomendado: consultar con un cursor de id​

Usa el id de la entrega como cursor en lugar de números de página: los números de página se desplazan a medida que llegan entregas nuevas y el cursor no.

  1. Guarda el último id de entrega que procesaste.
  2. Pide lo que viene después, de la más antigua a la más reciente:
    GET /api/v3/WebhookEvents?filters=id%3E1150&sorts=id&pageSize=100
    Envía siempre sorts=id al consultar con cursor. Sin él la lista viene de la más reciente a la más antigua, y una página después de tu cursor se salta las entregas intermedias más antiguas.
  3. Procesa la página, mueve el cursor al último id de esa página y repite pidiendo la página 1 hasta que una página venga vacía.
  4. Para recuperar un evento, pasa su payload al mismo handler que atiende tu endpoint de webhook. Solo necesitas reenviar cuando quieres una nueva entrega HTTP.

Para ver solo las fallidas, agrega delivered==false:

GET /api/v3/WebhookEvents?filters=delivered==false,id%3E1150&sorts=id&pageSize=100
Muchas veces no hace falta reenviar

payload es exactamente el body que se envió a tu URL, así que lo más simple suele ser pasárselo al mismo handler que atiende tu endpoint de webhook.

Errores comunes​

  • Una entrega fallida sigue fallida después de un reenvío exitoso. El reenvío es una entrega nueva con el mismo eventId, y la original conserva delivered: false. Por eso delivered==false puede listar eventos que ya se entregaron después. Agrupa por eventId: un evento sigue pendiente solo mientras ninguna de sus entregas tenga delivered: true.
  • Deduplica por eventId. Es igual al header X-H4B-Event-Id, así que puedes descartar los eventos que ya procesaste desde el webhook en vivo.
  • Un responseStatusCode de 0 es una entrega que seguía in-flight o que se interrumpió. Vuelve a consultarla antes de tratarla como fallida.
  • Filtra por id> siempre que puedas. Los filtros por delivered, created o eventType sin un cursor id> son más lentos en comercios con mucho historial, y lo mismo pasa con el totalCount que acompaña cada página.
  • Las entregas que no se pudieron registrar no aparecen. Llegaron sin X-H4B-Event-Id ni X-H4B-Event-Created (ver Headers del request); deduplícalas por su payload.

Consultar una entrega​

GET /api/v3/WebhookEvents/{id} devuelve un objeto entrega.

StatusCuándo
200La entrega existe para tu comercio
404El id no existe o pertenece a otro comercio

Reenviar una entrega​

POST /api/v3/WebhookEvents/{id}/Resend vuelve a enviar el payload almacenado de la entrega {id}, de forma síncrona, y devuelve la nueva entrega.

  • Se firma con el signing key vigente del webhook del comercio y va a su configuración actual.
  • Lleva el X-H4B-Event-Id y el X-H4B-Event-Created originales, así que un consumidor que deduplica lo reconoce.
  • Se registra como una entrega nueva, con un id nuevo y el mismo eventId.
  • Reenviar un reenvío conserva el identificador del evento original.

¿Qué URL lo recibe?

Configuración del comercioDestino
La URL de la entrega sigue configuradaSolo esa URL. La comparación ignora espacios alrededor y mayúsculas/minúsculas
La URL de la entrega ya no está configuradaTodas las URLs configuradas. La respuesta es una entrega fallida si alguna falló; si no, la última

La respuesta es el objeto de la nueva entrega: su campo delivered te dice de inmediato si tu endpoint la aceptó.

StatusCuándo
200Se envió. Revisa delivered en el body del response: un 200 aquí no significa que tu endpoint lo aceptó
400El comercio no tiene webhook configurado, o su configuración de URL no contiene ninguna URL
404El id no existe o pertenece a otro comercio
500El reenvío no se pudo registrar. Es seguro reintentar, porque cada entrega lleva el mismo X-H4B-Event-Id
El reenvío no reemplaza la deduplicación

Un reenvío llega con el X-H4B-Event-Id del evento original. Si ya habías procesado ese evento, tu handler debe descartarlo.

Limitaciones conocidas​

  • eventId y eventCreated no se pueden usar en filters ni en sorts.
  • Los reintentos automáticos siguen deteniéndose a los pocos segundos. Esta API es el camino de recuperación para todo lo que se escape.