API Reference

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.
Format des réponses : toutes les réponses sont en JSON. Les réponses signées incluent _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.

BASE URL https://votre-domaine.up.railway.app

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 invalides
  • 401 — Bearer token absent ou incorrect (endpoints admin)
  • 403 — clé bannie, expirée, ou HWID mismatch
  • 404 — ressource introuvable
  • 409 — 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
Bon à savoir : les tentatives réussies remettent le compteur à zéro. Un client légitime ne devrait jamais atteindre la limite.