# 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.
- URL: https://socialcutter.theboomer.dev/guias/prestashop/
- Idioma: es
- Familia: cms
- Actualizado: 2026-09-24
- Palabras clave: 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.

```bash
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

```bash
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:

```bash
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
<?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`:

```python
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:

```bash
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](/guias/wordpress/)
- WooCommerce: [Sube imágenes de catálogo a WooCommerce con SocialCutter](/guias/woocommerce/)
- Shopify: [Integra SocialCutter con la Admin API de Shopify](/guias/shopify/)
- Automatización: [Automatiza el recorte de imágenes con n8n](/guias/n8n/)
- Documentación: https://docs.socialcutter.theboomer.dev