MétodoRutaScopeQué hace
GET/api/v1/assets/{id}/variantsvariant:readLista las variantes, paginadas
POST/api/v1/assets/{id}/variantsvariant:writeGenera variantes (202 en cola o 201 síncrono)
POST/api/v1/assets/{id}/variants/uploadvariant:writeSube una variante ya recortada (201)
PATCH/api/v1/assets/{id}/variants/{variantId}variant:writeRenombra una variante
DELETE/api/v1/assets/{id}/variants/{variantId}variant:deleteBorra una variante y su fichero
POST/api/v1/variants/from-sourceasset:writeRecorta 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.

CampoRegla
name1–64 caracteres: letras, dígitos, - o _, empezando por letra o dígito. No se transforma
width, heightEnteros de 1 a 16384
formatwebp, jpeg, png o auto (equivale a webp)
quality1–100
fitcover, contain, fill o crop
crop_paramsx, y, width, height normalizados entre 0 y 1 (width y height mayores que 0)
asyncBooleano estricto, por defecto true
force_regenerationBooleano 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.

curl
# 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
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: file solo JPEG, PNG, WebP o GIF. variant_name sigue la misma regla de nombre (por defecto variant- y la hora), output_format es webp (por defecto), jpeg o png (jpg no vale aquí), width y height de 0 a 16384 (0 conserva el tamaño real) y permanent_url es true/false/1/0. Responde 201 con id, name, width, height, format, file_size, url, permanent y created_at. Admite Idempotency-Key.

Renombrar y borrar

curl
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
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 con url_expires mayor que 0; tras ese tiempo el fichero responde 403 y hay que pedir la URL de nuevo.
  • Formato: url sigue el formato por defecto del portal (WebP salvo que el portal diga otro); url_original es el fichero subido y url_webp el 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).

curl
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")"
  • url debe ir codificada con encodeURIComponent; si no, los parámetros internos (a, expires, signature) se leen como parámetros del endpoint y da 400 invalid_request. Solo se admiten url y format; json no 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.
EstadoCódigo (prefijo de detail)Causa
400invalid_request, invalid_formaturl ausente o sin codificar, parámetro desconocido, o format no soportado
403source_not_allowedLa ruta no es de /media/ ni /files/, o contiene ..
403invalid_source_signatureFalta la firma de la URL, es inválida o ha caducado: pide la URL de nuevo a la API
404source_not_foundLa imagen ya no existe
413 / 415 / 422source_too_large, unsupported_media_type, unprocessable_imageEl origen es demasiado grande, no es una imagen soportada o no se puede decodificar
429—Límite por IP; usa Retry-After
500conversion_failedFallo interno, con detalle genérico

Errores propios de esta página

EstadoCausa
403Falta el scope, o write_access_denied (asset legible de otro portal)
404Asset o variante inexistente, borrado o no legible (sin distinguir)
415Generar, PATCH y from-source exigen application/json; la subida exige multipart/form-data
422Especificació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.