🔄 Variantes y entrega
Versiones redimensionadas de un asset, cómo se sirven los ficheros y conversión de formato al vuelo.
| Método | Ruta | Scope | Qué hace |
|---|---|---|---|
| GET | /api/v1/assets/{id}/variants | variant:read | Lista las variantes, paginadas |
| POST | /api/v1/assets/{id}/variants | variant:write | Genera variantes (202 en cola o 201 síncrono) |
| POST | /api/v1/assets/{id}/variants/upload | variant:write | Sube una variante ya recortada (201) |
| PATCH | /api/v1/assets/{id}/variants/{variantId} | variant:write | Renombra una variante |
| DELETE | /api/v1/assets/{id}/variants/{variantId} | variant:delete | Borra una variante y su fichero |
| POST | /api/v1/variants/from-source | asset:write | Recorta una imagen al vuelo, sin guardar nada |
| GET | /api/v1/image-convert | — (público) | Convierte una imagen de Limbo a png, jpg o webp |
Generar variantes
Cuerpo JSON con variants, de 1 a 20 especificaciones. Cada una lleva name, width y height
(obligatorios) y, opcionalmente, format, quality, fit, preset_aspect, preset_size y crop_params.
| Campo | Regla |
|---|---|
name | 1–64 caracteres: letras, dígitos, - o _, empezando por letra o dígito. No se transforma |
width, height | Enteros de 1 a 16384 |
format | webp, jpeg, png o auto (equivale a webp) |
quality | 1–100 |
fit | cover, contain, fill o crop |
crop_params | x, y, width, height normalizados entre 0 y 1 (width y height mayores que 0) |
async | Booleano estricto, por defecto true |
force_regeneration | Booleano estricto, por defecto false |
Una clave desconocida en una especificación (incluida output_format) es 422. La política del portal (tamaño máximo, formatos, presets) también se valida y responde 422.
# En cola (por defecto): 202 Accepted, las variantes salen con status "queued"
curl -X POST https://limbo.lefebvre.es/api/v1/assets/$ID/variants \
-H "Authorization: Bearer $JWT" -H "Content-Type: application/json" \
-d '{"variants": [{"name": "card", "width": 400, "height": 300}, {"name": "hero", "width": 1600, "height": 900, "format": "webp", "quality": 85}]}'
# Síncrono: 201 Created, las variantes salen con status "completed" (o "error" con un texto fijo)
curl -X POST https://limbo.lefebvre.es/api/v1/assets/$ID/variants \
-H "Authorization: Bearer $JWT" -H "Content-Type: application/json" \
-d '{"async": false, "variants": [{"name": "card", "width": 400, "height": 300}]}'
Con 202 la generación se hace en un worker: consulta GET /api/v1/assets/{id}/variants hasta que aparezcan.
Admite Idempotency-Key. Máximo 20 variantes por asset.
Listar y subir una variante propia
curl "https://limbo.lefebvre.es/api/v1/assets/$ID/variants?page=1&per_page=50&url_expires=3600" \
-H "Authorization: Bearer $JWT"
# Variante ya recortada en el cliente (multipart; no admite URL ni base64)
curl -X POST https://limbo.lefebvre.es/api/v1/assets/$ID/variants/upload \
-H "Authorization: Bearer $JWT" \
-F "file=@recorte.png" -F "variant_name=banner" -F "output_format=webp" -F "width=1200" -F "height=400"
- Listado: orden por fecha de creación ascendente.
url_expires(segundos, máximo un año) hace caducar las URLs; con 0 (por defecto) son permanentes. Un asset legible de otro portal también se puede listar. - Subida:
filesolo JPEG, PNG, WebP o GIF.variant_namesigue la misma regla de nombre (por defectovariant-y la hora),output_formateswebp(por defecto),jpegopng(jpgno vale aquí),widthyheightde 0 a 16384 (0 conserva el tamaño real) ypermanent_urlestrue/false/1/0. Responde 201 conid,name,width,height,format,file_size,url,permanentycreated_at. AdmiteIdempotency-Key.
Renombrar y borrar
curl -X PATCH https://limbo.lefebvre.es/api/v1/assets/$ID/variants/$VARIANT_ID \
-H "Authorization: Bearer $JWT" -H "Content-Type: application/json" \
-d '{"name": "card-2x"}'
curl -X DELETE https://limbo.lefebvre.es/api/v1/assets/$ID/variants/$VARIANT_ID \
-H "Authorization: Bearer $JWT"
# { "success": true, "data": { "id": "...", "asset_id": "...", "status": "deleted" } }
PATCH solo acepta name. Enviar width, height, output_format, quality o
crop_params da 422: para cambiar el tamaño, borra la variante y genera otra. DELETE exige variant:delete
(asset:delete no basta). Una variante inexistente o de otro asset es 404.
Recortar sin guardar: from-source
Útil para generar recortes en un editor antes de subirlos. No crea ni cambia ningún asset y no admite Idempotency-Key.
image es un data URI, base64 o una URL http(s) (pasa por la guarda anti-SSRF; file:// y rutas de disco se rechazan).
crops lleva de 1 a 20 recortes con label (obligatoria y única; original está reservada), width y height de 1 a 3500,
y opcionalmente format (webp, jpeg, jpg o png), quality (1–100) y crop_params.
return_original añade la entrada original.
curl -X POST https://limbo.lefebvre.es/api/v1/variants/from-source \
-H "Authorization: Bearer $JWT" -H "Content-Type: application/json" \
-d '{"image": "https://cdn.ejemplo.es/foto.jpg", "crops": [{"label": "thumb", "width": 200, "height": 200, "format": "webp"}]}'
# Respuesta (recortada): un objeto por etiqueta
{ "success": true, "data": { "thumb": { "image": "data:image/webp;base64,UklGR...", "metas": { "width": 200, "height": 200, "format": "webp", "quality": 90 } } } }
Entrega de ficheros
La API devuelve en url / url_original (assets) y url (variantes) direcciones de la forma
https://limbo.lefebvre.es/media/{slug}/{nombre}.{ext}?a={token}. El token (a) va cifrado y firmado y es la única autorización:
se sirven sin Authorization, con CORS abierto, y valen directamente en un <img src>.
- No las recompongas: el
{slug}/{nombre}es decorativo; lo que cuenta es el token. Guarda la URL tal cual o vuelve a pedir el asset. - Caducidad: por defecto son permanentes (
permanent: true). Para URLs con caducidad, pide el asset o las variantes conurl_expiresmayor que 0; tras ese tiempo el fichero responde 403 y hay que pedir la URL de nuevo. - Formato:
urlsigue el formato por defecto del portal (WebP salvo que el portal diga otro);url_originales el fichero subido yurl_webpel master optimizado.
Convertir de formato: image-convert
GET /api/v1/image-convert?url=…&format=… es público (sin Authorization, apto para <img src>) y con límite propio de 600 peticiones por minuto e IP, independiente del de los proxies.
Convierte una imagen que ya sirve Limbo a png, jpg, jpeg o webp (por defecto webp) y devuelve el binario,
con ETag y soporte de If-None-Match (304).
URL='https://limbo.lefebvre.es/media/mi-portal/portada.jpg?a=Qm81B...'
curl -o portada.png "https://limbo.lefebvre.es/api/v1/image-convert?format=png&url=$(python3 -c "import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1], safe=''))" "$URL")"
urldebe ir codificada conencodeURIComponent; si no, los parámetros internos (a,expires,signature) se leen como parámetros del endpoint y da 400invalid_request. Solo se admitenurlyformat;jsonno existe en v1.- Solo imágenes de Limbo: una URL
/media/…?a=o/files/…?expires=&signature=con su propia firma. El host se ignora y no hay imágenes externas.
| Estado | Código (prefijo de detail) | Causa |
|---|---|---|
| 400 | invalid_request, invalid_format | url ausente o sin codificar, parámetro desconocido, o format no soportado |
| 403 | source_not_allowed | La ruta no es de /media/ ni /files/, o contiene .. |
| 403 | invalid_source_signature | Falta la firma de la URL, es inválida o ha caducado: pide la URL de nuevo a la API |
| 404 | source_not_found | La imagen ya no existe |
| 413 / 415 / 422 | source_too_large, unsupported_media_type, unprocessable_image | El origen es demasiado grande, no es una imagen soportada o no se puede decodificar |
| 429 | — | Límite por IP; usa Retry-After |
| 500 | conversion_failed | Fallo interno, con detalle genérico |
Errores propios de esta página
| Estado | Causa |
|---|---|
| 403 | Falta el scope, o write_access_denied (asset legible de otro portal) |
| 404 | Asset o variante inexistente, borrado o no legible (sin distinguir) |
| 415 | Generar, PATCH y from-source exigen application/json; la subida exige multipart/form-data |
| 422 | Especificación inválida o fuera de la política del portal, regeneración en PATCH, o Idempotency-Key con otro cuerpo |
Formato general de errores en Conceptos; schemas en la referencia OpenAPI. Siguiente: Portal y presets.