Saltar al contenido principal
Version: 2.0

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.

Objeto Event​

El contract para los eventos de webhook es el siguiente:

{
"orderId": "String!",
"orderReference": "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
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 evento type​

Created​

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

Ejemplo:

{
"orderId": "1057",
"orderReference": "test-3",
"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,
"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 cuerpo de la solicitud HTTP POST utilizando la llave secreta generada al configurar tu punto de conexión de webhook.

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);