Pour commencer
Introduction
L'API Panel KVM permet de piloter par programmation les VPS KVM de votre compte LWS : inventaire, supervision, alimentation, réinstallation, snapshots, sauvegardes, pare-feu, réseau et clés SSH. Elle reprend ce que le panel client KVM sait faire, pour vos scripts, votre intégration continue ou votre supervision.
Démarrage rapide
1. Créez votre clé d'API. Dans le panel KVM, ouvrez la page API / MCP, réservée au compte principal. Déclarez l'adresse IP depuis laquelle partiront vos appels, activez l'accès, générez la clé, puis choisissez les VPS qu'elle pourra piloter : tous, ou une sélection. Une clé qui ne couvre encore aucun VPS fonctionne, mais sa liste de VPS est vide. La clé ne s'affiche en entier qu'une seule fois : copiez-la aussitôt.
2. Enregistrez-la dans une variable d'environnement, comme le font tous les exemples de cette documentation :
export LWS_API_KEY="lws_live_sk_7Yc2Kp9RtNwQ4mZ8Bx3Vf1Hd6Ls0AjE2"
3. Vérifiez qu'elle fonctionne :
curl https://panelkvm.lwspanel.com/api/v1/me \
-H "Authorization: Bearer $LWS_API_KEY"
La réponse indique le compte, le niveau de permission de la clé et le nombre de VPS qu'elle couvre.
4. Listez vos VPS :
curl https://panelkvm.lwspanel.com/api/v1/servers \
-H "Authorization: Bearer $LWS_API_KEY"
Chaque VPS y est désigné par son vmid, que vous réutiliserez dans tous les autres appels.
5. Lancez une action et suivez-la. Redémarrez un VPS :
curl -X POST https://panelkvm.lwspanel.com/api/v1/servers/116807/power \
-H "Authorization: Bearer $LWS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"action": "reboot"}'
La réponse contient une tâche ("id": "tsk_000002e1"). Interrogez-la jusqu'à ce que son état soit succeeded :
curl https://panelkvm.lwspanel.com/api/v1/tasks/tsk_000002e1 \
-H "Authorization: Bearer $LWS_API_KEY"
Authentification
Chaque requête porte la clé dans l'en-tête Authorization, selon le schéma Bearer. Ne la transmettez jamais dans une URL : les journaux d'accès conservent les adresses.
La clé se règle depuis la page API / MCP du panel :
- Adresses autorisées (obligatoire) : IPv4, IPv6 ou plages CIDR. L'accès ne peut pas être activé sans au moins une adresse. Un appel venant d'une autre adresse est refusé (
403 ip_not_allowed). - Activation : un interrupteur coupe l'accès sans supprimer la clé (
401 access_disabled). - Régénération : une nouvelle clé invalide l'ancienne immédiatement, et le titulaire du compte en est averti par courriel.
Permissions et portée
Chaque clé reçoit un niveau de permission :
| Niveau | Valeur | Ce qu'il autorise |
|---|---|---|
| Lecture seule | read |
Toutes les consultations : inventaire, état, métriques, listes, tâches, journal d'activité. |
| Exploitation | exploitation |
Lecture seule, plus : alimentation, création de snapshot et de sauvegarde, images ISO, reverse DNS, clés SSH, création et modification de jeux de règles, application d'un jeu, activation du pare-feu, demande de déblocage du port 25. |
| Complet | full |
Exploitation, plus les opérations irréversibles ou qui exposent le serveur : réinstallation, mode secours, mot de passe root, restauration et suppression de snapshot, restauration de sauvegarde, désactivation du pare-feu, retrait et suppression de jeux de règles. |
Le niveau requis figure en tête de chaque opération. Un appel au-delà du niveau accordé est refusé (403 insufficient_scope), et la réponse précise le niveau exigé dans required_level.
Le niveau se choisit sur la page API / MCP du panel. Le passage au niveau Complet doit être confirmé par un code envoyé par courriel au titulaire du compte ; revenir à un niveau inférieur n'en demande pas.
La portée de la clé couvre soit tous les VPS du compte, y compris ceux achetés plus tard, soit une sélection de VPS. Un VPS hors portée répond exactement comme un VPS inexistant (404 vm_not_found).
Requêtes et réponses
- Les échanges se font en JSON, encodé en UTF-8. Les corps de requête s'envoient avec
Content-Type: application/json. - Une ressource est renvoyée sous
data. - Une liste est renvoyée sous
data, accompagnée d'un blocmeta. Les listes longues (VPS, tâches, journal d'activité) sont paginées parpage(défaut1) etper_page(défaut25, au plus100) ; les listes courtes sont renvoyées en entier. - Les dates suivent le format ISO 8601 avec décalage horaire :
2027-03-14T00:00:00+01:00. - Les volumes sont exprimés en octets, à l'exception de
min_memory_gbdans le catalogue des systèmes. - Les identifiants sont des chaînes,
vmidcompris :"116807". Seulaccount_id, dansGET /me, est un nombre. - Chaque réponse porte un en-tête
X-Request-Id. Communiquez-le au support LWS pour tout signalement : il permet de retrouver l'appel exact.
{
"data": [
{
"id": "tsk_000002e1",
"status": "succeeded",
"action": "server.reboot",
"vmid": "116807",
"description": "Demande de reboot du serveur VPS-116807",
"created_at": "2026-08-20T14:31:02+02:00",
"finished_at": "2026-08-20T14:31:40+02:00"
}
],
"meta": { "page": 1, "per_page": 25, "total": 1, "total_pages": 1 }
}
Opérations asynchrones
Les opérations marquées [Differed] (démarrage, réinstallation, snapshot, sauvegarde, pare-feu…) ne s'exécutent pas pendant la requête : elles sont mises en file et répondent 202 Accepted avec la tâche créée.
{
"data": {
"tasks": [
{
"id": "tsk_000002e1",
"status": "pending",
"action": "server.reboot",
"vmid": "116807",
"description": "Demande de reboot du serveur VPS-116807",
"created_at": "2026-08-20T14:31:02+02:00",
"finished_at": null
}
]
}
}
Suivez ensuite la tâche avec Consulter une tâche, toutes les quelques secondes, jusqu'à ce que status vaille succeeded ou failed. Interroger plus souvent n'accélère rien et consomme votre quota.
Une seule opération d'un même type peut s'exécuter à la fois sur un VPS : une seconde demande est refusée (409 task_already_running) et la réponse désigne la tâche en cours dans task_id.
Un VPS verrouillé par l'hyperviseur refuse lui aussi les écritures (409 server_locked). Le champ reason indique quoi faire : operation_in_progress, une opération est en cours, réessayez après le délai de l'en-tête Retry-After ; suspended, le VPS hiberne, démarrez-le d'abord ; support_notified, le verrou est anormal, l'équipe LWS est prévenue et intervient, inutile de réessayer en boucle.
Pendant une intervention annoncée par LWS sur le serveur hôte d'un VPS (mise à jour, redémarrage…), si ce serveur ne répond plus, les écritures sur ce VPS et les lectures qui interrogent l'hyperviseur sont refusées (503 server_maintenance). Le champ maintenance de la réponse en précise la nature et la fin prévue, et l'en-tête Retry-After le délai conseillé avant de réessayer. L'inventaire et la fiche du VPS continuent de répondre, avec status: maintenance.
Les autres écritures (images ISO, reverse DNS, mot de passe root, clés SSH, jeux de règles) sont immédiates et renvoient directement leur résultat.
Erreurs
Les erreurs sont renvoyées au format application/problem+json :
{
"type": "https://docs.lws.fr/kvm/errors/vm-not-found",
"title": "VPS introuvable",
"status": 404,
"code": "vm_not_found",
"detail": "Aucun VPS 999999 sur ce compte.",
"request_id": "3f9a1c07b2e45d18"
}
Basez votre traitement sur code, qui est stable. detail s'adresse à un humain et peut évoluer. Selon l'erreur, la réponse comporte aussi errors (détail par paramètre), required_level, task_id, lock et reason, ou retry_after.
| HTTP | Code | Cause |
|---|---|---|
| 400 | bad_request |
Corps illisible (JSON mal formé). |
| 400 | validation_failed |
Paramètre invalide ; errors détaille chaque champ fautif. |
| 401 | invalid_token |
En-tête Authorization absent ou malformé, clé inconnue ou régénérée depuis. |
| 401 | access_disabled |
Accès API coupé pour ce compte (interrupteur de la page « API / MCP »), ou service API temporairement indisponible. |
| 403 | ip_not_allowed |
Adresse source absente des adresses autorisées. |
| 403 | insufficient_scope |
Niveau de la clé insuffisant ; required_level donne le niveau exigé. |
| 404 | vm_not_found |
VPS inexistant ou hors de la portée de la clé (les deux sont volontairement indiscernables). |
| 404 | snapshot_not_found, backup_not_found, set_not_found, ssh_key_not_found, task_not_found |
Ressource inconnue sur ce VPS ou ce compte. |
| 404 | not_found |
Route inexistante. |
| 405 | method_not_allowed |
Verbe non prévu sur un chemin existant ; l'en-tête Allow liste les verbes acceptés. |
| 409 | task_already_running |
Une opération du même type est déjà en cours sur ce VPS ; task_id la désigne. |
| 409 | server_locked |
VPS verrouillé par l'hyperviseur ; reason indique s'il faut réessayer, le démarrer ou attendre l'équipe LWS. |
| 409 | service_suspended |
VPS désactivé ou expiré : les lectures restent possibles, pas les écritures. |
| 409 | invalid_state |
Action incompatible avec l'état courant. |
| 409 | quota_exceeded |
Limite fonctionnelle atteinte (3 snapshots, 10 jeux de règles par VPS). |
| 422 | unsupported_operation |
Fonction indisponible sur ce VPS (agent QEMU absent, notamment). |
| 429 | rate_limited |
Quota d'appels dépassé : respectez Retry-After. |
| 500 | internal_error |
Erreur inattendue : transmettez le request_id au support. |
| 502 | hypervisor_unreachable |
Hyperviseur momentanément injoignable : réessayez. |
| 502 | upstream_unavailable |
Dépendance interne indisponible (inventaire, sauvegardes, catalogue…) : réessayez. |
| 503 | server_maintenance |
Serveur hôte en intervention annoncée par LWS et injoignable : écritures et lectures sur l'hyperviseur refusées jusqu'à la fin prévue (maintenance) ; respectez Retry-After. |
Quotas
Les appels sont limités par compte, sur une fenêtre glissante d'une heure, selon trois familles indépendantes :
| Famille | Limite | Opérations concernées |
|---|---|---|
read |
3 600 appels par heure | Toutes les consultations (GET) |
mutation |
300 appels par heure | Les écritures courantes |
heavy |
6 appels par heure par VPS, 60 par compte | Snapshots (créer, restaurer, supprimer), sauvegardes (lancer, restaurer), réinstallation |
Une opération lourde est soumise à deux plafonds : celui du VPS visé et celui du compte. Le plafond par VPS évite qu'un même serveur soit sollicité en boucle, sans pénaliser les comptes qui ont beaucoup de VPS ; le message de refus précise lequel des deux plafonds est atteint.
Pour ménager les hyperviseurs, l'état et les métriques instantanées d'un VPS sont mis en cache 15 secondes, et l'historique des métriques de 1 minute à 1 heure selon la période. Interroger plus souvent renvoie la même valeur et consomme du quota sans rien apporter.
Les réponses aux appels authentifiés indiquent l'état du quota dans les en-têtes X-RateLimit-Limit, X-RateLimit-Remaining et X-RateLimit-Reset. Un appel authentifié mais refusé (paramètre invalide, niveau insuffisant, conflit…) consomme lui aussi du crédit ; un appel rejeté à l'authentification, vers une route inexistante, ou refusé pour dépassement (429) n'en consomme pas. Une fois la limite atteinte, l'API répond 429 rate_limited : attendez le nombre de secondes indiqué par l'en-tête Retry-After avant de réessayer.