CMS y webs
Imágenes de producto en PrestaShop por el Webservice
Genera los tamaños con SocialCutter y súbelos a PrestaShop usando el Webservice de imágenes, asignándolos después al producto.
- PrestaShop
- Webservice
- images/products
- API key
- PHP
- Python
- imágenes de producto
Por qué pre-generar las medidas
La ficha de producto de PrestaShop muestra la misma foto en la parrilla, en el listado de categoría, en el carrito y en las recomendaciones. Cada hueco recorta a su proporción, y lo hace con las reglas del tema.
El flujo es: entra un maestro, SocialCutter devuelve cada medida y PrestaShop recibe la que toca en cada hueco. El recorte de cover, que es el modo por defecto, es centrado: escala la imagen y reparte el recorte por igual a los dos lados. Deja margen en el maestro para no perder encuadre.
| Hueco en la tienda | Destino SocialCutter | Medida |
|---|---|---|
| Imagen principal del producto | instagram post | 1080x1080 (1:1) |
| Segunda imagen vertical | instagram story | 1080x1920 (9:16) |
| Banner de categoría | facebook post | 1200x630 (1.91:1) |
| Cabecera de la tienda | twitter header | 1500x500 (3:1) |
| Anuncio o ficha externa | facebook story | 1080x1920 (9:16) |
Las medidas salen de GET /api/v1/platforms, que es público. No hay 4:5 en el catálogo: lo cuadrado es 1:1 y lo vertical es 9:16.
Versiones y permisos
Versiones. El Webservice existe en 1.7 y en 8, pero no es idéntico. Cambian campos, algunos recursos y sobre todo la autenticación. Trabaja con la documentación de tu versión:
- PrestaShop 1.7: https://devdocs.prestashop-project.org/1.7/webservice/
- PrestaShop 8: https://devdocs.prestashop-project.org/8/webservice/
Comprueba siempre con una lectura antes de escribir: GET /api/products/12?output_format=JSON debe devolver el producto. El formato por defecto es XML; output_format=JSON devuelve JSON en las versiones que lo soportan, y ?schema=blank describe el esquema de un recurso.
Permisos. La clave se crea en Parámetros avanzados → Webservice. Los permisos son por recurso y por verbo:
| Recurso | Verbos | Para qué |
|---|---|---|
images | GET, POST, DELETE | Subir y listar las imágenes del producto |
products | GET, PUT | Asociar la imagen y leer la ficha |
image_types | GET | Consultar los tipos de imagen del tema |
Si un verbo no está marcado, la llamada falla con un error de autorización aunque la clave sea correcta.
Autenticación. La documentación actual usa la cabecera Authorization con autenticación básica: la clave como usuario y contraseña vacía. Muchas instalaciones siguen aceptando la clave dentro de la URL (https://CLAVE@tienda.com/api/...) o el parámetro ws_key. La clave en la URL acaba en los registros del servidor, así que prefiere la cabecera. curl -u "$PS_KEY:" construye esa cabecera por ti.
export PS_URL="https://tu-tienda.com"
export PS_KEY="CLAVE_DEL_WEBSERVICE"
export SC_KEY="sc_tu_clave"
1. Genera los tamaños con SocialCutter
curl -s -X POST "https://api.socialcutter.theboomer.dev/api/v1/images/process" \
-H "X-API-Key: $SC_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: producto-12-catalogo" \
-d '{
"source": { "type": "url", "value": "https://tu-cdn.com/maestro.jpg" },
"destinations": [
{ "platform": "instagram", "format": "post" },
{ "platform": "instagram", "format": "story" }
]
}' > sc.json
jq '.image_id, (.outputs[] | {url, platform, format, width, height})' sc.json
Cada salida es una URL pública. Idempotency-Key hace seguros los reintentos. Con un maestro local usa POST /api/v1/images/process/upload (multipart, campo file, máximo 5 MB) y para volúmenes grandes POST /api/v1/images/batch.
2. Sube la imagen al producto
El recurso de imágenes recibe el fichero en una petición multipart a POST /api/images/products/<id>. Descarga la salida de SocialCutter y súbela con la clave en la autenticación básica:
curl -s -o cuadrado.jpg "$(jq -r '.outputs[0].url' sc.json)"
# -u con la clave y contraseña vacía genera la cabecera Authorization
curl -s -o /dev/null -w "%{http_code}\n" -X POST \
-u "$PS_KEY:" \
-F "image=@cuadrado.jpg;type=image/jpeg" \
"$PS_URL/api/images/products/12"
Equivale en PHP, con CURLFile para forzar el envío como fichero:
<?php
function ps_subir_imagen( string $base, string $key, int $producto_id, string $ruta ): int {
$ch = curl_init( $base . '/api/images/products/' . $producto_id );
curl_setopt_array( $ch, array(
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_USERPWD => $key . ':',
CURLOPT_POSTFIELDS => array(
'image' => new CURLFile( $ruta, mime_content_type( $ruta ), basename( $ruta ) ),
),
CURLOPT_TIMEOUT => 60,
) );
$cuerpo = curl_exec( $ch );
$codigo = curl_getinfo( $ch, CURLINFO_HTTP_CODE );
curl_close( $ch );
if ( $codigo >= 300 ) {
throw new RuntimeException( 'PrestaShop devolvio HTTP ' . $codigo . ': ' . $cuerpo );
}
return $codigo;
}
Y en Python, con requests:
import requests
with open("cuadrado.jpg", "rb") as fichero:
respuesta = requests.post(
f"{BASE}/api/images/products/12",
auth=(KEY, ""),
files={"image": ("cuadrado.jpg", fichero, "image/jpeg")},
timeout=60,
)
respuesta.raise_for_status()
print(respuesta.status_code)
El nombre del campo y el tratamiento del multipart varían entre versiones: si recibes un 400, revisa el ejemplo de subida de tu versión antes de cambiar el código.
3. Comprueba y asocia
Lista lo que hay colgado del producto:
curl -s -u "$PS_KEY:" "$PS_URL/api/images/products/12?output_format=JSON" | jq '.image[]?.id'
Si tu versión no asocia la imagen sola, añade su id al nodo associations > images del XML del producto y guarda el producto completo con un PUT a /api/products/<id>. PrestaShop reemplaza el recurso entero en cada PUT, así que envía el XML completo que devuelve el GET, no un fragmento.
Para ver qué medidas genera el tema, consulta GET /api/image_types: los clásicos son small_default, medium_default, large_default, home_default y cart_default, y en 1.7 y 8 la lista depende del tema. La regeneración se lanza desde el panel (Diseño → Imágenes en 1.7, Design → Image Settings en 8) y no hay endpoint de Webservice documentado para dispararla: para medidas exactas o lotes grandes, pre-generar con SocialCutter ahorra una regeneración completa del catálogo.
Coste
- 1 uso por destino (plataforma y formato) por petición; los destinos repetidos no se cobran dos veces.
- Los procesamientos fallidos se devuelven.
- Todos los planes incluyen API y MCP: Free 3 usos/día, Basic 10, Pro 30, Agency 100.
Errores típicos
| Síntoma | Causa | Solución |
|---|---|---|
401 en cualquier llamada | Clave mal copiada, Webservice desactivado o IP no permitida | Revisa Parámetros avanzados → Webservice y la lista de IPs de la clave |
401 con la clave dentro de la URL | Tu versión ya exige la cabecera Authorization | Usa -u "$PS_KEY:" o auth=(KEY, "") |
403 al subir | El recurso images no tiene POST marcado en la clave | Añade el permiso y vuelve a guardar la clave |
400 al subir | Falta el campo del fichero o el MIME no es de imagen | Envía image como multipart y con type=image/jpeg |
| La imagen sube pero no se ve | No está asociada al producto, o las miniaturas no se han regenerado | Asocia el id en associations y regenera desde el panel |
XML rechazado en el PUT | Enviaste un fragmento en lugar del recurso completo | Haz GET del producto y modifica ese XML |
429 en SocialCutter | Cuota del monedero agotada | Consulta GET /api/v1/wallet o sube de plan |
Siguientes pasos
- WordPress: Integra SocialCutter con WordPress y WooCommerce
- WooCommerce: Sube imágenes de catálogo a WooCommerce con SocialCutter
- Shopify: Integra SocialCutter con la Admin API de Shopify
- Automatización: Automatiza el recorte de imágenes con n8n
- Documentación: https://docs.socialcutter.theboomer.dev
Preguntas frecuentes
¿La API key va en la URL o en una cabecera?
Depende de la versión. Las instalaciones antiguas aceptan la clave dentro de la URL (https://CLAVE@tienda.com/api/...) o como parámetro ws_key; la documentación actual recomienda la cabecera Authorization con autenticación básica, usando la clave como usuario y contraseña vacía. Comprueba cuál acepta tu versión.
¿Qué permisos necesita la clave del Webservice?
Por recurso y por verbo. Como mínimo images con GET y POST (y DELETE si vas a limpiar), products con GET y PUT si vas a asociar la imagen al producto, e image_types con GET para consultar los tipos disponibles.
¿Funciona igual en PrestaShop 1.7 y en 8?
El esquema de recursos es parecido, pero no idéntico: cambian campos, algunos recursos y la forma de autenticarse. Usa la documentación de la versión que tengas instalada, no la de otra.
¿Tengo que regenerar las miniaturas después?
La regeneración de miniaturas se lanza desde el panel de administración, en la configuración de imágenes del tema. Si subes con SocialCutter las medidas exactas que necesitas, dejas de depender de esa regeneración.
¿Cuánto cuesta procesar un producto?
1 uso por destino, es decir por cada par de plataforma y formato. Dos destinos desde el mismo maestro son 2 usos; repetir un destino en la misma petición no se cobra dos veces.