Le système de l'API en profondeur
Cette page explique comment l'API fonctionne réellement, de la requête HTTP jusqu'au conteneur Docker qui héberge ton bot. Utile pour intégrer l'API sereinement — et pour comprendre pourquoi elle se comporte comme elle le fait.
Vue d'ensemble
L'API est un service Fastify (Node.js + TypeScript) qui sert de cerveau métier. Elle expose deux surfaces distinctes :
- API interne (BFF) — consommée par le panel, authentifiée par session (cookie Redis, OAuth Discord).
- API publique
/api/v1— consommée par tes intégrations, authentifiée par clé d'API. C'est celle documentée ici.
Les deux surfaces partagent les mêmes services métier et la même base de données : une action via clé d'API produit exactement le même effet que la même action dans le panel.
Le cycle d'une requête
Une requête sur la surface publique traverse toujours les mêmes étapes :
Client
│ Authorization: Bearer ecl_…
▼
[1] Rate-limit (120 req/min/IP, Redis)
▼
[2] authenticateApiKey — hache la clé, la retrouve en base, vérifie scope
▼
[3] Validation Zod du corps / des paramètres
▼
[4] Service métier (server.service, offer.service…)
▼
[5] SDK Pterodactyl → Panel → Wings (Docker)
▼
Réponse JSON[1] Limitation de débit
Un plugin de rate-limit adossé à Redis compte les requêtes par IP sur une fenêtre glissante d'une minute. Au-delà de 120, la requête est rejetée en 429 avant même d'atteindre l'authentification — cela protège la base de données et Pterodactyl des pics.
[2] Authentification par clé
C'est le cœur du système. Le décorateur Fastify authenticateApiKey :
- Lit l'en-tête
Authorizationet exige le schémaBearer. - Vérifie que le jeton commence par le préfixe
ecl_. - Calcule le SHA-256 du jeton reçu.
- Cherche en base une clé dont le
hashedKeycorrespond. - Rejette si la clé est absente, révoquée, ou si la comparaison échoue.
- Peuple
req.useretreq.apiScopes, puis met à jourlastUsedAten tâche de fond.
Sécurité — la clé n'est jamais stockée en clair
hashedKey) et un préfixe lisible (ecl_ab12cd34, pour l'affichage) sont conservés. Même en cas de fuite de la base, les clés ne peuvent pas être reconstituées. La comparaison des hash utilise timingSafeEqual (comparaison à temps constant) pour ne pas laisser fuiter d'information via le temps de réponse (attaque temporelle).Le format d'une clé :
ecl_<48 caractères hexadécimaux>
└┬─┘ └──────────┬──────────────┘
préfixe secret (randomBytes(24))Scope write
Les routes d'écriture passent par authenticateApiKeyWrite : il exécute d'abord l'authentification standard, puis vérifie que write figure dans les scopes de la clé. Sinon, 403 — la clé est en lecture seule.
[3] Validation des entrées (Zod)
Chaque corps de requête est validé par un schéma Zod avant tout traitement. Exemple pour la création d'un serveur :
z.object({
name: z.string().min(3).max(48),
runtime: z.enum(["NODEJS", "PYTHON", "JAVA"]),
ram: z.number().int().min(128).max(8192), // Mo
disk: z.number().int().min(512).max(51200), // Mo
cpu: z.number().int().min(25).max(400), // %
withDatabase: z.boolean().optional(),
})Un corps non conforme est rejeté en 400 avec le détail des champs fautifs — la logique métier n'est jamais atteinte avec des données invalides.
[4] Services métier & quotas
Les routes sont volontairement minces : elles délèguent aux services(server.service, offer.service…). Avant de provisionner, le service vérifie que la demande respecte le quota de ton offre (RAM, nombre de serveurs). En cas de dépassement, une QuotaExceededError est traduite en 403.
Les services vérifient aussi la propriété : tu ne peux lire ou piloter que tes serveurs. Une ressource appartenant à un autre compte renvoie 404 (et non 403), pour ne pas révéler son existence.
[5] Pont vers Pterodactyl
Pour l'hébergement réel, l'API parle à Pterodactyl via un SDK typé, avec deux clés :
- Application (
ptla_…) — créer/administrer les serveurs. - Client (
ptlc_…) — power, fichiers, backups, console.
Provisioning asynchrone
INSTALLING) et confie le provisioning à une file BullMQ (Redis). L'endpoint répond immédiatement en 201 ; tu suis l'avancement via GET /servers/:id.Idempotence & bonnes pratiques
- Les lectures (
GET) sont sûres et peuvent être répétées librement. POST /servers/:id/powerest idempotent en pratique : renvoyerstartà un serveur déjà démarré est sans effet néfaste.- Sur
429, respecteRetry-Afteret applique un backoff. - Traite
INSTALLINGcomme un état transitoire : sonde/servers/:id.
Résumé
L'API publique est une couche mince, sécurisée et validée au-dessus des mêmes services que le panel : clés hachées et comparées à temps constant, scopes explicites, quotas appliqués, provisioning asynchrone, et Pterodactyl comme moteur d'exécution. Passe à la référence des endpoints pour l'implémentation.
