⚙️ Portal y presets
El perfil del portal del token, los portales que puede leer, sus presets de recorte y sus métricas de uso.
| Método | Ruta | Scope | Qué hace |
|---|---|---|---|
| GET | /api/v1/portals/me | portal:read | Perfil y políticas del portal |
| GET | /api/v1/portals/me/cross-portal-access | asset:read | Portales cuyos assets puede leer |
| GET | /api/v1/portals/me/presets | portal:read | Presets de aspecto y de tamaño |
| POST | /api/v1/portals/me/presets/aspect | portal:admin | Crea un preset de aspecto (201) |
| POST | /api/v1/portals/me/presets/size | portal:admin | Crea un preset de tamaño (201) |
| PATCH | /api/v1/portals/me/presets/aspect/{id} | portal:admin | Edita un preset |
| PATCH | /api/v1/portals/me/presets/size/{id} | portal:admin | Edita un preset |
| DELETE | /api/v1/portals/me/presets/aspect/{id} | portal:admin | Borra un preset |
| DELETE | /api/v1/portals/me/presets/size/{id} | portal:admin | Borra un preset |
| GET | /api/v1/metrics/usage | portal:read | Resumen y tendencia diaria de uso |
| GET | /api/v1/metrics/endpoints | portal:read | Ranking de endpoints más usados |
El portal es siempre el del token: ninguna ruta acepta un identificador de portal. Los scopes portal:read y portal:admin
solo existen en v1 y se conceden a la API key en el dashboard (Autenticación).
Perfil del portal
curl https://limbo.lefebvre.es/api/v1/portals/me -H "Authorization: Bearer $JWT"
# Respuesta (recortada)
{ "success": true,
"data": {
"id": "7c0e8a52-...", "name": "Mi Portal", "slug": "mi-portal", "public_key": "pk_...",
"allowed_origins": ["https://app.ejemplo.es"], "signed_url_duration_seconds": 3600, "retention_days": null,
"policies": { "format_policy": { "default_format": "webp" }, "presets_aspect": [], "presets_size": [], "allow_arbitrary": true, "cross_access_policy": "none" }
} }
public_key es la clave pública del portal, no la pk_ de tu API key. Nunca se devuelven la clave privada, la lista de acceso cruzado
ni las listas blanca y negra de acceso.
Acceso cross-portal
curl https://limbo.lefebvre.es/api/v1/portals/me/cross-portal-access -H "Authorization: Bearer $JWT"
{ "success": true,
"data": {
"self_portal": { "slug": "mi-portal", "label": "Mi Portal" },
"read_access": [ { "slug": "atenea", "label": "Atenea", "asset_count": 1240 } ]
} }
read_access lista solo los portales que la política del portal permite leer (con el número de assets activos) y está vacía salvo que la política de lectura sea
specific. Son los slugs que puedes pasar en include_portals al
listar assets. Se conceden por CLI
(limbo:grant-cross-portal-access); no hay endpoint público para ello. Un portal sin slug no se lista porque no podría usarse.
Presets
Dos tipos: aspect (relación de aspecto: name, ratio W:H, width, height) y
size (name, width, height). Todos los campos son obligatorios al crear; width y height
son enteros de 1 a 10000, name hasta 100 caracteres sin < ni >, y ratio tiene la forma 16:9.
El id lo genera el servidor; cualquier clave desconocida (incluidos id y, en size, ratio) es 422. Máximo 100 presets por tipo.
curl https://limbo.lefebvre.es/api/v1/portals/me/presets -H "Authorization: Bearer $JWT"
# { "success": true, "data": { "presets_aspect": [ { "id": "aspect-65f1c2a3b4d5e", "name": "Wide", "ratio": "16:9", "width": 16, "height": 9 } ],
# "presets_size": [ { "id": "size-65f1c2a3b4d5e", "name": "HD", "width": 1920, "height": 1080 } ] } }
curl -X POST https://limbo.lefebvre.es/api/v1/portals/me/presets/size \
-H "Authorization: Bearer $JWT" -H "Content-Type: application/json" \
-d '{"name": "Tarjeta", "width": 400, "height": 300}'
curl -X PATCH https://limbo.lefebvre.es/api/v1/portals/me/presets/size/size-65f1c2a3b4d5e \
-H "Authorization: Bearer $JWT" -H "Content-Type: application/json" \
-d '{"width": 800}'
curl -X DELETE https://limbo.lefebvre.es/api/v1/portals/me/presets/size/size-65f1c2a3b4d5e -H "Authorization: Bearer $JWT"
# { "success": true, "data": { "id": "size-65f1c2a3b4d5e", "status": "deleted" } }
- Listar exige
portal:read; crear, editar y borrar exigenportal:admin. El listado devuelve siempre las dos listas, vacías si no hay presets. PATCHcambia solo los campos enviados (nullcuenta como no enviado) y necesita al menos uno. Un preset inexistente, o de otro tipo, es 404.- Los
POSTadmitenIdempotency-Key. - Los presets se usan al generar variantes con
preset_aspect/preset_size(Variantes) y la política del portal puede limitar las variantes a ellos.
Métricas de uso
curl "https://limbo.lefebvre.es/api/v1/metrics/usage?period=last7days" -H "Authorization: Bearer $JWT"
curl "https://limbo.lefebvre.es/api/v1/metrics/usage?from=2026-10-01&to=2026-10-31" -H "Authorization: Bearer $JWT"
curl "https://limbo.lefebvre.es/api/v1/metrics/endpoints?period=last30days&top=5" -H "Authorization: Bearer $JWT"
# usage (recortada)
{ "success": true,
"data": {
"summary": { "total_requests": 200, "successful_requests": 190, "error_requests": 10, "server_error_requests": 1, "avg_latency_ms": 42.1, "max_latency_ms": 910, "total_bytes_out": 5230000, "success_rate": 95.0, "total_days": 7 },
"daily_trends": [ { "date": "2026-10-30", "total_requests": 31, "error_requests": 1, "avg_latency_ms": 40.2, "total_bytes_out": 800000, "success_rate": 96.8 } ]
},
"meta": { "period": "last7days", "from": "2026-10-25", "to": "2026-10-31" } }
- Rango:
period(today,yesterday,last7days,last30days,thismonth) ofrom+to(YYYY-MM-DD, ambos, máximo 365 días). Sin parámetros:last30days. - Un rango incoherente (
periodconfrom/to, solo uno de los dos,fromposterior ato, más de 365 días o fecha mal formada) es 422; no se recorta en silencio. endpointsdevuelve{endpoint, request_count, avg_latency_ms}ordenado por peticiones, sin paginar:topde 1 a 50 (por defecto 10).limitda 422.
Errores propios de esta página
| Estado | Causa |
|---|---|
| 403 | La API key no tiene portal:read / portal:admin (o asset:read en cross-portal) |
| 404 | Preset inexistente o de otro tipo |
| 422 | Campo inválido o desconocido, límite de 100 presets, rango de métricas inválido, o Idempotency-Key con otro cuerpo |
Formato general de errores en Conceptos; schemas en la referencia OpenAPI. Siguiente: IA, stock y externos.