# Sube imágenes a Webflow y usa SocialCutter
> Sube el maestro a los Assets de Webflow con la API v2, llamalo con SocialCutter y usa las salidas correctas en el CMS Collection o en la pagina.
- URL: https://socialcutter.theboomer.dev/guias/webflow/
- Idioma: es
- Familia: cms
- Actualizado: 2026-09-24
- Palabras clave: Webflow, API v2, Assets, CMS Collection, SocialCutter, feature image, imagenes
## El problema: un maestro, muchas medidas

Webflow te deja subir una imagen y colocarla en un CMS Collection o en el campo de imagen de una página. Lo que no hace por ti es generar la misma imagen en las medidas que pide cada red: 1200x630 para la tarjeta de Facebook, 1080x1920 para TikTok, 1200x675 para X. Si subes un solo JPG y lo reutilizas, acabas con recortes forzados o con el objeto cortado.

El flujo de esta guía sube **un solo maestro** a los Assets de Webflow, lo procesa con SocialCutter y usa cada salida en su sitio. Un origen, todas las medidas correctas.

## Requisitos y token de sitio

Necesitas la **Webflow Data API v2** (base `https://api.webflow.com/v2`) y un token de sitio. Créalo en **Site settings → Apps & integrations → API access** y activa los scopes que usaremos:

| Scope | Para qué |
|---|---|
| `assets:read` / `assets:write` | Crear y leer Assets |
| `cms:read` / `cms:write` | Leer y escribir items de la colección |
| `sites:read` / `sites:write` | Resolver el `site_id` y publicar el sitio |

Los nombres exactos de los scopes se ven en la pantalla de creación del token y pueden variar entre versiones. La referencia oficial está en https://developers.webflow.com/data/reference. La API v2 sustituye a la v1 antigua: si encuentras ejemplos con `/sites/{site_id}/assets` sin el prefijo `/v2`, son de la versión retirada.

Guarda el token y el `site_id` en variables:

```bash
export WEBFLOW_TOKEN="tu_token_de_sitio"
export SITE_ID="tu_site_id"
export API_URL="https://api.socialcutter.theboomer.dev"
export API_KEY="sc_tu_clave"
```

## 1. Subir el maestro a los Assets

La subida en la API v2 es en dos pasos, tal como describe la referencia oficial (*Upload Asset*): primero se crea el registro del asset y la API devuelve una URL de subida con los detalles del formulario; después se envía el fichero en multipart a esa URL.

`POST https://api.webflow.com/v2/sites/{site_id}/assets` · scope `assets:write`

| Campo | Obligatorio | Qué es |
|---|---|---|
| `fileName` | Sí | Nombre con extensión; menos de 100 caracteres |
| `fileHash` | Sí | MD5 del contenido del fichero |
| `parentFolder` | No | ID de la carpeta de Assets donde queda el fichero |

### Crear el asset

```bash
curl -s -X POST "https://api.webflow.com/v2/sites/$SITE_ID/assets" \
  -H "Authorization: Bearer $WEBFLOW_TOKEN" \
  -H "accept-version: 2.0.0" \
  -H "Content-Type: application/json" \
  -d '{
    "fileName": "maestro.jpg",
    "fileHash": "hash_md5_del_fichero",
    "parentFolder": "id_de_la_carpeta"
  }' > asset.json

jq '{id, contentType, uploadUrl, assetUrl, hostedUrl, parentFolder}' asset.json
```

La respuesta 200 trae, entre otros, estos campos:

| Campo | Qué es |
|---|---|
| `id` | Identificador del asset; el que usarás después para leerlo o cambiar su texto alternativo |
| `uploadUrl` | URL temporal **prefirmada de Amazon S3** a la que se envía el binario |
| `uploadDetails` | Metadatos para subir el binario: los campos del formulario que hay que mandar junto al fichero |
| `assetUrl` | Enlace del asset en S3 |
| `hostedUrl` | Enlace del asset, el que se usa para referenciarlo |
| `parentFolder` | Carpeta destino del asset |
| `contentType`, `originalFileName`, `createdOn`, `lastUpdated` | Tipo, nombre original y fechas |

La documentación lo dice explícito: hay que usar `uploadUrl` y `uploadDetails` en la petición POST a S3 para completar la subida. Esa URL la emite **Webflow**; SocialCutter no aloja tu fichero.

El `fileHash` es el MD5 del contenido del fichero: se calcula con `md5sum maestro.jpg` (en macOS, `md5 -q maestro.jpg`). Webflow lo usa para **evitar duplicados**: si el hash coincide con el de un fichero que ya existe, no lo guarda otra vez. Si no coincide, la subida falla con `400`. `parentFolder` es el ID de la carpeta de Assets y es opcional.

