Aller au contenu principal

API

Les projets et les jetons de sauvegarde se gèrent non seulement dans le portail, mais aussi via une API HTTP — pour votre propre automatisation ou avec le fournisseur Terraform. L'API parle JSON, se trouve à https://api.lionbackup.cloud/api/v1 et applique exactement le même contrôle des droits que le portail.

Créer une clé​

Dans le portail, sous Développeurs, vous créez un compte de service et une clé d'API associée. La clé n'est affichée qu'une seule fois — conservez-la en lieu sûr.

Un compte de service possède exactement les droits de la personne à qui il appartient. Qui ne peut pas créer de projets dans le portail ne le peut pas davantage via l'API ; si le compte est désactivé ou la clé supprimée, l'accès est fermé immédiatement.

Échanger la clé contre un jeton d'accès​

La clé n'est pas un jeton bearer : vous l'échangez d'abord contre un jeton d'accès de courte durée (un JWT, valable 15 minutes).

ACCESS_TOKEN=$(curl -s https://authentik.prod.lionbackup.cloud/application/o/token/ \
-d grant_type=client_credentials \
-d client_id=lionbackup-api \
-d client_secret="$LIONBACKUP_API_KEY" \
-d scope="profile lionbackup_api" | jq -r .access_token)

Utilisez toujours l'hôte authentik.prod.lionbackup.cloud pour l'échange : le nom court authentik.lionbackup.cloud répond par une redirection, et un POST ne suit pas une redirection — l'appel ne renvoie alors aucun jeton.

Vous envoyez ensuite le jeton dans l'en-tête Authorization :

API=https://api.lionbackup.cloud/api/v1

curl -s "$API/organizations" -H "Authorization: Bearer $ACCESS_TOKEN"
Environnement de développement

Pour l'environnement de développement, utilisez https://api.dev.lionbackup.cloud/api/v1 et https://authentik.dev.lionbackup.cloud/application/o/token/. Une clé n'est valable que dans l'environnement où elle a été créée.

Pas à pas : créer un projet et un jeton de sauvegarde​

Les appels suivants s'enchaînent et supposent ACCESS_TOKEN et API de la section précédente. Les identifiants dans les réponses sont des exemples.

1. Interroger les zones​

Un projet a besoin de l'identifiant (UUID) de la zone dans laquelle ses données seront stockées. Seules les zones avec status = active peuvent être réservées.

curl -s "$API/zones" -H "Authorization: Bearer $ACCESS_TOKEN"
{
"zones": [
{
"id": "3f0c2a4e-8b1d-4c6a-9e2f-5d7b1a9c0e31",
"name": "de01-1",
"status": "active",
"provider": "Hetzner",
"location_city": "Nürnberg",
"storage_type": "managed object storage"
},
{
"id": "7a9d4b2c-1e5f-4a83-b6c0-2f8e9d1c4a57",
"name": "de01-2",
"status": "preparing",
"provider": "Hetzner",
"location_city": "Falkenstein",
"storage_type": "managed object storage"
}
]
}

L'identifiant de la zone souhaitée peut être placé directement dans une variable :

ZONE_ID=$(curl -s "$API/zones" -H "Authorization: Bearer $ACCESS_TOKEN" \
| jq -r '.zones[] | select(.name == "de01-1") | .id')

2. Déterminer l'organisation​

Les projets appartiennent à une organisation. La liste montre chaque organisation dont vous êtes membre, avec votre rôle — owner et admin peuvent créer des projets.

curl -s "$API/organizations" -H "Authorization: Bearer $ACCESS_TOKEN"
{
"organizations": [
{
"id": "9b2e6c1a-4d3f-4e8b-a7c5-0f1d2e3a4b5c",
"name": "Example Ltd",
"status": "approved",
"role": "owner"
}
]
}
ORG_ID=$(curl -s "$API/organizations" -H "Authorization: Bearer $ACCESS_TOKEN" \
| jq -r '.organizations[] | select(.name == "Example Ltd") | .id')

Le choix par nom est volontaire : le compte de service voit toutes les organisations de son propriétaire et l'ordre de la liste n'est pas garanti.

3. Créer le projet​

Les champs obligatoires sont name (100 caractères au maximum) et availability_zone_id. Sont facultatifs alert_email, billing_reference, immutable_storage (par défaut false) et — uniquement pour le stockage immuable — retention_days (1 à 365, par défaut 30).

