Docs / Módulo / Imágenes
Módulo de Imágenes
CDN y API para redimensionado, compresión y conversión (WebP / AVIF) con baja latencia en LatAm y caché integrada. Soporta tres modos de integración: URL directa, librería JavaScript con lazy loading, y API autenticada.
Introducción
Las imágenes representan más del 50 % del peso de una página web. El módulo de Imágenes de Webability las procesa, redimensiona y convierte a WebP o AVIF en tiempo real, con caché integrada. Solo necesitas tu clientid (10 letras minúsculas) disponible en la consola de administración.
Ideal para
- • Web y móviles
- • E-commerce y catálogos
- • Mejora de Core Web Vitals
Formatos de salida
WebP y AVIF (o JPG como fallback automático). Entrada: JPG, PNG, GIF, WebP, AVIF.
Modos de integración
- 1. URL directa en HTML
- 2. Lazy Loading JS
- 3. API autenticada
Quickstart
En menos de 2 minutos puedes servir tu primera imagen optimizada. Solo necesitas tu clientid, que se obtiene en la consola → Configuración.
- 1 Obtén tu clientid de 10 letras en la consola de administración.
- 2 Configura el dominio de tu CDN de origen (donde viven las imágenes originales).
- 3 Usa el endpoint directamente en tu código HTML:
URL directa — estructura
https://cdn.webability.info/[IDCliente]/ruta/en/tu/cdn/720x480/imagen.jpg.webp
webp, avif o jpg
Ejemplo concreto — logo 50×50 en AVIF
<!-- imagen original: https://www.tusitio.com.mx/imagenes/logo.png --> <img src="https://cdn.webability.info/abcdefghij/imagenes/50x50/logo.png.avif" alt="Logo">
💡 Recomendado para producción
Usa el modo Lazy Loading JS para mejor SEO y performance: la librería detecta el viewport, carga imágenes bajo demanda y elige automáticamente el mejor formato soportado por el navegador.
Llamada directa por URL
El método más simple: construye la URL de la imagen optimizada y úsala directamente en el atributo src de cualquier etiqueta <img>, en CSS, en etiquetas <picture> o como argumento de cualquier petición HTTP. No requiere JavaScript ni autenticación.
Estructura de la URL
https://cdn.webability.info/{clientid}/{ruta}/{WxH}/{archivo.ext}
| Segmento | Descripción |
|---|---|
| {clientid} | Tu identificador de cliente (10 letras minúsculas). Disponible en la consola → Configuración. |
| {ruta} | Directorio de la imagen en tu CDN de origen, sin el dominio. Puede contener subcarpetas. |
| {WxH} | Dimensiones objetivo en píxeles. Formato: anchoXalto, p. ej. 800x600. |
| {archivo.ext} | Nombre del archivo original incluyendo su extensión, seguido de .webp, .avif o .jpg para la salida deseada. |
Ejemplos
Etiqueta <img> simple
<img src="https://cdn.webability.info/abcdefghij/productos/800x600/zapatilla.jpg.webp" alt="Zapatilla deportiva" width="800" height="600" />
Elemento <picture> con AVIF y WebP
<picture>
<source
type="image/avif"
srcset="https://cdn.webability.info/abcdefghij/blog/1200x630/portada.jpg.avif"
/>
<source
type="image/webp"
srcset="https://cdn.webability.info/abcdefghij/blog/1200x630/portada.jpg.webp"
/>
<img
src="https://cdn.webability.info/abcdefghij/blog/1200x630/portada.jpg.jpg"
alt="Portada del artículo"
width="1200" height="630"
/>
</picture>
srcset responsivo
<img
srcset="
https://cdn.webability.info/abcdefghij/hero/480x320/banner.jpg.webp 480w,
https://cdn.webability.info/abcdefghij/hero/768x512/banner.jpg.webp 768w,
https://cdn.webability.info/abcdefghij/hero/1200x800/banner.jpg.webp 1200w
"
sizes="(max-width: 600px) 480px, (max-width: 900px) 768px, 1200px"
src="https://cdn.webability.info/abcdefghij/hero/1200x800/banner.jpg.webp"
alt="Banner principal"
/>
Imagen de fondo en CSS
.hero {
background-image: url(
"https://cdn.webability.info/abcdefghij/home/1920x1080/fondo.jpg.webp"
);
background-size: cover;
}
cURL — descarga directa
curl -L "https://cdn.webability.info/abcdefghij/productos/400x400/item.png.avif" -o item.avif
Imagen de demostración del sitio (1.6 MB original → ~32 KB en WebP 600×450)
<img src="https://cdn.webability.info/webability/static/600x450/images.png.webp" />
La primera solicitud genera y cachea la imagen. Las siguientes son servidas directamente desde caché con Cache-Control: public, max-age=31536000.
Lazy Loading con la librería JavaScript
RecomendadoIncluye en tu sitio la librería JavaScript personalizada. Detectará automáticamente todos los elementos marcados, construirá las URLs correctas y los cargará de forma diferida (lazy loading), mejorando los Core Web Vitals y el SEO. Si el navegador no soporta WebP o AVIF, servirá automáticamente la alternativa en JPG.
Paso 1 — Incluir la librería en el <head>
<head>
...
<!-- Librería de imágenes Webability (reemplaza {clientid} con tu ID) -->
<script src="https://cdn.webability.info/js/[IDCliente]" defer></script>
...
</head>
Paso 2 — Marcar las imágenes con atributos data-*
En lugar del atributo src, usa los atributos de datos siguientes:
| Atributo | Obligatorio | Descripción |
|---|---|---|
| data-src | Sí | Ruta completa de la imagen en tu CDN de origen (URL absoluta o ruta relativa al dominio configurado). |
| data-width | Sí | Ancho deseado en píxeles (número entero). |
| data-height | Sí | Alto deseado en píxeles (número entero). |
| data-format | No | Formato de salida: webp (defecto), avif, jpg u original (mantiene el formato fuente). |
Ejemplos
Imagen básica en WebP (formato por defecto)
<img class="wa-lazy" data-src="/imagenes/logo.png" data-width="50" data-height="50" style="width:50px; height:50px;" alt="Logo" />
Imagen en AVIF con dimensiones explícitas
<img class="wa-lazy" data-src="/fotos/producto.jpg" data-width="400" data-height="300" data-format="avif" style="width:400px; height:300px;" alt="Producto" />
Hero banner en WebP
<img class="wa-lazy rounded-xl" data-src="/static/images.png" data-width="600" data-height="450" data-format="webp" style="width:600px;" alt="Hero" />
Formato original (sin conversión)
<img class="wa-lazy" data-src="/catalogos/ficha.gif" data-width="300" data-height="200" data-format="original" alt="Animación de ficha" />
Página completa — ejemplo de integración
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title>Mi Sitio</title>
<script src="https://cdn.webability.info/js/abcdefghij" defer></script>
</head>
<body>
<!-- Logo en header -->
<img class="wa-lazy" data-src="/static/logotr.png" data-width="50" data-height="50" style="width:50px;">
<!-- Galería de productos -->
<img class="wa-lazy" data-src="/productos/camisa-azul.jpg" data-width="400" data-height="400" data-format="webp">
<img class="wa-lazy" data-src="/productos/pantalon.jpg" data-width="400" data-height="400" data-format="avif">
<!-- Indicador de carga (opcional) -->
<div class="wa-loader"></div>
</body>
</html>
URL generada automáticamente por la librería (lo que termina en el src)
https://cdn.webability.info/abcdefghij/productos/400x400/camisa-azul.jpg.webp
La librería solo carga imágenes cuando entran al viewport del usuario (Intersection Observer API), reduciendo el ancho de banda inicial y mejorando el LCP.
API autenticada
La API autenticada permite operaciones avanzadas desde tu backend: obtener imágenes procesadas, subir originales directamente y gestionar la caché. Todos los endpoints requieren los tres headers de autenticación descritos en la sección Autenticación.
Endpoint /v1/image
Gestión completa de imágenes: obtener, subir y purgar caché.
Recupera una imagen procesada y redimensionada. Si no existe en caché, la descarga desde tu CDN de origen, la convierte y la almacena. La respuesta es el binario de la imagen con el Content-Type correspondiente.
Segmentos de la URL
| Segmento | Descripción |
|---|---|
| {ruta} | Directorio de la imagen en el repositorio del cliente. |
| {WxH} | Dimensiones en píxeles. Formato: anchoXalto, p. ej. 800x600. |
| {archivo.ext} | Nombre del archivo original con su extensión fuente, más la extensión de salida: imagen.jpg.webp. Salida soportada: webp, avif, jpg. |
Ejemplos de request
cURL — obtener imagen
curl -X GET \
-H "X-WA-Token: {token}" \
-H "X-WA-Timestamp: {unix}" \
-H "X-WA-Digest: {hmac}" \
"https://api.webability.info/v1/image/productos/800x600/zapatilla.jpg.webp" \
-o zapatilla.webp
Go — HTTP client
req, _ := http.NewRequest("GET",
"https://api.webability.info/v1/image/productos/800x600/zapatilla.jpg.webp", nil)
req.Header.Set("X-WA-Token", token)
req.Header.Set("X-WA-Timestamp", ts)
req.Header.Set("X-WA-Digest", digest)
resp, _ := http.DefaultClient.Do(req)
// resp.Body contiene la imagen binaria
Respuesta
HTTP/1.1 200 OK Content-Type: image/webp Cache-Control: public, max-age=31536000 [binary image data]
Sube una imagen original al repositorio del cliente. Acepta los formatos jpg, jpeg, png, gif, webp y avif. Tamaño máximo: 50 MB. Al subir un archivo, purga automáticamente todas las versiones cacheadas del mismo.
Nota:
El tamaño máximo se puede cambiar en las cuentas empresariales.
Body
Content-Type: multipart/form-data con el campo file conteniendo el binario de la imagen.
cURL — subir imagen
curl -X POST \
-H "X-WA-Token: {token}" \
-H "X-WA-Timestamp: {unix}" \
-H "X-WA-Digest: {hmac}" \
-F "file=@/local/zapatilla.jpg" \
"https://api.webability.info/v1/image/productos/zapatilla.jpg"
Respuesta JSON
{
"status": "ok",
"path": "productos/zapatilla.jpg",
"filename": "zapatilla.jpg",
"size": 284560,
"cache_purged": 12
}
Permite tres modos de eliminación:
| URL | Efecto |
|---|---|
| /v1/image | Purga toda la caché de versiones procesadas (secondcache). Los originales se conservan. |
| /v1/image/prod/img.jpg | Elimina el original y todas sus versiones cacheadas. |
| /v1/image/carpeta/ | Elimina la carpeta completa de ambas cachés (originales y versiones procesadas). |
cURL — purgar imagen específica
curl -X DELETE \
-H "X-WA-Token: {token}" \
-H "X-WA-Timestamp: {unix}" \
-H "X-WA-Digest: {hmac}" \
"https://api.webability.info/v1/image/productos/zapatilla.jpg"
Respuesta JSON
{
"status": "ok",
"deleted_firstcache": 1,
"deleted_secondcache": 8,
"total": 9
}
Endpoint /v1/stat
Estadísticas de uso del repositorio y la caché del cliente. Solo soporta GET.
Devuelve el total de archivos y tamaño por caché y por formato.
Request
curl -X GET \
-H "X-WA-Token: {token}" \
-H "X-WA-Timestamp: {unix}" \
-H "X-WA-Digest: {hmac}" \
"https://api.webability.info/v1/stat"
Respuesta JSON
{
"status": "ok",
"client": "abcdefghij",
"firstcache": {
"files": 120,
"size_bytes": 48234560,
"size_mb": 46.01,
"by_format": { "jpg": 80, "png": 30, "gif": 10 }
},
"secondcache": {
"files": 850,
"size_bytes": 210345678,
"size_mb": 200.61,
"by_format": { "webp": 600, "avif": 150, "jpg": 100 }
},
"total": {
"files": 970,
"size_bytes": 258580238,
"size_mb": 246.62
}
}
Lista todas las versiones cacheadas de una imagen específica con sus dimensiones, formato y tamaño.
Request
curl -X GET \
-H "X-WA-Token: {token}" \
-H "X-WA-Timestamp: {unix}" \
-H "X-WA-Digest: {hmac}" \
"https://api.webability.info/v1/stat/banners/logo.jpg"
Respuesta JSON
{
"status": "ok",
"image": "banners/logo.jpg",
"original": {
"exists": true,
"size_bytes": 142560
},
"versions": [
{
"filename": "800x600-logo.webp",
"size": 18432,
"width": 800,
"height": 600,
"format": "webp"
},
{
"filename": "400x300-logo.webp",
"size": 9216,
"width": 400,
"height": 300,
"format": "webp"
}
],
"version_count": 2
}
Autenticación
Todos los endpoints de la API autenticada requieren tres headers en cada request. El digest es un HMAC-SHA256 calculado con tu token como clave secreta.
| Header | Valor |
|---|---|
| X-WA-Token | Tu token de cuenta, disponible en la consola de administración. |
| X-WA-Timestamp | Unix timestamp actual en segundos. Debe estar dentro de ±5 minutos del reloj del servidor. |
| X-WA-Digest | HMAC-SHA256 en hexadecimal. Mensaje canónico: {METHOD}|{PATH}|{TIMESTAMP}|{TOKEN}. Clave: tu token. |
Ejemplo de cálculo del digest
Go
import (
"crypto/hmac"
"crypto/sha256"
"fmt"
"time"
)
token := "mi_token_secreto"
method := "GET"
path := "/v1/image/productos/800x600/item.jpg.webp"
ts := fmt.Sprintf("%d", time.Now().Unix())
msg := method + "|" + path + "|" + ts + "|" + token
mac := hmac.New(sha256.New, []byte(token))
mac.Write([]byte(msg))
digest := fmt.Sprintf("%x", mac.Sum(nil))
JavaScript (Node.js)
const crypto = require('crypto');
const token = 'mi_token_secreto';
const method = 'GET';
const path = '/v1/image/productos/800x600/item.jpg.webp';
const ts = Math.floor(Date.now() / 1000).toString();
const msg = `${method}|${path}|${ts}|${token}`;
const digest = crypto
.createHmac('sha256', token)
.update(msg)
.digest('hex');
PHP
$token = 'mi_token_secreto';
$method = 'GET';
$path = '/v1/image/productos/800x600/item.jpg.webp';
$ts = (string) time();
$msg = "$method|$path|$ts|$token";
$digest = hash_hmac('sha256', $msg, $token);
Códigos de error
Los errores de la API devuelven un JSON con status, code y message.
Formato de error
{ "status": "error", "code": 2010, "message": "Imagen original no encontrada" }
| HTTP | Código | Descripción |
|---|---|---|
| 401 | 2001 | Headers de autenticación faltantes o inválidos. |
| 401 | 2002 | Firma HMAC inválida o timestamp fuera de rango (±5 min). |
| 401 | 2003 | Token no encontrado. |
| 400 | 2004 | El cliente no tiene configuración CDN activa. |
| 400 | 2010 | URL inválida (segmentos insuficientes) o imagen original no encontrada en el CDN de origen. |
| 400 | 2011 | Falta la extensión del archivo de salida. |
| 400 | 2012 | Formato de dimensiones inválido. Se espera WxH, p. ej. 800x600. |
| 400 | 2013 | Formato de salida no soportado. Usa webp, avif o jpg. |
| 400 | 2020 | Subida: falta el campo file en el formulario multipart. |
| 400 | 2021 | Subida: formato de archivo no permitido. |
| 403 | 2022 | Subida: path traversal detectado. |
| 400 | 2023 | Subida: error al guardar el archivo en el servidor. |
| 403 | 2030 | Eliminación: path traversal detectado. |
| 400 | 2031 | Eliminación: error durante la operación de borrado. |