| Méthode |
Route |
Description |
Auth |
| POST |
/api/register |
Créer un compte opérateur |
Public |
| POST |
/api/login |
Obtenir un JWT |
Public |
| GET |
/api/api_keys |
Lister vos API keys |
Auth requise |
| POST |
/api/api_keys |
Créer/restricter une API key |
Auth requise |
| PUT |
/api/api_keys/{id} |
Mettre à jour la portée |
Auth requise |
| DELETE |
/api/api_keys/{id} |
Révoquer une API key |
Auth requise |
| GET |
/api/projects/{id}/api_keys |
Filtrer les clés par projet |
Auth requise |
| GET |
/api/projects |
Lister vos projets |
Auth requise |
| POST |
/api/projects |
Créer un projet |
Auth requise |
| POST |
/api/projects/{id}/add_manager |
Déléguer la gestion |
Auth requise |
| GET |
/api/projects/{id}/licenses |
Suivre vos licences |
Auth requise |
| GET |
/api/projects/{id}/licenses/by_key |
Retrouver une licence via sa clé |
Auth requise |
| POST |
/api/projects/{id}/licenses |
Générer une licence |
Auth requise |
| PUT |
/api/licenses/{license_id} |
Mettre à jour une licence |
Auth requise |
| DELETE |
/api/licenses/{license_id} |
Supprimer définitivement |
Auth requise |
| POST |
/api/validate_license |
Validation côté client |
Public |
| POST |
/api/client_metadata |
Client met à jour ses métadonnées |
Public |
| GET |
/api/licenses/{license_id}/metadata |
Lire les métadonnées |
Auth requise |
| PUT |
/api/licenses/{license_id}/metadata |
Mettre à jour les métadonnées |
Auth requise |
| PATCH |
/api/projects/{id}/crypto |
Activer/désactiver la signature crypto |
Auth requise |
| GET |
/api/projects/{id}/public_key |
Récupérer la clé publique Ed25519 |
Public |
| POST |
/api/projects/{id}/rotate_signing_key |
Rotation de la paire de clés |
Auth requise |
| Webhooks |
| GET |
/api/projects/{id}/webhooks |
Lister les webhooks |
Auth requise |
| POST |
/api/projects/{id}/webhooks |
Créer un webhook |
Auth requise |
| PUT |
/api/webhooks/{id} |
Modifier un webhook |
Auth requise |
| DELETE |
/api/webhooks/{id} |
Supprimer un webhook |
Auth requise |
| POST |
/api/webhooks/{id}/test |
Envoyer un ping de test |
Auth requise |
| GET |
/api/webhooks/{id}/deliveries |
Historique de livraison |
Auth requise |
| Audit |
| GET |
/api/projects/{id}/audit |
Consulter le journal d'audit |
Auth requise |
| GET |
/api/projects/{id}/audit/export |
Exporter CSV ou JSON |
Auth requise |
| Quotas |
| GET |
/api/licenses/{id}/usage |
Résumé d'utilisation (activations, devices) |
Auth requise |
| Activation offline |
| POST |
/api/licenses/{id}/offline_tokens |
Émettre un token offline |
Auth requise |
| GET |
/api/licenses/{id}/offline_tokens |
Lister les tokens offline |
Auth requise |
| POST |
/api/offline_tokens/{id}/revoke |
Révoquer un token offline |
Auth requise |
| POST |
/api/offline_tokens/verify |
Vérifier un token offline |
Public |
Exemple de requête
POST /api/register
Content-Type: application/json
{
"username": "automation_bot",
"email": "[email protected]",
"password": "Strong!Passw0rd"
}
Exemple de réponse
{
"id": 14,
"username": "automation_bot",
"message": "Compte créé. Connectez-vous pour obtenir un token."
}
Exemple de requête
POST /api/login
Content-Type: application/json
{
"username": "admin",
"password": "password"
}
Exemple de réponse
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 86400
}
Utilisez l'en-tête Authorization: Bearer <token> pour toutes les routes protégées.
Alternative sans captcha: envoyez {"username": "bot", "api_key": "sk_live_..."}. La clé doit avoir accès au(x) projet(s) visé(s).
Exemple de requête
GET /api/projects
Authorization: Bearer <token>
Exemple de réponse
[
{
"id": 1,
"name": "CommunityCore",
"managers": ["admin"],
"licenses_issued": 128
}
]
Exemple de requête
POST /api/projects
Authorization: Bearer <token>
Content-Type: application/json
{
"name": "CommunityCore",
"description": "Tooling pour la communauté"
}
Exemple de réponse
{
"id": 1,
"name": "CommunityCore",
"slug": "communitycore",
"message": "Projet créé"
}
Exemple de requête
POST /api/projects/1/add_manager
Authorization: Bearer <token>
Content-Type: application/json
{
"username": "support_team"
}
Exemple de réponse
{
"project_id": 1,
"delegated_to": "support_team",
"message": "Manager ajouté"
}
Exemple de requête
GET /api/projects/1/licenses
Authorization: Bearer <token>
Exemple de réponse
[
{
"id": 45,
"key": "CL-1A2B-3C4D-5E6F",
"is_active": true,
"expires_at": "2025-12-31T23:59:59",
"metadata": {
"plan": "enterprise",
"seats": 10
}
}
]
Exemple de requête
GET /api/projects/1/licenses/by_key?key=CL-1A2B-3C4D-5E6F
Authorization: Bearer <token>
Exemple de réponse
{
"id": 45,
"key": "CL-1A2B-3C4D-5E6F",
"project_id": 1,
"is_active": true,
"metadata": {
"plan": "enterprise"
}
}
Le paramètre key est insensible à la casse et doit appartenir au projet ciblé.
Exemple de requête
POST /api/projects/1/licenses
Authorization: Bearer <token>
Content-Type: application/json
{
"days_valid": 30,
"metadata": {
"plan": "enterprise",
"seats": 10,
"discord_id": "1234567890"
}
}
Exemple de réponse
{
"license_id": 45,
"key": "CL-1A2B-3C4D-5E6F",
"expires_at": "2024-12-23T15:02:11",
"metadata": {
"plan": "enterprise",
"seats": 10,
"discord_id": "1234567890"
}
}
Exemple de requête
PUT /api/licenses/45
Authorization: Bearer <token>
Content-Type: application/json
{
"is_active": false,
"expires_at": "2026-01-01T00:00:00",
"reset_hwid": true,
"metadata": {
"plan": "revoked",
"notes": "Chargeback"
}
}
Exemple de réponse
{
"id": 45,
"is_active": false,
"expires_at": "2026-01-01T00:00:00",
"metadata": {
"plan": "revoked",
"notes": "Chargeback"
}
}
Exemple de requête
DELETE /api/licenses/45
Authorization: Bearer <token>
Exemple de réponse
{
"id": 45,
"message": "Licence supprimée"
}
Exemple de requête
POST /api/validate_license
Content-Type: application/json
{
"project_id": 1,
"key": "CL-1A2B-3C4D-5E6F",
"hwid": "unique-hardware-id"
}
Exemple de réponse
{
"valid": true,
"expires_at": "2025-12-31T23:59:59",
"metadata": {
"plan": "enterprise",
"seats": 10,
"hwid": "unique-hardware-id"
},
"nonce": "abc123",
"timestamp": 1711353600,
"signature": "a1b2c3...hex..."
}
Le premier appel lie automatiquement la licence au HWID fourni si aucun verrou n'existe encore. Les champs nonce, timestamp et signature ne sont présents que si la signature cryptographique est activée sur le projet (voir Section 07). Vous pouvez aussi envoyer un hwid_encrypted (SealedBox base64) au lieu de hwid en clair lorsque le crypto est activé.
Générez une clé par SDK ou automation. Chaque clé peut être limitée à un sous-ensemble de projets et révoquée instantanément sans toucher aux autres identifiants.
Exemple de réponse
[
{
"id": 7,
"public_id": "key_5f82...",
"label": "Deploy bot",
"allow_all_projects": false,
"project_ids": [1, 4],
"revoked_at": null
}
]
Utilisez cette route côté dashboard pour afficher vos clés et indiquer si elles couvrent le projet sélectionné.
Exemple de requête
POST /api/api_keys
Authorization: Bearer <token>
Content-Type: application/json
{
"label": "CI Runner",
"project_ids": [2],
"allow_all_projects": false
}
Exemple de réponse
{
"id": 12,
"public_id": "key_32af...",
"secret": "sk_live_XYZ...",
"project_ids": [2],
"allow_all_projects": false
}
Le champ secret n'est renvoyé qu'une seule fois. Stockez-le avant de quitter la page.
Payload
{
"project_ids": [1, 4, 7]
}
{
"allow_all_projects": true
}
Envoyez DELETE /api/api_keys/{id} pour révoquer définitivement une clé. Le dashboard exploite également GET /api/projects/{id}/api_keys pour ne montrer que les clés appartenant au projet courant.
Seules les clés marquées Client editable peuvent être modifiées côté client. Les autres champs restent accessibles uniquement via les routes protégées.
Chaque projet peut activer la signature cryptographique Ed25519. Lorsqu'elle est activée, les réponses de /api/validate_license incluent un champ signature que vos SDK peuvent vérifier avec la clé publique du projet. Les HWIDs peuvent aussi être chiffrés côté client via Curve25519 SealedBox.
Note : La signature cryptographique est désactivée par défaut sur les projets existants. Les nouveaux projets l'ont activée automatiquement. Activez-la manuellement depuis le panneau Signing Key du projet ou via l'endpoint ci-dessous.
Exemple de requête
PATCH /api/projects/1/crypto
Authorization: Bearer <token>
Content-Type: application/json
{
"enabled": true
}
Exemple de réponse
{
"msg": "Cryptographic signing enabled",
"crypto_enabled": true,
"signing_public_key": "a1b2c3d4...hex..."
}
Seul le propriétaire du projet peut modifier ce paramètre. Si c'est la première activation, une paire de clés Ed25519 est générée automatiquement.
Exemple de requête
GET /api/projects/1/public_key
Exemple de réponse
{
"project_id": 1,
"public_key": "a1b2c3d4...hex..."
}
Retourne 404 si la signature cryptographique n'est pas activée sur le projet.
Exemple de requête
POST /api/projects/1/rotate_signing_key
Authorization: Bearer <token>
Content-Type: application/json
{
"confirm": "ROTATE"
}
Exemple de réponse
{
"msg": "Signing key rotated successfully",
"signing_public_key": "e5f6a7b8...hex..."
}
Nécessite {"confirm": "ROTATE"} dans le body. Retourne 400 si le crypto n'est pas activé. Seul le propriétaire du projet peut effectuer cette action.
Recevez des callbacks HTTP lorsqu'un événement de licence se produit. Les payloads sont signés HMAC-SHA256 lorsque vous fournissez un secret. Vérifiez l'en-tête X-Authlix-Signature côté serveur.
Exemple de réponse
[
{
"id": 3,
"url": "https://my-app.io/hooks",
"events": ["license.created", "license.revoked"],
"is_active": true,
"created_at": "2026-03-01T12:00:00"
}
]
Exemple de requête
POST /api/projects/1/webhooks
Authorization: Bearer <token>
Content-Type: application/json
{
"url": "https://my-app.io/hooks",
"events": ["license.created", "license.revoked"],
"secret": "whsec_my_signing_secret"
}
Exemple de réponse
{
"id": 3,
"url": "https://my-app.io/hooks",
"events": ["license.created", "license.revoked"],
"is_active": true
}
Événements disponibles : license.created, license.activated, license.expired, license.revoked, quota.exceeded.
Payload
{
"url": "https://new-url.io/hooks",
"events": ["license.created"],
"is_active": false
}
Tous les champs sont optionnels. Envoyez uniquement ceux à modifier. DELETE /api/webhooks/{id} pour supprimer.
Exemple de réponse
{
"msg": "Test delivered",
"status_code": 200
}
Exemple de réponse
[
{
"id": 12,
"event_type": "license.created",
"response_status": 200,
"delivered_at": "2026-03-15T14:30:00",
"success": true
}
]
Chaque action significative est enregistrée dans un journal append-only : création/modification/suppression de licences, gestion des clés API, modifications de webhooks. Le journal inclut l'acteur, l'horodatage, l'adresse IP et les détails de l'opération.
Paramètres query
GET /api/projects/1/audit?page=1&per_page=50
Authorization: Bearer <token>
Exemple de réponse
{
"items": [
{
"id": 42,
"action": "license.created",
"actor": "admin",
"ip_address": "192.168.1.1",
"details": "License CL-1A2B created",
"timestamp": "2026-03-15T14:30:00"
}
],
"total": 128,
"page": 1,
"pages": 3,
"per_page": 50
}
Exemple de requête
GET /api/projects/1/audit/export?format=csv
Authorization: Bearer <token>
Formats supportés : csv (par défaut) et json. La réponse est streamée pour les exports volumineux.
Les projets peuvent définir des politiques de quota : nombre maximum d'activations, nombre maximum de devices, et période de grâce. L'évaluation des quotas est automatique lors de la validation (/api/validate_license).
Note : Lorsque le quota est dépassé, la validation retourne 429 Too Many Requests. Le champ quota_info est inclus dans toute réponse de validation réussie.
Exemple de requête
GET /api/licenses/45/usage
Authorization: Bearer <token>
Exemple de réponse
{
"license_id": 45,
"activation_count": 3,
"max_activations": 5,
"device_count": 2,
"max_devices": 3,
"quota_status": "ok",
"remaining_activations": 2,
"remaining_devices": 1,
"grace_until": null
}
Émettez des tokens signés Ed25519 pour les environnements sans accès Internet. Le client peut vérifier le token localement avec la clé publique du projet — aucun appel réseau nécessaire.
Workflow : L'opérateur émet un token → le transfère au client (USB, email, QR) → le client vérifie localement → l'opérateur peut révoquer à tout moment côté serveur.
Exemple de requête
POST /api/licenses/45/offline_tokens
Authorization: Bearer <token>
Content-Type: application/json
{
"machine_hash": "sha256-of-machine-id",
"ttl_days": 90
}
Exemple de réponse
{
"id": 7,
"token": "eyJ0eXAiOiJKV1QiLCJ...",
"expires_at": "2026-06-15T14:30:00",
"machine_hash": "sha256-of-machine-id"
}
La signature cryptographique doit être activée sur le projet. Le ttl_days est optionnel (défaut : 30 jours).
Exemple de requête
POST /api/offline_tokens/verify
Content-Type: application/json
{
"token": "eyJ0eXAiOiJKV1QiLCJ..."
}
Exemple de réponse
{
"valid": true,
"license_id": 45,
"machine_hash": "sha256-of-machine-id",
"expires_at": "2026-06-15T14:30:00"
}
Le SDK propose aussi LicenseClient.verify_offline_token_locally() pour une vérification 100% locale avec la clé publique Ed25519.
Exemple de réponse
{
"msg": "Token revoked"
}
Utilisez GET /api/licenses/{id}/offline_tokens pour lister tous les tokens d'une licence et identifier ceux à révoquer.
Les clés API peuvent être restreintes à un sous-ensemble d'opérations via le système de scopes. Les clés existantes (pré-scopes) conservent un accès complet par rétrocompatibilité.
| Scope |
Description |
licenses:read | Lire les licences et métadonnées |
licenses:write | Créer, modifier, supprimer des licences |
projects:read | Lire les paramètres projet |
projects:write | Modifier les paramètres projet |
api_keys:manage | Créer et révoquer des clés API |
webhooks:manage | Gérer les webhooks |
audit:read | Consulter le journal d'audit |
offline:manage | Émettre et révoquer des tokens offline |
quota:read | Lire les données d'usage et quotas |
Créer une clé avec scopes
POST /api/api_keys
Authorization: Bearer <token>
Content-Type: application/json
{
"label": "Read Only Bot",
"project_ids": [1],
"scopes": ["licenses:read", "audit:read"]
}
Si scopes est omis, la clé a accès à toutes les opérations (rétrocompatibilité). L'endpoint retourne 403 si une clé tente une action hors de ses scopes.