curl -s -X POST "$API/organizations/$ORG_ID/projects" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"name\":\"web-servers\",\"availability_zone_id\":\"$ZONE_ID\",\"alert_email\":\"ops@example.com\"}"

Réponse avec le statut 201 :

{
"project": {
"id": "ea1296ad-5c7b-4f2e-8a1d-3b6c9e0f7d24",
"name": "web-servers",
"status": "active",
"organization_id": "9b2e6c1a-4d3f-4e8b-a7c5-0f1d2e3a4b5c",
"availability_zone_id": "3f0c2a4e-8b1d-4c6a-9e2f-5d7b1a9c0e31",
"alert_email": "ops@example.com",
"billing_reference": null,
"immutable_storage": false,
"retention_days": null,
"created_at": "2026-09-24 09:41:12.418273"
}
}
PROJECT_ID=ea1296ad-5c7b-4f2e-8a1d-3b6c9e0f7d24

4. Créer un jeton de sauvegarde​

Un jeton de sauvegarde appartient à exactement un projet. Avec type = write, le client sauvegarde ; avec type = read, il restaure. Sans indication, un jeton d'écriture pour Linux est créé ; operating_system connaît Linux, Windows et macOS. En option, usage_count_limit, rate_limit_per_minute et rate_limit_per_hour limitent l'utilisation.

curl -s -X POST "$API/projects/$PROJECT_ID/tokens" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"type":"write","operating_system":"Linux"}'

Réponse avec le statut 201 :

{
"token": {
"id": "c4d1e8f2-6a3b-4c9d-8e7f-1a2b3c4d5e6f",
"type": "write",
"secret": "9f3e7b1c…a41c"
}
}
Le secret n'apparaît que dans cette réponse

secret est le véritable jeton de sauvegarde (128 caractères hexadécimaux). Il n'est délivré qu'une seule fois et ne peut plus être récupéré par la suite — la plateforme n'en conserve qu'un hachage. Déposez-le immédiatement dans votre gestionnaire de secrets.

Un jeton de lecture pour les restaurations se crée de la même manière :

curl -s -X POST "$API/projects/$PROJECT_ID/tokens" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"type":"read"}'
{
"token": {
"id": "5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9",
"type": "read",
"secret": "d27c0a8e…5b93"
}
}

5. Lister les jetons​

La liste ne contient que des métadonnées — jamais un secret. Les jetons révoqués n'y apparaissent plus.

curl -s "$API/projects/$PROJECT_ID/tokens" -H "Authorization: Bearer $ACCESS_TOKEN"
{
"tokens": [
{
"id": "5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9",
"type": "read",
"operating_system": "Linux",
"is_active": true,
"usage_count": 0,
"usage_count_limit": null,
"created_at": "2026-09-24 09:43:05.102944",
"expire": null
},
{
"id": "c4d1e8f2-6a3b-4c9d-8e7f-1a2b3c4d5e6f",
"type": "write",
"operating_system": "Linux",
"is_active": true,
"usage_count": 0,
"usage_count_limit": null,
"created_at": "2026-09-24 09:42:37.556210",
"expire": null
}
]
}

6. Révoquer un jeton​

TOKEN_ID=c4d1e8f2-6a3b-4c9d-8e7f-1a2b3c4d5e6f

curl -s -X DELETE "$API/projects/$PROJECT_ID/tokens/$TOKEN_ID" \
-H "Authorization: Bearer $ACCESS_TOKEN"
{ "deleted": true }

7. Fermer le projet​

Un projet n'est pas supprimé mais fermé : le statut passe à closing, tous les jetons d'écriture sont révoqués immédiatement, la réponse en indique le nombre. L'appel est idempotent — un projet déjà fermé répond de nouveau 200.

curl -s -X POST "$API/projects/$PROJECT_ID/close" \
-H "Authorization: Bearer $ACCESS_TOKEN"
{
"project": {
"id": "ea1296ad-5c7b-4f2e-8a1d-3b6c9e0f7d24",
"name": "web-servers",
"status": "closing",
"organization_id": "9b2e6c1a-4d3f-4e8b-a7c5-0f1d2e3a4b5c",
"availability_zone_id": "3f0c2a4e-8b1d-4c6a-9e2f-5d7b1a9c0e31",
"alert_email": "ops@example.com",
"billing_reference": null,
"immutable_storage": false,
"retention_days": null,
"created_at": "2026-09-24 09:41:12.418273"
},
"write_tokens_revoked": 1
}