### Crear la carpeta destino (opcional)

Si quieres que los assets no caigan en la raíz del panel, crea antes la carpeta:

```bash
curl -s -X POST "https://api.webflow.com/v2/sites/$SITE_ID/asset_folders" \
  -H "Authorization: Bearer $WEBFLOW_TOKEN" \
  -H "accept-version: 2.0.0" \
  -H "Content-Type: application/json" \
  -d '{ "displayName": "SocialCutter" }' > folder.json

jq '{id, displayName, parentFolder}' folder.json
```

El endpoint es `POST /v2/sites/{site_id}/asset_folders` (scope `assets:write`) y acepta `displayName` (obligatorio) y `parentFolder` (opcional, para anidar carpetas). Guarda el `id` que devuelve y pásalo como `parentFolder` al crear el asset.

### Subir el fichero

Los campos de `uploadDetails` hay que enviarlos tal cual, junto al fichero, a la `uploadUrl`:

```bash
UPLOAD_URL=$(jq -r '.uploadUrl' asset.json)
jq -r '.uploadDetails | to_entries[] | "\(.key)=\(.value)"' asset.json > fields.txt

curl -s -X POST "$UPLOAD_URL" \
  $(while IFS= read -r line; do printf -- "-F %s " "$line"; done < fields.txt) \
  -F "file=@./maestro.jpg" > upload.json
```

No inventes los nombres de los campos: vienen en `uploadDetails` y cambian según el tipo de asset. Envía exactamente los que devuelva la API.

Límite de tamaño: las imágenes de Webflow no pueden superar **4 MB** (los documentos, 10 MB), según la guía *Working with Assets*. El maestro que acepta SocialCutter llega a 5 MB, así que un maestro grande puede no entrar directamente en los Assets: genéralo antes con SocialCutter, que devuelve salidas mucho más ligeras, o redúcelo.

### Comprobar que el asset ha quedado bien

`GET https://api.webflow.com/v2/assets/{asset_id}` (scope `assets:read`) devuelve el detalle del asset ya subido:

```bash
curl -s "https://api.webflow.com/v2/assets/$ASSET_ID" \
  -H "Authorization: Bearer $WEBFLOW_TOKEN" \
  -H "accept-version: 2.0.0" \
  | jq '{id, hostedUrl, contentType, size, originalFileName, altText}'
```

Los campos que sirven para verificar: `hostedUrl` (el enlace real, el que pasarás a SocialCutter), `contentType` (tipo de fichero), `size` (tamaño en bytes), `originalFileName`, `altText` y `variants` (las variantes responsive que genera Webflow para servir la imagen). Si `hostedUrl` no carga al abrirlo, la subida a `uploadUrl` no se completó: repite el POST con los campos de `uploadDetails` y el fichero.

El mismo detalle se puede listar por carpeta. Ojo: el campo `folderId` solo aparece en las respuestas de listado, no al consultar un asset suelto. El listado acepta `folderId` (ObjectId hexadecimal de 24 caracteres) y paginación con `limit` (máximo 100) y `offset`:

```bash
curl -s "https://api.webflow.com/v2/sites/$SITE_ID/assets?folderId=$FOLDER_ID&limit=100" \
  -H "Authorization: Bearer $WEBFLOW_TOKEN" \
  -H "accept-version: 2.0.0" \
  | jq '.assets[] | {id, hostedUrl, size, folderId, altText}'
```

El texto alternativo y el nombre visible se cambian con `PATCH https://api.webflow.com/v2/assets/{asset_id}` (scope `assets:write`), enviando `altText` y/o `displayName`.

## 2. Llamar a SocialCutter con la URL del asset

Cuando el maestro está en los Assets, su `hostedUrl` es el origen para SocialCutter:

```bash
curl -s -X POST "$API_URL/api/v1/images/process" \
  -H "X-API-Key: *** \
  -H "Content-Type: application/json" \
  -d "{
    \"source\": { \"type\": \"url\", \"value\": \"$(jq -r '.hostedUrl' asset.json)\" },
    \"destinations\": [
      { \"platform\": \"facebook\", \"format\": \"link\" },
      { \"platform\": \"instagram\", \"format\": \"post\" },
      { \"platform\": \"twitter\", \"format\": \"summary_large_image\" }
    ]
  }" > sc.json

jq '.image_id, (.outputs[] | {url, platform, format, width, height})' sc.json
```

Cada elemento de `outputs` trae la URL de la salida, su plataforma, su formato y sus medidas. El recorte de `cover` (por defecto) es centrado.

