# 🐯 TIGROU GEN - DOCUMENTATION API UNIVERSELLE DE LICENCES (v1.0.0)

Bienvenue sur l'API Universelle de gestion et vérification de licences **Tigrou Gen**.
Cette API RESTful haute performance permet d'intégrer facilement le système d'authentification par clé Tigrou dans **n'importe quel projet externe** :
- Applications C++ (Loaders, Cheats, Outils bureautiques, Jeux)
- Scripts & Bots Python
- Applications C# / .NET (WPF, WinForms, Blazor, ASP.NET)
- Outils Web & APIs (Node.js, Express, PHP, Go, Rust)
- Boutiques externes automatisées (Sellix, Shoppy, WooCommerce, Stripe, Discord Bots)

---

## 🌐 INFORMATIONS GÉNÉRALES & BASE URL

- **URL de Base Production** : `https://tigrouomni.wisp.uno`
- **Format d'échange** : `application/json` (UTF-8)
- **Protocole** : HTTPS (TLS 1.2 / 1.3)

---

## 🔐 MODES D'AUTHENTIFICATION

L'API propose deux niveaux d'accès distincts :

### 1. Vérification Client (Public / Sans clé maître)
Pour vérifier si la clé d'un utilisateur est valide, aucun secret n'est requis. L'exécutable client envoie simplement la licence et son HWID :
```http
POST /api/v1/license/verify
Content-Type: application/json

{
  "key": "TIGROU-AB12CD34EF56GH78",
  "hwid": "4C4C4544-004A-4B10-8053-C7C04F343232"
}
```

