CMS y webs
Sube a Etsy las imágenes del listing con la API v3
Genera los formatos con SocialCutter y súbelos al listing por la API v3 de Etsy en multipart: requisitos de tamaño y formato, OAuth, jpg o png y errores.
- Etsy
- API v3
- listing images
- listings_w
- multipart
- Bearer
- jpg
Por qué generar las proporciones antes de subir
Etsy recorta tus fotos para sus propias vistas: la miniatura cuadrada, la vertical y la apaisada. Su página de requisitos lo dice sin rodeos: conviene que la imagen tenga margen suficiente para poder recortarse a cuadrado, vertical y horizontal sin perder producto, y que el motivo importante esté en el centro.
Si subes un solo maestro, el recorte lo decide Etsy y tú no ves el resultado hasta después. Si generas antes la proporción exacta del hueco al que va la imagen, el fichero ya encaja y el recorte no tiene nada que quitar. El recorte de SocialCutter es centrado: escala y recorta el exceso por igual a los dos lados, sin analizar el contenido de la imagen.
| Hueco en el listing | Destino SocialCutter | Medida generada |
|---|---|---|
| Vista cuadrada, foto principal en 1:1 | instagram post | 1080x1080 (1:1) |
| Foto secundaria apaisada | twitter post | 1200x675 (16:9) |
| Banda ancha para una cabecera o una ficha | linkedin post | 1200x627 (1.91:1) |
| Vertical para un vídeo corto del listing | instagram story | 1080x1920 (9:16) |
| Imagen muy ancha, tipo banner | youtube banner | 2560x1440 (16:9) |
Dos avisos honestos sobre las medidas:
- No hay 4:5 en el catálogo. Las verticales son 9:16 (1080x1920) y la cuadrada es 1:1 (1080x1080). Si necesitas exactamente 4:5, tendrás que recortarla fuera de SocialCutter.
- La medida la fija el destino y no se amplía. Si Etsy recomienda 2000 píxeles de ancho y alto, el cuadrado del catálogo (1080x1080) se queda por debajo de esa recomendación aunque supere con holgura el mínimo de 635 píxeles de la primera foto. Cuando el zoom a 2000 píxeles sea un requisito, sube la foto principal a resolución completa y usa SocialCutter para las medidas del resto de canales y para las fotos secundarias.
Requisitos de imagen de Etsy
Lo que publica su centro de ayuda:
| Criterio | Qué pide Etsy |
|---|---|
| Formatos aceptados | .jpg, .gif, .png, .svg y .heic |
| Formatos no soportados | GIF animado y PNG con transparencia; las zonas transparentes se ven negras |
| Tamaño recomendado del listing | Ancho y alto de al menos 2000 píxeles |
| Primera foto | Al menos 635 píxeles de ancho y de alto, o el listing baja posiciones en las búsquedas |
| Peso del fichero | Por encima de 1 MB la subida puede no completarse, sobre todo con mala conexión |
| Perfil de color | Etsy convierte a sRGB: parte de sRGB para no llevarte sorpresas |
| Primera foto | Horizontal (apaisada) o cuadrada |
| Vistas | Etsy recorta a cuadrado, vertical y horizontal, así que la imagen necesita margen |
La consecuencia práctica para el flujo es directa: pide JPG o PNG, no WebP. Etsy no lista WebP entre los formatos que acepta, y la salida por defecto de SocialCutter es WebP. En la misma petición se fija el formato y la calidad:
{
"source": { "type": "url", "value": "https://tu-cdn.com/maestro.jpg" },
"destinations": [ { "platform": "instagram", "format": "post" } ],
"options": { "fit_mode": "cover", "format": "jpg", "quality": 88 }
}
quality va de 1 a 100 y por defecto es 85. Bajarla es la palanca más rápida para quedarte por debajo del megabyte que Etsy considera seguro; en una foto de producto, un JPG a 85-90 suele pesar bastante menos de 1 MB sin que se note.
La subida por la API v3
POST https://openapi.etsy.com/v3/application/shops/{shop_id}/listings/{listing_id}/images
- Cuerpo:
multipart/form-data, con el fichero en el campoimage. - Campos opcionales:
rank: posición en el listing; la 1 es la que aparece más a la izquierda. Por defecto 1.overwrite: entrue, reemplaza la imagen que ya ocupa eserank. Por defectofalse.alt_text: texto alternativo, máximo 500 caracteres.listing_image_id: reasigna una imagen ya borrada en lugar de subir una nueva.is_watermarked: marca de agua, por defectofalse.
- Autenticación: dos cosas a la vez. La cabecera
x-api-keycon el formatokeystring:shared_secrety la cabeceraAuthorization: Bearer <token>. - Permiso: el token OAuth necesita el scope
listings_w. - Respuesta:
201con un objeto de imagen del listing que traelisting_image_id,rank,alt_text,full_width,full_heightyurl_fullxfull(hasta 3000 píxeles por lado).
Si mandas image y listing_image_id en la misma petición, la API sube la del campo image e ignora el identificador.
Lee con atención la nota de la referencia: al subir una imagen nueva, los datos calculados (colores, medidas) pueden volver a null porque Etsy la procesa de forma asíncrona. Hay que consultarlos después con el endpoint de consulta de la imagen del listing.
OAuth de Etsy
- Autorización:
https://www.etsy.com/oauth/connect. - Token:
https://openapi.etsy.com/v3/public/oauth/token. - Base de la API:
https://openapi.etsy.com, con las rutas bajo/v3/application/.
El token caduca y hay que renovarlo; el refresh_token del flujo de código de autorización es lo que permite hacerlo sin volver a pasar por la pantalla de consentimiento. Guarda el keystring, el shared secret y el token en variables de entorno, nunca en el código.
Snippet completo en Python
import json, os, requests
API = "https://api.socialcutter.theboomer.dev"
ETSY = "https://openapi.etsy.com/v3/application"
SHOP_ID = os.environ["ETSY_SHOP_ID"]
LISTING_ID = os.environ["ETSY_LISTING_ID"]
sc = requests.Session()
sc.headers["X-API-Key"] = os.environ["SOCIALCUTTER_API_KEY"]
etsy = requests.Session()
etsy.headers["x-api-key"] = os.environ["ETSY_API_KEY"] # keystring:shared_secret
etsy.headers["Authorization"] = f"Bearer {os.environ['ETSY_ACCESS_TOKEN']}"
# 1. Formatos en jpg: WebP no está entre los que acepta Etsy
r = sc.post(f"{API}/api/v1/images/process", json={
"source": {"type": "url", "value": "https://tu-cdn.com/maestro.jpg"},
"destinations": [
{"platform": "instagram", "format": "post"}, # 1080x1080 (1:1)
{"platform": "twitter", "format": "post"}, # 1200x675 (16:9)
],
"options": {"fit_mode": "cover", "format": "jpg", "quality": 88},
}, timeout=120)
r.raise_for_status()
# 2. Subir cada salida al listing con su rank
for puesto, salida in enumerate(r.json()["outputs"], start=1):
img = sc.get(salida["url"], timeout=120)
img.raise_for_status()
nombre = f"{salida['platform']}-{salida['format']}.jpg"
up = etsy.post(
f"{ETSY}/shops/{SHOP_ID}/listings/{LISTING_ID}/images",
files={"image": (nombre, img.content, "image/jpeg")},
data={
"rank": puesto,
"overwrite": "true",
"alt_text": "Camiseta de algodón, vista frontal",
},
timeout=120,
)
up.raise_for_status()
datos = up.json()
print(datos["listing_image_id"], datos["rank"], datos["url_fullxfull"])
Snippet con curl
# 1. Generar los formatos en jpg
curl -s -X POST "https://api.socialcutter.theboomer.dev/api/v1/images/process" \
-H "X-API-Key: $SOCIALCUTTER_API_KEY" \
-H "Content-Type: application/json" \
--data '{"source":{"type":"url","value":"https://tu-cdn.com/maestro.jpg"},
"destinations":[{"platform":"instagram","format":"post"}],
"options":{"fit_mode":"cover","format":"jpg","quality":88}}' \
> salida.json
curl -s "$(jq -r '.outputs[0].url' salida.json)" -o listing-1.jpg
# 2. Subirla al listing en multipart
curl -s -X POST \
"https://openapi.etsy.com/v3/application/shops/$ETSY_SHOP_ID/listings/$ETSY_LISTING_ID/images" \
-H "x-api-key: $ETSY_API_KEY" \
-H "Authorization: Bearer $ETSY_ACCESS_TOKEN" \
-F "[email protected];type=image/jpeg" \
-F "rank=1" \
-F "overwrite=true" \
-F "alt_text=Camiseta de algodón, vista frontal" \
| jq '{listing_image_id, rank, url_fullxfull}'
Para llenar varias posiciones, repite la segunda llamada cambiando rank (2, 3, 4…) y el fichero. El campo overwrite solo hace falta cuando quieres sustituir lo que ya está en esa posición.
Coste
- 1 uso por destino (plataforma y formato) por petición a SocialCutter. Destinos repetidos no se cobran dos veces y los procesamientos fallidos se devuelven.
- Planes: 0 EUR (3 usos/día), 3 EUR (10/día), 9 EUR (30/día) y 29 EUR (100/día), todos con API y servidor MCP incluidos.
- La API de Etsy no se cobra por llamada; aplica sus propios límites de uso, así que espacia las subidas si vas a llenar muchas posiciones seguidas.
Errores típicos
| Código | Origen | Qué pasa | Qué hacer |
|---|---|---|---|
| 400 | Etsy | Problema con los datos de la petición | Revisar el multipart y los campos enviados |
| 401 | Etsy | Faltan las credenciales o el token no vale | Comprobar x-api-key y el Authorization Bearer |
| 403 | Etsy | La operación no está permitida para ese token | Añadir el scope listings_w y volver a autorizar |
| 404 | Etsy | No encuentra el recurso | Revisar shop_id y listing_id |
| 409 | Etsy | Conflicto con el estado actual del listing | Releer las posiciones antes de reescribir |
| 500 | Etsy | Error interno de Etsy | Reintentar con espera; la imagen no se ha creado |
| La subida no termina | Etsy | El fichero pasa de 1 MB, sobre todo con conexión lenta | Bajar options.quality y volver a generar el JPG |
| 401 | SocialCutter | Falta o no vale la cabecera X-API-Key | Comprobar que el valor empieza por sc_ y sigue activo |
| 413 | SocialCutter | El maestro supera 5 MB | Reducir la imagen antes de la llamada |
| 429 | SocialCutter | Cuota del monedero agotada | Consultar GET /api/v1/wallet |
Lo que SocialCutter no hace
El recorte es centrado y determinista: no analiza el contenido de la imagen para decidir qué conservar, no edita la foto (no retoca color, no quita fondos, no compone texto), no publica en redes sociales ni en Etsy, y no acepta ficheros de más de 5 MB. Genera las versiones con la medida exacta de cada destino y devuelve sus URLs: subirlas al listing es cosa de tu script.
Siguientes pasos
- Otras tiendas: Integra SocialCutter con la API de Shopify, WooCommerce y BigCommerce
- Medidas: Medidas de redes sociales: tamaños y proporciones
- Formatos: PNG, JPG o WebP: qué formato usar en cada red
- Código: Automatiza SocialCutter con Python y desde la terminal con curl
- Documentación de la API de SocialCutter: https://docs.socialcutter.theboomer.dev
- Referencia de la API v3 de Etsy: https://developer.etsy.com/documentation/reference/
- Requisitos de imagen de Etsy: https://help.etsy.com/hc/en-us/articles/115015663347
Preguntas frecuentes
¿Qué formatos de fichero acepta Etsy?
Su página de requisitos lista .jpg, .gif, .png, .svg y .heic. WebP no está en esa lista, así que la salida por defecto de SocialCutter (webp) no vale aquí: pide options.format con jpg o png en la misma petición.
¿Qué tamaño pide Etsy para la foto de un listing?
Etsy recomienda un ancho y un alto de al menos 2000 píxeles, y pide que la primera foto tenga como mínimo 635 píxeles de ancho y de alto para no perder posiciones en las búsquedas. El catálogo de SocialCutter fija la medida de cada destino y no amplía, así que la medida sale de la lista de destinos y no al revés.
¿Por qué me devuelve null el color o el tamaño de la imagen recién subida?
Porque Etsy procesa la imagen de forma asíncrona. La propia referencia de la API avisa de que campos como los colores o el tamaño pueden llegar a null en la respuesta de subida; se leen después con el endpoint de consulta de la imagen del listing.
¿Cómo sustituyo una foto que ya está en una posición del listing?
Con rank para indicar la posición y overwrite en true, que reemplaza la imagen que ya ocupa ese puesto. Si no lo pones, Etsy añade una imagen nueva y la respuesta no sustituye nada.
¿Cuánto cuesta preparar los formatos de un listing?
1 uso por destino, es decir por cada pareja de plataforma y formato. Dos medidas para el mismo listing son 2 usos. Los planes incluyen la API y el servidor MCP.