## 3. Publicar el sitio

Los Assets nuevos y los items creados no se ven en el sitio publicado hasta que lo publiques:

```bash
curl -s -X POST "https://api.webflow.com/v2/sites/$SITE_ID/publish" \
  -H "Authorization: Bearer $WEBFLOW_TOKEN" \
  -H "accept-version: 2.0.0" \
  -H "Content-Type: application/json" \
  -d '{ "publishToWebflowSubdomain": true, "customDomains": ["tu-dominio.com"] }'
```

Ajusta `customDomains` a los dominios reales del proyecto.

## 4. Usar las salidas en el CMS Collection

Si el CMS Collection tiene un campo de imagen, hay dos caminos: subir cada salida como Asset (repitiendo el paso 1) y referenciar su `id`, o pasar la URL directamente si tu campo lo admite. Consulta el esquema de la colección antes de construir el item:

```bash
# Lista de colecciones
curl -s "https://api.webflow.com/v2/sites/$SITE_ID/collections" \
  -H "Authorization: Bearer $WEBFLOW_TOKEN" \
  -H "accept-version: 2.0.0" | jq '.collections[] | {id, slug}'

# Esquema de una coleccion (campos y tipos)
curl -s "https://api.webflow.com/v2/collections/$COLLECTION_ID" \
  -H "Authorization: Bearer $WEBFLOW_TOKEN" \
  -H "accept-version: 2.0.0" | jq '.fields[] | {slug, type}'
```

Crea el item en vivo con el valor del campo de imagen tomado de `outputs[0].url`:

```bash
curl -s -X POST "https://api.webflow.com/v2/collections/$COLLECTION_ID/items/live" \
  -H "Authorization: Bearer $WEBFLOW_TOKEN" \
  -H "accept-version: 2.0.0" \
  -H "Content-Type: application/json" \
  -d "{
    \"fieldData\": {
      \"name\": \"Entrada de ejemplo\",
      \"slug\": \"entrada-de-ejemplo\",
      \"imagen\": \"$(jq -r '.outputs[0].url' sc.json)\"
    }
  }"
```

El nombre real del campo de imagen es el `slug` que devuelve el esquema, no tiene por qué llamarse `imagen`.

## 5. Usar las salidas como imágenes de página

Para una imagen suelta en una página, sube la salida a los Assets y usa su URL en el HTML. En la práctica, el patrón más limpio es: subir el maestro, procesar con SocialCutter y subir cada salida una vez, guardando su `hostedUrl` para referenciarla desde el CMS o desde las páginas.

Ahí está la ventaja del orden: el fichero que subes a los Assets ya viene generado por SocialCutter **en la proporción del destino** (1080x1080 para `instagram` `post`, 1200x627 para `linkedin` `post`), con recorte centrado. Webflow solo lo aloja y genera sus variantes responsive, así que el CDN sirve ficheros que ya están en la medida correcta y no versiones recortadas del maestro original.

## Coste

- **1 uso por destino** (combinación de plataforma y formato) por petición.
- Destinos repetidos en la misma petición no se cobran dos veces.
- Los procesamientos fallidos se devuelven.

## Errores típicos

| Situación | Causa probable |
|---|---|
| 401 en Webflow | Token ausente, mal formado o sin el scope necesario (`assets:write` para crear el asset) |
| 400 al crear el asset | `fileHash` no coincide con el MD5 del fichero, o `fileName` supera los 100 caracteres |
| El asset queda vacío o `hostedUrl` no carga | No se completó el POST a `uploadUrl` con los campos de `uploadDetails` |
| La imagen no aparece | Falta publicar el sitio o el item está en borrador |
| 401 en SocialCutter | Clave `sc_` mal formada o revocada |
| 413 en SocialCutter | El maestro supera 5 MB |
| El maestro no sube a Webflow | Supera el límite de 4 MB por imagen de Webflow |
| 429 en SocialCutter | Cuota del monedero agotada |
| Campo de imagen vacío | El `slug` del campo no es el que creías: revisa el esquema |
| Un asset aparece duplicado o no aparece | Webflow usa el `fileHash` para no repetir ficheros con el mismo MD5 |

## Siguientes pasos

- Guía de WordPress: [Publica las medidas correctas en WordPress](/guias/wordpress/)
- Guía de Shopify: [Imágenes de producto y blog en Shopify](/guias/shopify/)
- Automatización: [Orquesta el flujo con n8n](/guias/n8n/)
- API desde la terminal: [Procesa imágenes con curl](/guias/curl/)
- Referencia oficial de Webflow: https://developers.webflow.com/data/reference