### 2. API Maître Développeur (Server-to-Server / Administration)
Pour générer des clés, bannir, réinitialiser des HWID ou lister les licences, fournissez votre **Clé API Développeur** (`tk_live_...`) dans les en-têtes HTTP de l'une des façons suivantes :
```http
X-API-Key: tk_live_xxxxxxxxxxxxxxxxxxxxxxxx
```
ou
```http
Authorization: Bearer tk_live_xxxxxxxxxxxxxxxxxxxxxxxx
```
*(Générez et révoquez vos Clés API à tout moment depuis le Panel Admin dans l'onglet **API Universelle**).*

---

## 📡 RÉFÉRENCE DES ENDPOINTS

### ─── 1. CLIENT & VÉRIFICATION DE LICENCE ───

#### `POST /api/v1/license/verify` (ou `GET /api/v1/license/verify`)
Vérifie la validité d'une licence, son expiration, et effectue le verrouillage matériel (HWID Lock).

**Paramètres de requête (JSON Body ou Query Params) :**
| Champ | Type | Requis | Description |
| :--- | :--- | :--- | :--- |
| `key` | `string` | **Oui** | La clé de licence (ex: `TIGROU-XXXX-XXXX`) |
| `hwid` | `string` | *Optionnel* | L'identifiant matériel unique de la machine. Si la clé n'a pas encore de HWID, elle s'associe automatiquement à celui-ci (1ère activation). Si elle en a déjà un, le HWID doit correspondre. |
| `discordId` | `string` | *Optionnel* | ID Discord du client si vous souhaitez verrouiller sur un compte Discord. |
| `app_id` | `string` | *Optionnel* | Nom ou identifiant de votre logiciel (ex: `MonLogiciel-v2`). |

**Réponse en cas de succès (HTTP 200) :**
```json
{
  "valid": true,
  "status": "ACTIVE",
  "message": "Licence valide et active",
  "key": "TIGROU-AB12CD34EF56GH78",
  "days": 30,
  "isLifetime": false,
  "createdAt": "2026-09-25T10:00:00.000Z",
  "expiresAt": "2026-10-25T10:00:00.000Z",
  "daysLeft": 30,
  "secondsLeft": 2592000,
  "hwid": "4C4C4544-004A-4B10-8053-C7C04F343232",
  "discordId": null,
  "note": "Abonnement VIP"
}
```

**Réponses en cas d'erreur / clé invalide (HTTP 200 avec `valid: false`) :**
- Clé inconnue :
  ```json
  { "valid": false, "status": "NOT_FOUND", "message": "Clé de licence invalide ou introuvable." }
  ```
- Clé expirée :
  ```json
  { "valid": false, "status": "EXPIRED", "message": "Cette licence a expiré le 20/09/2026.", "expiresAt": "2026-09-20T10:00:00.000Z" }
  ```
- Clé bannie :
  ```json
  { "valid": false, "status": "BANNED", "message": "Cette licence a été suspendue/bannie." }
  ```
- HWID différent (tentative de partage sur un autre PC) :
  ```json
  { "valid": false, "status": "HWID_MISMATCH", "message": "Cette clé est verrouillée sur un autre ordinateur." }
  ```

---

#### `GET /api/v1/license/info?key=TIGROU-XXXX`
Consulte les informations d'une clé sans modifier ni lier son HWID (mode lecture seule).

---

### ─── 2. GESTION DES CLÉS (API DÉVELOPPEUR) ───
*(Nécessite le header `X-API-Key: tk_live_...`)*

#### `POST /api/v1/keys/create`
Génère une ou plusieurs nouvelles clés de licence.

**Corps de la requête (JSON) :**
```json
{
  "days": 30,
  "count": 1,
  "note": "Vente Sellix #5821",
  "discordId": "123456789012345678",
  "metadata": { "customer_email": "client@example.com" }
}
```
*Note : Mettez `"days": 9999` pour une licence à vie (Lifetime).*

**Réponse :**
```json
{
  "success": true,
  "count": 1,
  "keys": [
    {
      "key": "TIGROU-FE19AB42398C12A0",
      "days": 30,
      "createdAt": "2026-09-25T12:00:00.000Z",
      "expiresAt": "2026-10-25T12:00:00.000Z",
      "note": "Vente Sellix #5821"
    }
  ]
}
```

---

#### `GET /api/v1/keys`
Liste les clés enregistrées avec filtres et pagination.

**Paramètres Query :**
- `search` (optionnel) : recherche par clé, note, ou Discord ID.
- `status` (optionnel) : `active`, `expired`, ou `banned`.
- `limit` (optionnel, défaut: 50).
- `page` (optionnel, défaut: 1).

---

#### `POST /api/v1/keys/:key/reset-hwid`
Réinitialise le verrouillage matériel d'une clé afin que le client puisse l'utiliser sur un nouveau PC.

**Réponse :**
```json
{
  "success": true,
  "message": "Le HWID de la clé a été réinitialisé avec succès.",
  "key": "TIGROU-AB12CD34EF56GH78"
}
```

---

#### `POST /api/v1/keys/:key/ban`
Suspend ou réactive une clé de licence.

**Corps de la requête (JSON) :**
```json
{
  "banned": true,
  "reason": "Litige bancaire PayPal"
}
```

---

#### `POST /api/v1/keys/:key/extend`
Prolonge la durée d'une licence existante en ajoutant des jours supplémentaires.

**Corps de la requête (JSON) :**
```json
{
  "days": 7
}
```

---

#### `DELETE /api/v1/keys/:key`
Supprime définitivement une clé de licence du système.

---

## 💻 EXEMPLES D'INTÉGRATION PRÊTS À L'EMPLOI

### 1. Exemple C++ (Windows WinINet - Sans dépendance externe)
Ce code fonctionne nativement sous Visual Studio C++ sans nécessiter de bibliothèque externe :

```cpp
#include <windows.h>
#include <wininet.h>
#include <iostream>
#include <string>

#pragma comment(lib, "wininet.lib")

// Récupération automatique du HWID machine sous Windows
std::string GetMachineHWID() {
    HW_PROFILE_INFOA hwInfo;
    if (GetCurrentHwProfileA(&hwInfo)) {
        return std::string(hwInfo.szHwProfileGuid);
    }
    return "UNKNOWN_HWID";
}

// Vérification de licence via l'API Tigrou
bool VerifyTigrouLicense(const std::string& licenseKey) {
    HINTERNET hInternet = InternetOpenA("TigrouClient/1.0", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
    if (!hInternet) return false;

    HINTERNET hConnect = InternetConnectA(hInternet, "tigrouomni.wisp.uno", INTERNET_DEFAULT_HTTPS_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
    if (!hConnect) { InternetCloseHandle(hInternet); return false; }

    HINTERNET hRequest = HttpOpenRequestA(hConnect, "POST", "/api/v1/license/verify", NULL, NULL, NULL, 
                                         INTERNET_FLAG_SECURE | INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_CACHE_WRITE, 0);
    if (!hRequest) { InternetCloseHandle(hConnect); InternetCloseHandle(hInternet); return false; }

    std::string hwid = GetMachineHWID();
    std::string body = "{\"key\":\"" + licenseKey + "\",\"hwid\":\"" + hwid + "\",\"app_id\":\"MonProgrammeCPP\"}";
    std::string headers = "Content-Type: application/json\r\n";

    BOOL sent = HttpSendRequestA(hRequest, headers.c_str(), (DWORD)headers.length(), (LPVOID)body.c_str(), (DWORD)body.length());
    if (!sent) {
        InternetCloseHandle(hRequest);
        InternetCloseHandle(hConnect);
        InternetCloseHandle(hInternet);
        return false;
    }

    char buffer[4096];
    DWORD bytesRead = 0;
    std::string response = "";
    while (InternetReadFile(hRequest, buffer, sizeof(buffer) - 1, &bytesRead) && bytesRead > 0) {
        buffer[bytesRead] = '\0';
        response += buffer;
    }

    InternetCloseHandle(hRequest);
    InternetCloseHandle(hConnect);
    InternetCloseHandle(hInternet);

    // Vérifie simplement si la réponse contient "valid":true
    return (response.find("\"valid\":true") != std::string::npos);
}

int main() {
    std::cout << "Entrez votre cle de licence Tigrou : ";
    std::string key;
    std::cin >> key;

    if (VerifyTigrouLicense(key)) {
        std::cout << "[+] Licence VALIDE ! Bienvenue dans le programme." << std::endl;
        // Votre code protégé ici...
    } else {
        std::cout << "[-] Erreur : Licence invalide, expiree ou HWID incorrect !" << std::endl;
        Sleep(3000);
        return 1;
    }
    return 0;
}
```

---

### 2. Exemple Python (requests)
```python
import requests
import subprocess
import sys

def get_hwid():
    try:
        cmd = 'wmic csproduct get uuid'
        uuid = subprocess.check_output(cmd, shell=True).decode().split('\n')[1].strip()
        return uuid
    except Exception:
        return "UNKNOWN_HWID"

def check_license(key):
    url = "https://tigrouomni.wisp.uno/api/v1/license/verify"
    payload = {
        "key": key.strip(),
        "hwid": get_hwid(),
        "app_id": "MonScriptPython"
    }
    try:
        res = requests.post(url, json=payload, timeout=8)
        data = res.json()
        if data.get("valid"):
            print(f"[+] Succès : {data.get('message')}")
            print(f"[i] Jours restants : {data.get('daysLeft')} jour(s)")
            return True
        else:
            print(f"[-] Erreur : {data.get('message')} (Code: {data.get('status')})")
            return False
    except Exception as e:
        print(f"[-] Erreur de connexion au serveur d'authentification : {e}")
        return False

if __name__ == "__main__":
    user_key = input("Entrez votre clé Tigrou : ")
    if not check_license(user_key):
        sys.exit(1)

    print("[*] Accès autorisé. Démarrage du script...")
```

---

### 3. Exemple C# / .NET
```csharp
using System;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

public class TigrouAuth
{
    private static readonly HttpClient client = new HttpClient();

    public static async Task<bool> ValidateKeyAsync(string licenseKey)
    {
        string hwid = Environment.MachineName + "_" + Environment.UserName;
        var payload = new
        {
            key = licenseKey,
            hwid = hwid,
            app_id = "AppCSharp"
        };

        var content = new StringContent(JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json");
        var response = await client.PostAsync("https://tigrouomni.wisp.uno/api/v1/license/verify", content);
        
        string json = await response.Content.ReadAsStringAsync();
        using var doc = JsonDocument.Parse(json);
        
        if (doc.RootElement.TryGetProperty("valid", out var validElem) && validElem.GetBoolean())
        {
            return true;
        }
        return false;
    }
}
```

---

### 4. Exemple cURL (Terminal / Bash)
```bash
# Vérifier une clé :
curl -X POST https://tigrouomni.wisp.uno/api/v1/license/verify \
     -H "Content-Type: application/json" \
     -d '{"key":"TIGROU-VOTRE-CLE", "hwid":"TEST-HWID"}'

# Créer une clé (Développeur / Webhook boutique) :
curl -X POST https://tigrouomni.wisp.uno/api/v1/keys/create \
     -H "Content-Type: application/json" \
     -H "X-API-Key: tk_live_VOTRE_CLE_API" \
     -d '{"days":30, "note":"Client Webhook"}'
```

---

## 🛡️ TABLEAU DES STATUS

| Status Code | Description | Action recommandée |
| :--- | :--- | :--- |
| `ACTIVE` | Clé valide et en cours d'abonnement | Autoriser l'accès |
| `NOT_FOUND` | La clé n'existe pas dans la base | Inviter l'utilisateur à vérifier sa saisie |
| `EXPIRED` | La durée d'abonnement est écoulée | Proposer de renouveler la clé |
| `BANNED` | La clé a été bannie par l'administrateur | Bloquer l'accès |
| `HWID_MISMATCH` | Clé utilisée sur une machine non autorisée | Demander un reset de HWID à l'admin |
| `DISCORD_MISMATCH` | Clé liée à un autre compte Discord | Connecter le bon compte Discord |

---
*Support & Administration : Contactez l'administrateur via Discord ou sur le Panel d'administration.*
