Webhooks Data Center
Los webhooks permiten que las aplicaciones externas reciban notificaciones en tiempo real cuando se producen determinados eventos en el Babel Licensing Service. Úselos para conectar sus sistemas existentes, automatizar flujos de trabajo y mantener los datos sincronizados.

Webhooks
Acceder a los webhooks
Los webhooks están disponibles en el menú de navegación principal del Babel Licensing Service. Haga clic en el elemento de menú «Webhooks» de la barra lateral izquierda para acceder a la interfaz de gestión de webhooks.
Gestionar los webhooks
Ver los webhooks
La página de webhooks muestra una tabla con todas las suscripciones de webhook configuradas y sus detalles:
- Name: un nombre descriptivo del webhook
- URL: el punto de acceso al que se envían las notificaciones de eventos. La URL se muestra como un vínculo en el que se puede hacer clic solo cuando usa http o https.
- Event: el tipo de evento al que está suscrito el webhook
- Owner User: el usuario que creó el webhook
- Sent At: la marca de tiempo de la última entrega de un evento
- Next Retry: cuándo se hará el siguiente intento de entrega (si procede)
- Status: el estado actual del webhook (OK, Error, etc.)
Añadir un webhook nuevo
Abrir el formulario del webhook nuevo
Haga clic en el botón «+ ADD» (añadir) de la esquina superior derecha de la página de webhooks.
Rellenar la información obligatoria
- Name: introduzca un nombre descriptivo para el webhook
- URL: indique la URL del punto de acceso al que deben enviarse las notificaciones
- Event: seleccione el tipo o los tipos de evento a los que quiere suscribirse
- Secret: genere o introduzca una clave secreta para verificar las solicitudes
Guardar el webhook
Haga clic en «Save» (guardar) para crear la suscripción de webhook.
Editar un webhook
Buscar el webhook
Busque el webhook en la lista.
Abrir el editor
Haga clic en el icono de edición (lápiz) de la fila.
Modificar los detalles
Modifique los detalles del webhook.
Guardar los cambios
Haga clic en «Save» para actualizar la suscripción de webhook.
Eliminar un webhook
Buscar la suscripción de webhook
Busque la suscripción de webhook en la lista.
Eliminarla
Haga clic en el icono de eliminación (papelera) de la fila.
Confirmar la eliminación
Confirme la eliminación cuando se le pida.
Probar un webhook
Buscar la suscripción de webhook
Busque la suscripción de webhook en la lista.
Enviar un evento de prueba
Haga clic en el icono de actualización para enviar un evento de prueba.
Ver el resultado de la entrega
Vea el resultado de la entrega en los detalles de los eventos del webhook.
El sistema procesa el evento de prueba con el mismo mecanismo de entrega que los eventos reales, con las mismas cabeceras y la misma verificación de firma, de modo que puede validar cómo trata su punto de acceso las cargas útiles de los webhooks.
Detalles de los eventos de un webhook
Cuando se desencadena un webhook, la vista expandida muestra los detalles de la entrega:
- Timestamp: cuándo se produjo el evento
- Event Type: el tipo de evento (por ejemplo, license.created)
- Status: el estado de la entrega (OK, Failed)
- Response: la respuesta recibida de su punto de acceso
- Error: los mensajes de error (si la entrega falló)
- Retry Count: el número de intentos de entrega
- Next Retry: cuándo se hará el siguiente reintento (si procede)
Eventos admitidos
El Babel Licensing Service admite los siguientes eventos de webhook:
Licencias
- license.created Se desencadena cuando se crea una licencia nueva.
- license.updated Se desencadena cuando se actualiza una licencia existente.
- license.deleted Se desencadena cuando se elimina una licencia.
- license.expiring Se desencadena cuando una licencia está a punto de caducar.
- license.expired Se desencadena cuando una licencia ha caducado.
- license.revoked Se desencadena cuando se revoca una licencia.
- license.supportexpiring Se desencadena cuando el soporte de una licencia está a punto de vencer.
- license.supportexpired Se desencadena cuando el soporte de una licencia ha vencido.
- license.activated Se desencadena cuando se activa una licencia.
- license.deactivated Se desencadena cuando se desactiva una licencia.
- license.requested Se desencadena cuando se solicita una licencia.
- license.released Se desencadena cuando se libera una licencia.
Pedidos
- order.created Se desencadena cuando se crea un pedido nuevo.
- order.updated Se desencadena cuando se actualiza un pedido existente.
- order.deleted Se desencadena cuando se elimina un pedido.
Informes
report.created Se desencadena cuando se crea un informe nuevo.
Referencia de la carga útil de los webhooks
Esta sección describe con detalle la estructura y el contenido de la carga útil de los eventos de webhook para los distintos tipos de evento.
Carga útil de los eventos de licencia
Al tratar un evento de licencia (como license.created), la carga útil incluye los campos siguientes:
{
"id": 101,
"licenseId": "LIC-0001",
"userKey": "XJK-SHJD-GE5E",
"licensee": "Acme Corp",
"licensingMode": 1,
"issueDate": "2025-03-16T00:00:00Z",
"supportExpireDate": "2026-03-16T00:00:00Z",
"expireDate": "2025-12-31T23:59:59Z",
"customerId": 501,
"orderId": 302,
"templateId": 10,
"revoked": false,
"trace": false,
"eventType": "license.created",
"timestamp": "2025-03-16T12:00:00Z"
}| Campo | Tipo | Descripción |
|---|---|---|
id | Entero | El identificador único de la licencia en la base de datos. Se usa como referencia en la API y para el seguimiento interno. |
licenseId | Cadena | Un identificador de licencia legible por personas (por ejemplo, «LIC-0001») que se usa en las comunicaciones con los clientes y en la documentación. |
userKey | Cadena | La clave de activación que los usuarios finales introducen para activar el software con licencia. |
licensee | Cadena | El nombre de la persona o de la organización a la que se emite la licencia. |
licensingMode | Entero | La modalidad de licencia aplicada (por ejemplo, «0: File», «1: Activation», «2: Floating»). |
issueDate | Fecha y hora ISO 8601 | La fecha y la hora en que se emitió la licencia por primera vez. |
supportExpireDate | Fecha y hora ISO 8601 | La fecha y la hora en que termina el soporte técnico de esta licencia. |
expireDate | Fecha y hora ISO 8601 | La fecha y la hora en que la propia licencia caduca y deja de ser válida. |
customerId | Entero | Referencia al cliente propietario de esta licencia. Corresponde a un registro de cliente del sistema. |
orderId | Entero | Referencia al pedido con el que se compró esta licencia. |
templateId | Entero | El id de la plantilla de licencia con la que se generó esta licencia, que determina sus funciones y sus limitaciones. |
revoked | Booleano | Indica si la licencia se ha invalidado de forma administrativa (true) o sigue activa (false). |
trace | Booleano | Indica si la licencia tiene la traza activada. |
eventType | Cadena | Identifica el tipo de evento concreto que desencadenó este webhook (por ejemplo, «license.created», «license.updated»). |
timestamp | Fecha y hora ISO 8601 | El momento exacto en que se produjo el evento y se envió el webhook. |
Carga útil de los eventos de pedido
En los eventos relacionados con pedidos (como order.created), la carga útil del webhook contiene estos campos:
{
"id": 202,
"orderNumber": "ORD-12345",
"customerId": 501,
"createdAt": "2025-03-16T12:00:00Z",
"status": "completed",
"eventType": "order.created",
"timestamp": "2025-03-16T12:05:00Z"
}| Campo | Tipo | Descripción |
|---|---|---|
id | Entero | El identificador único del pedido en la base de datos. Use este id en las llamadas a la API para obtener los detalles del pedido. |
orderNumber | Cadena | Un número de referencia del pedido legible por personas, que se usa en las comunicaciones con los clientes y en los registros financieros. |
customerId | Entero | El identificador único del cliente que hizo el pedido. Hace referencia a un registro de cliente. |
createdAt | Fecha y hora ISO 8601 | La fecha y la hora en que el pedido se creó en el sistema. |
status | Cadena | El estado de procesamiento actual del pedido. Los valores posibles son: «pending», «processing», «completed», «cancelled», «refunded». |
eventType | Cadena | Identifica qué evento de pedido desencadenó este webhook (por ejemplo, «order.created», «order.updated», «order.deleted»). |
timestamp | Fecha y hora ISO 8601 | El momento exacto en que se produjo el evento y se envió el webhook. |
Carga útil de los eventos de informe
En los eventos relacionados con informes (como report.created), la carga útil del webhook incluye estos campos:
{
"id": 303,
"name": "Monthly Report",
"date": "2025-03-15T00:00:00Z",
"eventType": "report.created",
"timestamp": "2025-03-16T12:10:00Z"
}| Campo | Tipo | Descripción |
|---|---|---|
id | Entero | El identificador único del informe en la base de datos. Use este id para obtener el informe completo mediante la API. |
name | Cadena | El título descriptivo del informe, tal como está definido en el sistema. |
date | Fecha y hora ISO 8601 | La fecha asociada al contenido del informe (normalmente, la fecha final del período del informe). |
eventType | Cadena | Identifica qué evento de informe desencadenó este webhook (actualmente solo «report.created»). |
timestamp | Fecha y hora ISO 8601 | El momento exacto en que se produjo el evento y se envió el webhook. |
Entrega de webhooks y lógica de reintentos
El Babel Licensing Service procesa los webhooks mediante un servicio en segundo plano que se ejecuta de forma continua:
- El servicio comprueba cada 30 segundos si hay eventos de webhook nuevos
- Los webhooks se procesan en lotes de hasta 50 eventos cada vez
- El sistema trata tanto los eventos pendientes (nuevos) como los eventos que fallaron antes y tienen un reintento programado
- Cada entrega de webhook incluye cabeceras estándar:
User-Agent: identifica al Babel Licensing ServiceX-Babel-Webhook-Id: el identificador único de la entrega del webhookX-Babel-Event: el tipo de evento que se entregaX-Babel-Timestamp: cuándo se envió el eventoX-Babel-Signature: la firma HMAC-SHA256 (si hay un secreto configurado)
Mecanismo de reintento
Cuando falla la entrega de un webhook:
- El sistema programa automáticamente un reintento para 5 minutos después
- Cada webhook se puede configurar con un número máximo de reintentos
- Los eventos fallidos permanecen en el sistema hasta que se entregan correctamente o se alcanza el número máximo de reintentos
- La interfaz de webhooks muestra la hora del siguiente reintento programado de las entregas fallidas
- Cada entrega fallida guarda el mensaje de error o el código de estado HTTP para la solución de problemas
Estado de los webhooks
Los webhooks del sistema pueden tener los estados siguientes:
- OK: el evento se entregó correctamente
- Failed: la entrega del evento falló y se superó el máximo de reintentos
- Pending: el evento está a la espera de procesarse
- Scheduled: la entrega del evento falló y tiene un reintento programado
Proteger los webhooks
Todas las solicitudes de webhook incluyen una firma en la cabecera X-Babel-Signature. La firma se genera con HMAC-SHA256, a partir de la clave secreta de su webhook y del cuerpo de la solicitud.
Para verificar el webhook:
Obtener la firma
Obtenga la firma de la cabecera X-Babel-Signature.
Calcular la firma esperada
Calcule una firma HMAC-SHA256 con su clave secreta y el cuerpo sin procesar de la solicitud.
Comparar las firmas
Compare la firma calculada con la de la cabecera.
Procesar solo si coinciden
Procese el webhook solo si las firmas coinciden.
Código de verificación de ejemplo (C#):
private bool VerifyWebhookSignature(string payload, string signatureHeader, string secret)
{
using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(secret));
var computedHash = hmac.ComputeHash(Encoding.UTF8.GetBytes(payload));
var computedSignature = Convert.ToBase64String(computedHash);
return signatureHeader == computedSignature;
}Implementar un receptor de webhooks
A continuación se muestra un ejemplo completo de cómo implementar en ASP.NET Core un receptor de webhooks que valida correctamente las firmas de los webhooks:
// WebhookValidator.cs
using System;
using System.Security.Cryptography;
using System.Text;
namespace YourProject.Utilities
{
public static class WebhookValidator
{
/// <summary>
/// Validates the webhook payload against the provided signature using HMAC-SHA256.
/// </summary>
/// <param name="payload">The raw JSON payload.</param>
/// <param name="secret">The shared secret.</param>
/// <param name="signature">The signature from the incoming request header.</param>
/// <returns>True if the signature is valid; otherwise, false.</returns>
public static bool ValidateSignature(string payload, string secret, string signature)
{
using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(secret));
var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(payload));
var computedSignature = BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant();
return string.Equals(computedSignature, signature, StringComparison.OrdinalIgnoreCase);
}
}
}
// WebhookController.cs
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System.IO;
using System.Threading.Tasks;
using YourProject.Utilities;
namespace YourProject.Controllers
{
[ApiController]
[Route("api/webhook")]
public class WebhookController : ControllerBase
{
private readonly ILogger<WebhookController> _logger;
// Ideally, the secret comes from configuration
private readonly string _webhookSecret = "your-webhook-secret";
public WebhookController(ILogger<WebhookController> logger)
{
_logger = logger;
}
[HttpPost]
public async Task<IActionResult> ReceiveWebhook()
{
// Read the payload from the request body
var payload = await new StreamReader(Request.Body).ReadToEndAsync();
// Retrieve the signature from the request headers
if (!Request.Headers.TryGetValue("X-Babel-Signature", out var incomingSignature))
{
_logger.LogWarning("Missing X-Babel-Signature header");
return Unauthorized("Signature header missing");
}
// Validate the signature
if (!WebhookValidator.ValidateSignature(payload, _webhookSecret, incomingSignature))
{
_logger.LogWarning("Invalid webhook signature");
return Unauthorized("Invalid signature");
}
// Process the webhook payload
_logger.LogInformation("Webhook payload validated and processed");
// TODO: Deserialize and process the payload as needed
return Ok();
}
}
}Prácticas recomendadas para recibir webhooks
Al implementar un receptor de webhooks:
- Valide siempre las firmas: use el código de validación de firmas proporcionado para verificar la autenticidad de cada webhook
- Guarde de forma segura el secreto del webhook: no lo escriba en el código como en el ejemplo; use un sistema de configuración seguro
- Responda con rapidez: devuelva una respuesta 200 OK en cuanto haya validado la firma
- Procese de forma asíncrona: después de validar y de devolver la respuesta, procese el webhook en un subproceso en segundo plano o en una cola
- Implemente la idempotencia: use el id del evento para no procesar webhooks duplicados si se entregan más de una vez
- Registre todos los eventos de webhook: conserve constancia de todos los webhooks recibidos para la depuración y las auditorías
Procesar los eventos de webhook
Tratar los distintos tipos de evento
Su receptor de webhooks debe estar diseñado para tratar de forma adecuada los distintos tipos de evento. El ejemplo siguiente muestra cómo se pueden procesar varios eventos de webhook después de validar la firma:
// Example of webhook event processing
private async Task ProcessWebhookEvent(string payload, string eventType)
{
switch (eventType)
{
case "license.created":
await ProcessNewLicense(payload);
break;
case "license.expired":
await ProcessExpiredLicense(payload);
break;
case "order.created":
await ProcessNewOrder(payload);
break;
// Handle other event types
default:
_logger.LogWarning($"Unhandled webhook event type: {eventType}");
break;
}
}
// Example deserialization and processing
private async Task ProcessNewLicense(string payload)
{
try
{
// Deserialize the payload
var licenseEvent = JsonSerializer.Deserialize<LicenseCreatedEvent>(payload);
// Process the license
_logger.LogInformation($"Processing new license: {licenseEvent.LicenseId}");
// Example: Store in your database, notify users, etc.
await _licenseService.SyncLicenseAsync(licenseEvent.Id);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error processing license.created webhook");
}
}Solución de problemas
Problemas habituales
- El webhook no recibe eventos: compruebe el estado del webhook en el panel y verifique que el tipo de evento es uno de aquellos a los que está suscrito
- Errores de autenticación: verifique que su código de validación de firmas es correcto y que usa el mismo secreto que está configurado en el webhook
- Tiempos de espera agotados: asegúrese de que su punto de acceso responde en un tiempo razonable (el sistema espera una respuesta antes de marcar la entrega como correcta)
- URL no válida: compruebe que la URL de su webhook es accesible desde Internet y devuelve códigos de estado HTTP 2xx
- Las cabeceras personalizadas no se aplican: revise el formato de sus cabeceras personalizadas en la configuración del webhook
- Webhook marcado como fallido: compruebe el mensaje de error en los detalles del webhook para ver el código de estado HTTP concreto o la excepción que se produjo
Ver el historial de un webhook
De cada webhook puede ver el historial de entregas completo:
- Haga clic en un webhook de la lista principal para expandir sus detalles
- La sección del historial muestra todos los intentos de entrega, con las marcas de tiempo, los tipos de evento, el estado y los mensajes de error
- Use esta información para diagnosticar problemas de entrega o verificar las entregas correctas