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:

1

Crear endpoint en tu servidor

Un endpoint que acepte peticiones POST

2

Registrar URL en el dashboard

Configuración → Webhooks → Añadir webhook

3

Seleccionar eventos

Elige qué eventos quieres recibir

Probar webhook

Usa el botón "Test" para verificar

Ejemplo de endpoint (Node.js/Express)javascript
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

EventoDescripción
user.loginUn usuario inició sesión exitosamente
user.logoutUn usuario cerró sesión
user.createdSe creó un nuevo usuario
user.bannedUn usuario fue baneado
license.createdSe generó una nueva licencia
license.activatedUna licencia fue activada por primera vez
license.expiredUna licencia expiró
license.revokedUna licencia fue revocada
session.createdSe inició una nueva sesión
session.terminatedUna sesión fue terminada
security.hwid_mismatchIntento de login con HWID diferente
security.ip_blockedIntento de acceso desde IP bloqueada

Estructura de Payloads

Ejemplo de payload: user.loginjson
{
  "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"
  }
}
Ejemplo de payload: license.expiredjson
{
  "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

Índices recomendadosjavascript
// 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 (Node.js)bash
npm install -g @KeyNexus/cli
Homebrew (macOS)bash
brew install KeyNexus-cli
Configurar credencialesbash
# 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 list

Comandos Disponibles

Gestión de licenciasbash
# 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
Gestión de usuariosbash
# 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
Monitoreobash
# 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 health

Ejemplos de Código

Implementaciones completas y patrones comunes

Ejemplo Básico Completo

Este ejemplo muestra una implementación completa con manejo de errores y buenas prácticas.
Aplicación de consola completa (C#)csharp
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

Nota: Usa tus propias credenciales (App ID y Secret Key) del dashboard para probar las APIs.

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