Ce qu'il faut savoir​

Droits par action​

L'API vérifie les mêmes rôles que le portail :

ActionRôle
Lire un projet, lister les jetonstout rôle dans le projet
Modifier un projet, créer un jetonowner, admin, writer
Révoquer un jetonowner, admin
Créer un projet, fermer un projetowner ou admin de l'organisation

404 au lieu de 403​

Une ressource qui n'existe pas et une ressource sur laquelle vous n'avez aucun rôle répondent de la même façon : 404 avec {"error":"not_found"}. L'API ne révèle ainsi pas quels identifiants existent. Vous ne recevez un 403 avec permission_denied que si vous êtes autorisé à voir la ressource, mais pas à effectuer l'action.

La publication vers la zone est asynchrone​

Un nouveau jeton est transmis à la Storage Zone après sa création. Tant que ce n'est pas fait, la zone rejette le jeton avec 401 — en général quelques secondes, en cas d'incident jusqu'à la prochaine synchronisation. Ne recréez pas le jeton dans ce cas, mais réessayez plus tard. Inversement, un jeton révoqué peut rester brièvement valable dans la zone.

Fermeture d'un projet​

La fermeture révoque immédiatement tous les jetons d'écriture et fait passer le projet à closing. Les jetons de lecture restent valables pendant la durée de rétention et, tant qu'une sauvegarde est encore dans sa durée de rétention, vous pouvez aussi créer de nouveaux jetons de lecture pour continuer à restaurer les sauvegardes stockées. Un projet closing refuse les nouveaux jetons d'écriture (409 project_closed) ; une fois closed, il n'accepte plus aucun jeton. De même, une organisation fermée refuse les nouveaux projets (409 organization_closed).

Limites de débit​

LimiteValeurS'applique à
Requêtes par adresse IP60/minutechaque requête vers l'API
Requêtes par compte de service60/minutechaque requête authentifiée
Taille d'une requête1 Mole contenu envoyé

Chaque réponse authentifiée porte X-RateLimit-Limit, X-RateLimit-Remaining et X-RateLimit-Reset (heure Unix à laquelle la fenêtre d'une minute en cours se termine). Au-delà de la limite, l'API répond 429 avec {"error":"rate_limited"} et l'en-tête Retry-After — attendez ce nombre de secondes puis répétez la requête. Le fournisseur Terraform le fait de lui-même.

Les en-têtes X-RateLimit-* peuvent manquer : si le cache de compteurs de la plateforme tombe en panne, l'API ne compte temporairement plus par compte de service et n'annonce alors aucun budget. Dans votre automatisation, fiez-vous au statut 429 et à Retry-After, pas aux en-têtes.

Format des erreurs​

Chaque erreur est un objet JSON avec exactement un champ : {"error":"<code>"}. Le code est stable et destiné aux programmes ; basez vos branchements sur lui, pas sur le seul statut HTTP.

StatutCodeSignification
400invalid_requestle contenu n'est pas du JSON, un champ obligatoire manque ou une valeur est invalide
400invalid_zoneavailability_zone_id est inconnu ou la zone n'est pas active
400retention_out_of_rangeretention_days est en dehors de 1 à 365
401invalid_tokenjeton d'accès absent, invalide ou expiré, compte de service supprimé
403owner_inactivela personne à qui appartient le compte de service est désactivée
403permission_deniedvotre rôle n'autorise pas cette action
404not_foundressource inconnue ou invisible pour vous
405method_not_allowedle chemin existe, pas la méthode HTTP
409organization_closedl'organisation est en cours de fermeture ou fermée
409project_closedle projet est closed, ou closing et un jeton d'écriture a été demandé
429rate_limitedlimite de débit — respecter Retry-After
500internal_errorerreur inattendue sur la plateforme
503service_unavailabletemporairement indisponible — réessayer plus tard

Terraform​

Pour Terraform et OpenTofu, il existe un fournisseur qui utilise la même API et gère les projets ainsi que les jetons de sauvegarde comme des ressources. Vous trouverez la source d'installation, la configuration et un exemple complet sur la page Terraform.

Référence​

La spécification complète est disponible sous forme de document OpenAPI 3.1 : openapi.yaml. L'API elle-même sert le même fichier sur /api/v1/openapi.yaml — elle décrit donc toujours exactement la version en cours d'exécution.

Loading the API reference…