Saku Method API
Documentation pour intégrer le système de licence dans tes applications C++, C#, Python, Node.js, Rust ou n'importe quel langage capable de faire une requête HTTP.
Introduction
L'API Saku expose trois surfaces distinctes :
- Client — appelée depuis ton application déployée (aimbot, unlock, spoofer). Activation, heartbeat, validation HWID.
- Admin — appelée depuis le panel ou tes scripts backend. Nécessite un
Bearer token. - Reseller — appelée depuis le panel revendeur. Session par token opaque après login username/password.
_sig (HMAC-SHA256) et _ts (timestamp) pour éviter les attaques de rejeu et le tampering. Voir la section Vérifier la signature.
Base URL
Toutes les requêtes sont HTTPS en production. En local (dev) : http://localhost:5000.
Endpoints Client
Deux endpoints pour intégrer le lock HWID dans ton binaire. Aucune authentification préalable — la clé fait office de credential.
POST /api/v1/{app_id}/activate
Active une clé sur une machine. À appeler au premier lancement de ton app, puis à chaque démarrage. Bind la clé au HWID si elle est vierge, ou valide qu'elle est déjà bindée à ce HWID.
POST /api/v1/default/activate Content-Type: application/json { "key": "SAKU-XXXX-XXXX-XXXX-XXXX", "hwid": "unique-device-id", "version": "1.0", // optionnel "nonce": "a1b2c3" // optionnel · anti-rejeu }
POST /api/v1/{app_id}/heartbeat
Ping périodique pour maintenir la session active. Appelle toutes les 60-120 secondes. Si la clé est bannie ou expirée, la réponse est un refus et tu dois fermer l'app.
POST /api/v1/default/heartbeat Content-Type: application/json { "session_id": "...", "hwid": "unique-device-id" } // Réponse { "success": true, "expires_at": 1792606647, "_ts": "1790015420", "_sig": "..." }
Vérifier la signature
Chaque réponse signée contient _sig et _ts. _sig = HMAC-SHA256(app_secret, _ts + JSON), où JSON est la réponse SANS _sig ni _ts, clés triées et séparateurs compacts.
Pourquoi ? Sans ça, un attaquant proxy peut modifier une réponse "banned: true" en "banned: false". Avec la sig, toute modification casse le HMAC et ton client refuse la réponse.
import hashlib, hmac, json def verify(response: dict, secret: str) -> bool: data = dict(response) sig, ts = data.pop("_sig", ""), data.pop("_ts", "0") body = json.dumps(data, separators=(",", ":"), sort_keys=True) expected = hmac.new(secret.encode(), (ts + body).encode(), hashlib.sha256).hexdigest() return hmac.compare_digest(sig, expected)
Endpoints Admin
Tous les endpoints admin nécessitent le header Authorization: Bearer {ADMIN_TOKEN}. Le token est défini via la variable d'environnement SAKU_ADMIN_TOKEN.
GET /api/status
Public, sans auth. Renvoie version + uptime + nombre total de clés. Utile pour un healthcheck.
POST /api/admin/generate
Génère un lot de clés dans une app.
{
"count": 10,
"days": 30,
"plan": "standard", // standard | premium | lifetime
"app_id": "default",
"note": "batch janvier"
}
GET /api/admin/keys?app_id=X
Liste toutes les clés d'une app (ou toutes si app_id omis).
POST /api/admin/ban · /unban · /reset-hwid · /delete
Actions sur une clé. Body : { "key": "SAKU-..." }.
POST /api/admin/extend
Prolonge une clé de N jours. Body : { "key": "SAKU-...", "days": 30 }.
GET /api/admin/apps · POST même URL pour créer
Liste ou crée des applications. POST body : { "name": "Mon App" }.
GET /api/admin/logs?app_id=X&limit=200
Les N derniers événements du journal.
GET /api/admin/stats
Stats agrégées : total, actives, expirées, bannies, bindées, nombre d'apps et de revendeurs.
Endpoints Reseller
Un revendeur se connecte avec un couple username / password, reçoit un token opaque à passer dans chaque requête suivante.
POST /api/reseller/login
{ "username": "toto", "password": "..." }
// Réponse
{
"success": true,
"token": "48-char-hex-session-token",
"quota": 100,
"used": 12,
"app_id": "valorant-internal",
"plan": "standard"
}
POST /api/reseller/generate
Génère des clés dans les limites du quota du revendeur.
{ "token": "...", "count": 3, "days": 30 }
POST /api/reseller/me
Renvoie le profil du revendeur + toutes les clés qu'il a générées.
{ "token": "..." }
Codes d'erreur
Structure standard : { "success": false, "error": "..." } ou { "success": false, "message": "..." }.
400— paramètres manquants ou invalides401— Bearer token absent ou incorrect (endpoints admin)403— clé bannie, expirée, ou HWID mismatch404— ressource introuvable409— conflit (app déjà existante par exemple)429— rate limit dépassé
Rate limits
Pour protéger le backend contre le brute-force :
- Activate : 10 tentatives échouées / 5 min par IP
- Login (admin & reseller) : 5 tentatives échouées / 15 min par IP
- Heartbeat : pas de limit stricte, mais espace tes appels au minimum 60s