API
Los proyectos y los tokens de copia de seguridad no solo se gestionan en el
portal, sino también a través de una API HTTP — para su propia automatización o
mediante el proveedor de Terraform. La API habla JSON, está en
https://api.lionbackup.cloud/api/v1 y aplica exactamente la misma comprobación
de permisos que el portal.
Crear una clave
En el portal, en Desarrollo, se crea una cuenta de servicio y una clave de API para ella. La clave se muestra una sola vez — guárdela en un lugar seguro.
Una cuenta de servicio tiene exactamente los permisos de la persona a la que pertenece. Quien no pueda crear proyectos en el portal tampoco podrá hacerlo por la API; al desactivar la cuenta o borrar la clave, el acceso se cierra de inmediato.
Canjear la clave por un token de acceso
La clave no es un bearer token: primero se canjea por un token de acceso de corta duración (un JWT, válido 15 minutos).
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)
Para el canje utilice siempre el host authentik.prod.lionbackup.cloud: el
nombre corto authentik.lionbackup.cloud responde con una redirección, y un
POST no sigue las redirecciones — la llamada no devolvería entonces ningún
token.
Después se envía el token en la cabecera Authorization:
API=https://api.lionbackup.cloud/api/v1
curl -s "$API/organizations" -H "Authorization: Bearer $ACCESS_TOKEN"
Para el entorno de desarrollo rigen https://api.dev.lionbackup.cloud/api/v1
y https://authentik.dev.lionbackup.cloud/application/o/token/. Una clave
solo es válida en el entorno en el que fue creada.
Paso a paso: crear un proyecto y un token de copia de seguridad
Las siguientes llamadas se basan unas en otras y presuponen ACCESS_TOKEN y
API de la sección anterior. Los identificadores de las respuestas son
ejemplos.
1. Consultar las zonas
Un proyecto necesita el identificador (UUID) de la zona en la que deben residir
sus datos. Solo son contratables las zonas con status = active.
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"
}
]
}
El identificador de la zona deseada puede guardarse directamente en una variable:
ZONE_ID=$(curl -s "$API/zones" -H "Authorization: Bearer $ACCESS_TOKEN" \
| jq -r '.zones[] | select(.name == "de01-1") | .id')
2. Determinar la organización
Los proyectos pertenecen a una organización. La lista muestra cada organización
de la que usted es miembro, junto con su rol — pueden crear proyectos owner y
admin.
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')
La selección por nombre es intencional: la cuenta de servicio ve todas las organizaciones de su propietario y el orden de la lista no está garantizado.
3. Crear el proyecto
Los campos obligatorios son name (100 caracteres como máximo) y
availability_zone_id. Son opcionales alert_email, billing_reference,
immutable_storage (por defecto false) y — solo con almacenamiento
inmutable — retention_days (de 1 a 365, por defecto 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\"}"
Respuesta con estado 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. Crear un token de copia de seguridad
Un token de copia de seguridad pertenece exactamente a un proyecto. Con type
= write el cliente hace copias; con type = read restaura. Sin indicación
se crea un token de escritura para Linux; operating_system admite Linux,
Windows y macOS. Opcionalmente, usage_count_limit,
rate_limit_per_minute y rate_limit_per_hour limitan el uso.
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"}'
Respuesta con estado 201:
{
"token": {
"id": "c4d1e8f2-6a3b-4c9d-8e7f-1a2b3c4d5e6f",
"type": "write",
"secret": "9f3e7b1c…a41c"
}
}
secret es el token de copia de seguridad propiamente dicho (128 caracteres
hexadecimales). Se entrega una sola vez y no puede consultarse después — la
plataforma solo guarda un hash. Deposítelo de inmediato en su gestor de
secretos.
Un token de lectura para restauraciones se crea de la misma manera:
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. Listar los tokens
La lista contiene solo metadatos — nunca un secreto. Los tokens revocados ya no aparecen.
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. Revocar un token
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. Cerrar el proyecto
Un proyecto no se borra, sino que se cierra: el estado pasa a closing, todos
los tokens de escritura se revocan de inmediato y la respuesta indica cuántos.
La llamada es idempotente — un proyecto ya cerrado responde de nuevo con 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
}
Lo que debe saber
Permisos por acción
La API comprueba los mismos roles que el portal:
| Acción | Rol |
|---|---|
| Leer el proyecto, listar los tokens | cualquier rol en el proyecto |
| Modificar el proyecto, crear tokens | owner, admin, writer |
| Revocar tokens | owner, admin |
| Crear el proyecto, cerrar el proyecto | owner o admin de la organización |
404 en lugar de 403
Un recurso que no existe y uno sobre el que usted no tiene ningún rol responden
igual: 404 con {"error":"not_found"}. Así la API no revela qué
identificadores existen. Un 403 con permission_denied solo lo recibe cuando
puede ver el recurso pero no realizar la acción.
La publicación en la zona es asíncrona
Un token nuevo se transmite a la Storage Zone después de crearlo. Hasta que eso
ocurra, la zona rechaza el token con 401 — normalmente cuestión de segundos,
en caso de avería hasta la siguiente sincronización. No vuelva a crear el
token entonces; inténtelo de nuevo más tarde. A la inversa, un token revocado
puede seguir siendo válido brevemente en la zona.
Cierre de un proyecto
Cerrar revoca de inmediato todos los tokens de escritura y pone el proyecto en
closing. Los tokens de lectura siguen siendo válidos durante el período de
retención y, mientras quede una copia dentro de su retención, también puede
crear tokens de lectura nuevos para seguir restaurando las copias guardadas. Un
proyecto en closing rechaza tokens de escritura nuevos (409 project_closed); cuando está closed ya no acepta ningún token. Del mismo
modo, una organización cerrada rechaza proyectos nuevos (409 organization_closed).
Límites de frecuencia
| Límite | Valor | Se aplica a |
|---|---|---|
| Peticiones por dirección IP | 60/minuto | cada petición a la API |
| Peticiones por cuenta de servicio | 60/minuto | cada petición autenticada |
| Tamaño de una petición | 1 MB | el contenido enviado |
Cada respuesta autenticada lleva X-RateLimit-Limit, X-RateLimit-Remaining
y X-RateLimit-Reset (hora Unix en la que termina la ventana de un minuto en
curso). Por encima del límite la API responde 429,
{"error":"rate_limited"} y la cabecera Retry-After — espere esos segundos
y repita la petición. El proveedor de Terraform lo hace por sí mismo.
Las cabeceras X-RateLimit-* pueden faltar: si falla la caché de contadores
de la plataforma, la API deja temporalmente de contar por cuenta de servicio y
tampoco anuncia entonces ningún presupuesto. En su automatización confíe en el
estado 429 y en Retry-After, no en las cabeceras.
Formato de los errores
Cada error es un objeto JSON con exactamente un campo: {"error":"<code>"}.
El código es estable y está pensado para programas; ramifique según él, no
solo según el estado HTTP.
| Estado | Código | Significado |
|---|---|---|
400 | invalid_request | el contenido no es JSON, falta un campo obligatorio o un valor no es válido |
400 | invalid_zone | availability_zone_id es desconocido o la zona no está active |
400 | retention_out_of_range | retention_days está fuera del rango de 1 a 365 |
401 | invalid_token | el token de acceso falta, no es válido o ha caducado, o la cuenta de servicio se borró |
403 | owner_inactive | la persona a la que pertenece la cuenta de servicio está desactivada |
403 | permission_denied | su rol no permite esta acción |
404 | not_found | recurso desconocido o no visible para usted |
405 | method_not_allowed | la ruta existe, el método HTTP no |
409 | organization_closed | la organización se está cerrando o está cerrada |
409 | project_closed | el proyecto está closed, o closing y se pidió un token de escritura |
429 | rate_limited | límite de frecuencia — respete Retry-After |
500 | internal_error | error inesperado en la plataforma |
503 | service_unavailable | temporalmente no disponible — inténtelo de nuevo más tarde |
Terraform
Para Terraform y OpenTofu existe un proveedor que usa la misma API y gestiona proyectos y tokens de copia de seguridad como recursos. Dónde obtenerlo, cómo configurarlo y un ejemplo completo se encuentran en la página Terraform.
Referencia
La especificación completa está disponible para descargar como documento
OpenAPI 3.1: openapi.yaml. La propia API sirve el
mismo archivo en /api/v1/openapi.yaml — describe por tanto siempre
exactamente la versión en ejecución.
Loading the API reference…