Saltar al contenido principal
SocialCutter

CMS y webs

Sube imágenes a HubSpot con la Files API

Sube las imágenes que genera SocialCutter al File Manager de HubSpot por la Files API, con multipart o desde una URL, y úsalas en correos, landings y redes.

  • HubSpot
  • Files API
  • File Manager
  • import-from-url
  • scopes
  • SocialCutter
  • email marketing

Por qué pasar por el File Manager

El File Manager de HubSpot es la biblioteca de medios del portal: todo lo que insertas en correos, páginas, landings y posts de blog se sirve desde ahí, a través del CDN de HubSpot. SocialCutter genera versiones recortadas de forma centrada a las medidas exactas de cada destino y devuelve una URL pública por salida; si esas imágenes van a vivir dentro de HubSpot, conviene subirlas al File Manager en lugar de enlazar URLs externas: así las gestionas y las reutilizas.

La frontera importa: SocialCutter genera imágenes, no publica. HubSpot solo almacena y sirve el fichero.

Requisitos: Private app y scopes

Crea una Private app en Configuración → Integraciones → Private apps y marca los scopes del Files API:

ScopePara qué sirve
filesLeer, subir y archivar ficheros y carpetas
files.ui_hidden.readAcceder a ficheros ocultos que no aparecen en el listado público

El token empieza por pat- y viaja en la cabecera Authorization: Bearer pat-…. La referencia completa de la Files API, con los scopes y campos vigentes, está en https://developers.hubspot.com/docs/api-reference/latest/files/guide.

Subir un fichero por multipart

POST /files/v3/files acepta multipart/form-data. Un fichero por petición:

curl -s -X POST "https://api.hubapi.com/files/v3/files" \
  -H "Authorization: Bearer pat-tu_token" \
  -F "file=@instagram-post.jpg" \
  -F "folderPath=/socialcutter" \
  -F 'options={"access":"PUBLIC_INDEXABLE"}'
CampoObligatorioDescripción
fileSíEl binario a subir
folderId o folderPathUno de los dosCarpeta destino; se recomienda no subir a la raíz
fileNameNoNombre final; si se omite se genera del contenido
optionsNoJSON con access y, opcionalmente, ttl (de 1 día a 1 año)

La respuesta 201 trae id, path, url, defaultHostingUrl, access, width, height e isUsableInContent. Guarda el id y la url: son lo que usas después en el editor de correos o en el selector de imágenes.

Subir desde una URL con import-from-url

Cuando SocialCutter ya te devuelve URLs, no hace falta descargar y resubir a mano. HubSpot importa desde una URL de forma asíncrona:

curl -s -X POST "https://api.hubapi.com/files/v3/files/import-from-url/async" \
  -H "Authorization: Bearer pat-tu_token" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://cdn.socialcutter.theboomer.dev/out/twitter-post.jpg",
    "access": "PUBLIC_INDEXABLE",
    "folderPath": "/socialcutter",
    "duplicateValidationStrategy": "REJECT",
    "duplicateValidationScope": "EXACT_FOLDER"
  }'

La respuesta 202 devuelve un id de tarea. Consultas el estado con GET /files/v3/files/import-from-url/async/tasks/{taskId}/status, que responde PENDING, PROCESSING, COMPLETE o CANCELED. Con COMPLETE el fichero ya está en el File Manager.

Aviso de versiones: HubSpot ha ido moviendo el Files API a rutas versionadas (de files/v3 a esquemas como files/2026-09), y los nombres de scope han cambiado entre versiones. Antes de fijar rutas en tu código, confirma la ruta y los scopes vigentes en la documentación oficial enlazada arriba.

Niveles de acceso y dónde se puede usar cada fichero

access¿Se puede insertar en correos, páginas y landings?
PUBLIC_INDEXABLESí, y además se puede indexar en buscadores
PUBLIC_NOT_INDEXABLESí, pero sin indexación
PRIVATENo directamente: requiere URL firmada e isUsableInContent es false
SENSITIVENo: pensado para datos, no para contenido

Si la imagen va a un correo o una landing, usa acceso público. Un fichero privado no se renderiza en el correo porque el cliente de email no puede firmar la URL.

Tabla de tamaños recomendados por HubSpot

Estas son medidas orientativas que HubSpot publica para los sitios donde se usan imágenes dentro del portal. Para las medidas exactas que genera SocialCutter por red social, la referencia es la guía interna de medidas (enlazada abajo).

