Webhooks
Recibe notificaciones en tiempo real
Configuración de Webhooks
Los webhooks te permiten recibir notificaciones HTTP cuando ocurren eventos importantes en tu aplicación.
Pasos para configurar:
Crear endpoint en tu servidor
Un endpoint que acepte peticiones POST
Registrar URL en el dashboard
Configuración → Webhooks → Añadir webhook
Seleccionar eventos
Elige qué eventos quieres recibir
Probar webhook
Usa el botón "Test" para verificar
const express = require('express');
const crypto = require('crypto');
const app = express();
app.use(express.json());
// Verificar firma del webhook
function verifyWebhookSignature(payload, signature, secret) {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(JSON.stringify(payload))
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
);
}
app.post('/webhooks/KeyNexus', (req, res) => {
const signature = req.headers['x-KeyNexus-signature'];
const webhookSecret = process.env.WEBHOOK_SECRET;
// Verificar firma
if (!verifyWebhookSignature(req.body, signature, webhookSecret)) {
return res.status(401).json({ error: 'Invalid signature' });
}
const { event, data, timestamp } = req.body;
switch (event) {
case 'user.login':
console.log(`Usuario ${data.username} inició sesión`);
break;
case 'license.activated':
console.log(`Licencia ${data.licenseKey} activada`);
break;
case 'license.expired':
console.log(`Licencia ${data.licenseKey} expiró`);
// Enviar email al usuario
break;
default:
console.log(`Evento desconocido: ${event}`);
}
res.json({ received: true });
});
app.listen(3000);Eventos Disponibles
| Evento | Descripción |
|---|---|
| user.login | Un usuario inició sesión exitosamente |
| user.logout | Un usuario cerró sesión |
| user.created | Se creó un nuevo usuario |
| user.banned | Un usuario fue baneado |
| license.created | Se generó una nueva licencia |
| license.activated | Una licencia fue activada por primera vez |
| license.expired | Una licencia expiró |
| license.revoked | Una licencia fue revocada |
| session.created | Se inició una nueva sesión |
| session.terminated | Una sesión fue terminada |
| security.hwid_mismatch | Intento de login con HWID diferente |
| security.ip_blocked | Intento de acceso desde IP bloqueada |
Estructura de Payloads
{
"event": "user.login",
"timestamp": "2024-01-15T10:30:00Z",
"applicationId": "app_xxxxxxxxxxxx",
"data": {
"userId": "user_xxxxxxxxxxxx",
"username": "john_doe",
"email": "[email protected]",
"ip": "192.168.1.100",
"hwid": "abc123...",
"location": {
"country": "US",
"city": "New York",
"timezone": "America/New_York"
},
"sessionId": "sess_xxxxxxxxxxxx",
"licenseKey": "XXXXX-XXXXX-XXXXX-XXXXX",
"subscriptionExpiry": "2024-12-31T23:59:59Z"
}
}{
"event": "license.expired",
"timestamp": "2024-01-15T00:00:00Z",
"applicationId": "app_xxxxxxxxxxxx",
"data": {
"licenseId": "lic_xxxxxxxxxxxx",
"licenseKey": "XXXXX-XXXXX-XXXXX-XXXXX",
"userId": "user_xxxxxxxxxxxx",
"username": "john_doe",
"email": "[email protected]",
"type": "time-based",
"createdAt": "2023-12-15T10:30:00Z",
"expiredAt": "2024-01-15T00:00:00Z",
"totalDaysActive": 31
}
}Base de Datos
Esquema y modelos de datos
Esquema de Base de Datos
KeyNexus utiliza MongoDB como base de datos principal. A continuación el esquema de las colecciones principales:
Applications
interface Application {
_id: ObjectId;
name: string;
description?: string;
version: string;
secretKey: string;
SecretKey: string;
ownerId: ObjectId;
settings: {
hwidLock: boolean;
maxSessions: number;
antiDebug: boolean;
};
status: 'active' | 'paused';
createdAt: Date;
updatedAt: Date;
}AppUsers
interface AppUser {
_id: ObjectId;
applicationId: ObjectId;
username: string;
email?: string;
password?: string;
hwid?: string;
licenseKey?: string;
subscriptionExpiry?: Date;
status: 'active' | 'banned';
banReason?: string;
lastLogin?: Date;
totalLogins: number;
createdAt: Date;
}Licenses
interface License {
_id: ObjectId;
applicationId: ObjectId;
key: string;
type: 'lifetime' | 'time-based' | 'subscription';
duration?: number;
durationUnit?: string;
expiresAt?: Date;
activatedAt?: Date;
userId?: ObjectId;
hwid?: string;
status: 'unused' | 'active' |
'expired' | 'revoked';
note?: string;
createdAt: Date;
}Sessions
interface Session {
_id: ObjectId;
applicationId: ObjectId;
userId: ObjectId;
sessionToken: string;
hwid: string;
ip: string;
location?: {
country: string;
city: string;
};
status: 'active' | 'expired';
lastActivity: Date;
createdAt: Date;
expiresAt: Date;
}Índices y Optimización
// Applications
db.applications.createIndex({ "SecretKey": 1 }, { unique: true });
db.applications.createIndex({ "ownerId": 1 });
// AppUsers
db.appusers.createIndex({ "applicationId": 1, "username": 1 }, { unique: true });
db.appusers.createIndex({ "applicationId": 1, "licenseKey": 1 });
db.appusers.createIndex({ "applicationId": 1, "hwid": 1 });
db.appusers.createIndex({ "subscriptionExpiry": 1 });
// Licenses
db.licenses.createIndex({ "applicationId": 1, "key": 1 }, { unique: true });
db.licenses.createIndex({ "applicationId": 1, "status": 1 });
db.licenses.createIndex({ "expiresAt": 1 });
// Sessions
db.sessions.createIndex({ "sessionToken": 1 }, { unique: true });
db.sessions.createIndex({ "applicationId": 1, "userId": 1 });
db.sessions.createIndex({ "expiresAt": 1 }, { expireAfterSeconds: 0 }); // TTL
// Whitelist
db.whitelists.createIndex({ "applicationId": 1, "type": 1, "value": 1 });CLI & Terminal
Herramienta de línea de comandos
Instalación del CLI
npm install -g @KeyNexus/clibrew install KeyNexus-cli# Configurar API Key
KeyNexus config set secret-key YOUR_SECRET_KEY
# Configurar aplicación por defecto
KeyNexus config set app-id app_xxxxxxxxxxxx
# Ver configuración actual
KeyNexus config listComandos Disponibles
# Generar licencias
KeyNexus licenses generate --type time-based --duration 30 --count 10
# Listar licencias
KeyNexus licenses list --status unused
# Revocar licencia
KeyNexus licenses revoke XXXXX-XXXXX-XXXXX-XXXXX
# Extender licencia
KeyNexus licenses extend XXXXX-XXXXX-XXXXX-XXXXX --days 30
# Exportar licencias a CSV
KeyNexus licenses export --format csv --output licenses.csv# Listar usuarios
KeyNexus users list --limit 50
# Ver detalles de usuario
KeyNexus users get user_xxxxxxxxxxxx
# Banear usuario
KeyNexus users ban user_xxxxxxxxxxxx --reason "Violación de ToS"
# Reset HWID
KeyNexus users reset-hwid user_xxxxxxxxxxxx
# Exportar usuarios
KeyNexus users export --format json --output users.json# Ver sesiones activas en tiempo real
KeyNexus sessions watch
# Estadísticas de la aplicación
KeyNexus stats --period 7d
# Ver logs de auditoría
KeyNexus logs --type auth --limit 100
# Health check
KeyNexus healthEjemplos de Código
Implementaciones completas y patrones comunes
Ejemplo Básico Completo
using System;
using System.Threading.Tasks;
using KeyNexus;
using KeyNexus.Models;
using KeyNexus.Exceptions;
namespace MyProtectedApp
{
class Program
{
private static KeyNexusClient _KeyNexus;
private static UserData _currentUser;
static async Task Main(string[] args)
{
Console.Title = "Mi Aplicación Protegida v1.0";
try
{
// Paso 1: Inicializar KeyNexus
await InitializeKeyNexus();
// Paso 2: Autenticar usuario
await AuthenticateUser();
// Paso 3: Ejecutar aplicación principal
await RunMainApplication();
}
catch (KeyNexusException ex)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine($"\nError de KeyNexus: {ex.Message}");
Console.WriteLine($"Código: {ex.ErrorCode}");
}
catch (Exception ex)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine($"\nError inesperado: {ex.Message}");
}
finally
{
Console.ResetColor();
Console.WriteLine("\nPresiona cualquier tecla para salir...");
Console.ReadKey();
}
}
static async Task InitializeKeyNexus()
{
Console.WriteLine("Inicializando...");
_KeyNexus = new KeyNexusClient(new KeyNexusOptions
{
ApplicationId = Environment.GetEnvironmentVariable("KeyNexus_APP_ID")
?? "app_xxxxxxxxxxxx",
SecretKey = Environment.GetEnvironmentVariable("KeyNexus_SECRET_KEY")
?? "sk_xxxxxxxxxxxxxxxxxxxx",
Version = "1.0.0",
Security = new SecurityOptions
{
AntiDebug = true,
EncryptCommunication = true
}
});
var result = await _KeyNexus.InitializeAsync();
if (!result.Success)
throw new KeyNexusException(result.ErrorCode, result.Message);
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine($"✓ Conectado a {result.Data.Name}");
Console.ResetColor();
}
static async Task AuthenticateUser()
{
Console.WriteLine("\n=== AUTENTICACIÓN ===");
Console.Write("Ingresa tu licencia: ");
var license = Console.ReadLine()?.Trim();
if (string.IsNullOrEmpty(license))
throw new ArgumentException("La licencia no puede estar vacía");
var hwid = HardwareInfo.GetHwid();
Console.WriteLine($"HWID: {hwid.Substring(0, 16)}...");
var result = await _KeyNexus.LoginWithLicenseAsync(new LicenseLoginRequest
{
LicenseKey = license,
Hwid = hwid
});
if (!result.Success)
throw new KeyNexusException(result.ErrorCode, result.Message);
_currentUser = result.Data.User;
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine($"\n✓ ¡Bienvenido, {_currentUser.Username}!");
Console.ResetColor();
Console.WriteLine($" Expira: {_currentUser.SubscriptionExpiry:dd/MM/yyyy}");
Console.WriteLine($" Logins totales: {_currentUser.TotalLogins}");
}
static async Task RunMainApplication()
{
Console.WriteLine("\n=== APLICACIÓN PRINCIPAL ===");
Console.WriteLine("Tu aplicación está funcionando...");
// Mantener sesión activa
var sessionChecker = Task.Run(async () =>
{
while (true)
{
await Task.Delay(TimeSpan.FromMinutes(5));
var check = await _KeyNexus.CheckSessionAsync();
if (!check.Success)
{
Console.WriteLine("\n⚠ Sesión expirada");
Environment.Exit(0);
}
}
});
// Tu lógica de aplicación aquí
while (true)
{
Console.Write("\n> ");
var command = Console.ReadLine()?.ToLower();
switch (command)
{
case "status":
var userData = await _KeyNexus.GetUserDataAsync();
Console.WriteLine($"Días restantes: {userData.Data.DaysRemaining}");
break;
case "sessions":
var sessions = await _KeyNexus.GetUserSessionsAsync();
Console.WriteLine($"Sesiones activas: {sessions.Data.Count}");
break;
case "logout":
await _KeyNexus.LogoutAsync();
Console.WriteLine("Sesión cerrada");
return;
case "exit":
return;
default:
Console.WriteLine("Comandos: status, sessions, logout, exit");
break;
}
}
}
}
}Solución de Problemas
Diagnóstico y resolución de errores comunes
Problemas Comunes
Error: HWID_MISMATCH
Causa: La licencia está vinculada a un hardware diferente
Soluciones:
- Solicitar reset de HWID al administrador
- Verificar que no se hayan cambiado componentes de hardware
- Usar el portal de cliente para resetear HWID (si está habilitado)
Error: LICENSE_EXPIRED
Causa: La suscripción ha expirado
Soluciones:
- Renovar la licencia desde el portal
- Contactar soporte para extensión
- Adquirir una nueva licencia
Error: CONNECTION_FAILED
Causa: No se puede conectar con el servidor
Soluciones:
- Verificar conexión a internet
- Comprobar si el firewall está bloqueando
- Verificar que el servidor esté en línea
- Desactivar VPN si está activa
Error: SESSION_LIMIT
Causa: Demasiadas sesiones activas
Soluciones:
- Cerrar sesión en otros dispositivos
- Esperar a que expiren las sesiones antiguas
- Contactar administrador para aumentar límite
Preguntas Frecuentes (FAQ)
¿Puedo usar la misma licencia en múltiples dispositivos?
Depende de la configuración. Si HWID lock está habilitado, la licencia se vincula al primer dispositivo. Algunos planes permiten múltiples dispositivos.
¿Qué pasa si cambio mi hardware?
Necesitarás un reset de HWID. Puedes solicitarlo desde el portal de cliente o contactar al administrador. Hay un límite de resets por mes.
¿Las licencias son transferibles?
Por defecto no. El administrador puede habilitar transferencias desde el dashboard.
¿Cómo protejo mi API Key?
Nunca expongas la API Key en código cliente. Úsala solo en el servidor. Para clientes, usa el flujo de autenticación con licencia.
¿Qué lenguajes están soportados?
Ofrecemos SDKs oficiales para C#, C++, Python, Rust y Go. También puedes usar la API REST directamente.
¿Hay límite de requests?
Sí, el rate limit por defecto es 60 requests/minuto por IP. Contacta soporte para aumentar límites.
API Playground
Prueba la API en vivo
Credenciales de la Aplicación
Inicializar
Verificar que la aplicación está activa
Ejemplo de petición cURL:
curl -X POST https://keynexus.es/api/client \
-H "Content-Type: application/json" \
-d '{
"action": "init",
"appId": "app_xxxxxxxxxxxx",
"secretKey": "sk_xxxxxxxxxxxxxxxxxxxx"
}'¿No encontraste lo que buscabas? Contacta a nuestro equipo de soporte