Ubicación en HubSpotTamaño recomendadoProporción
Imagen dentro de un correo600 px de anchoVariable (el ancho de plantilla manda)
Cabecera de correo600x2003:1
Imagen destacada de blog1200x628~1.91:1
Imagen para compartir en redes (social share)1200x6301.91:1
Miniatura de blog400x4001:1
Hero / ancho completo de landing1920x1080 (≥1200 px de ancho)16:9
Banner del sitio2500x6254:1
Imagen de autor500x5001:1

Fuentes de HubSpot: su guía de medidas para redes (https://blog.hubspot.com/marketing/ultimate-guide-social-media-image-dimensions-infographic) y la de imágenes para web (https://blog.hubspot.com/website/image-size-for-website). Ojo con las diferencias finas: el social share de HubSpot es 1200x630 y su destacada de blog 1200x628; el destino más cercano del catálogo de SocialCutter es facebook + post (1200x630). Si necesitas una medida que no produce el catálogo, recórtala aparte.

Flujo: de SocialCutter al File Manager

  1. Procesa la maestra: POST /api/v1/images/process con source y destinations.
  2. Recorre el array outputs y, por cada URL, lanza un import-from-url/async.
  3. Espera a COMPLETE por tarea y recoge la url final.
  4. Inserta esa URL en el correo, la landing o el post de blog.
import time, requests

HUB = {"Authorization": "Bearer pat-tu_token"}
BASE = "https://api.hubapi.com/files/v3/files/import-from-url/async"

def subir(url, folder="/socialcutter"):
    r = requests.post(BASE, headers={**HUB, "Content-Type": "application/json"},
                      json={"url": url, "access": "PUBLIC_INDEXABLE", "folderPath": folder},
                      timeout=30)
    r.raise_for_status()
    task = r.json()["id"]
    while True:
        s = requests.get(f"{BASE}/tasks/{task}/status", headers=HUB, timeout=30).json()
        if s.get("status") in ("COMPLETE", "CANCELED"):
            return s
        time.sleep(2)

for out in outputs:            # outputs viene de SocialCutter
    print(out["platform"], subir(out["url"]))

Coste

ConceptoValor
Coste por procesamiento1 uso por destino (plataforma y formato)
Destinos repetidos en la misma peticiónNo se cobran dos veces
Subida al File Manager de HubSpotSin coste adicional, dentro de los límites del portal
Planes de SocialCutter0, 3, 9 y 29 EUR, con API y MCP incluidos

Una petición de Instagram post + LinkedIn post + X post consume 3 usos de SocialCutter y produce 3 subidas a HubSpot.

Errores típicos

ErrorQué pasa realmenteQué hacer
401/403 al subirEl token no tiene el scope filesAñade el scope en la Private app y regenera el token
La imagen no se ve en el correoSe subió como PRIVATESube con acceso público (PUBLIC_INDEXABLE o PUBLIC_NOT_INDEXABLE)
400 en el upload por multipartFalta folderId/folderPath o la carpeta no existeCrea la carpeta antes, o usa import-from-url, que puede crearla
429Límite de peticiones del portalAñade reintentos con espera exponencial
Nombre duplicadoYa existe un fichero igual en la carpetaUsa duplicateValidationStrategy: RETURN_EXISTING o overwrite
La URL de destino no importaHubSpot no pudo descargar la imagenComprueba que la URL es pública y accesible sin sesión

Siguientes pasos

Preguntas frecuentes

¿Qué scopes necesita el token de HubSpot?

Para subir ficheros, el scope files. Para leer ficheros ocultos, además files.ui_hidden.read. Se conceden en una Private app del portal y el token empieza por pat-.

¿Puedo subir una imagen directamente desde su URL?

Sí. El endpoint POST /files/v3/files/import-from-url/async descarga la imagen en segundo plano y devuelve una tarea; consultas su estado hasta que ponga COMPLETE. Es la vía natural cuando SocialCutter ya te da una URL pública.

¿Por qué la imagen no se ve en un correo de HubSpot?

Casi siempre porque el fichero se subió con access PRIVATE. Un fichero privado solo se sirve con URL firmada y no es válido para insertarlo en correos o páginas. Para contenido usa acceso público.

¿Cuánto cuesta procesar una imagen con SocialCutter?

1 uso por destino, entendiendo destino como cada combinación de plataforma y formato. HubSpot no cobra por subir al File Manager dentro de los límites del portal.

¿El recorte lo decide HubSpot o SocialCutter?

SocialCutter recorta de forma centrada y determinista antes de subir: no hay detección de sujeto ni de rostros. HubSpot solo almacena y sirve el fichero que le entregas.