IA y agentes
Adjunta en Airtable las medidas generadas con SocialCutter
Genera los formatos con SocialCutter y adjunta la URL de salida a un campo attachment por la API de Airtable: flujo directo, Python, curl y errores.
- Airtable
- attachment
- API
- token personal
- Python
- curl
- SocialCutter
Por qué el flujo es directo en Airtable
Un campo de tipo attachment (multipleAttachments) acepta, al escribir, una lista de objetos con url. Airtable descarga el fichero desde esa URL y se queda con su propia copia. Como SocialCutter devuelve una URL pública por cada formato generado, no hace falta subir binarios ni montar ningún intermediario: generas, adjuntas y ya está.
La frontera sigue siendo la misma que en el resto de integraciones: SocialCutter genera imágenes, no publica. El recorte es centrado, sin detección de sujeto ni análisis de contenido. Publicar o adjuntar es del llamante.
Por qué pre-generar antes de adjuntar
Airtable muestra la miniatura del adjunto, pero no recorta la imagen a la proporción que pide cada hueco. Si guardas un solo maestro y lo reutilizas para la miniatura de la galería, el brief de un reel y la portada del registro, cada vista lo escala a su manera.
| Hueco en el registro | Destino SocialCutter | Medida |
|---|---|---|
| Miniatura cuadrada de la galería | instagram post | 1080x1080 (1:1) |
| Imagen vertical para un brief de reel | instagram story | 1080x1920 (9:16) |
| Tarjeta apaisada o vista de galería | twitter post | 1200x675 (16:9) |
| Portada del registro o de la vista | facebook post | 1200x630 (1.91:1) |
| Banner ancho para una cabecera | linkedin cover | 1128x191 (5.9:1) |
Pre-generar las cinco son 5 usos y sale en una única petición, así que el registro queda completo con las medidas ya resueltas.
Cómo escribe la API en un campo attachment
- Forma de escritura: un array de objetos. Basta
url, yfilenamees opcional pero recomendable para controlar el nombre del adjunto. - Airtable descarga el fichero. La URL tiene que ser alcanzable desde fuera, sin login ni firma caducada, y devolver un
Content-Typede imagen. - Lo que envías es lo que queda. Los adjuntos que no incluyas en el array se eliminan del campo. Para conservarlos, mándalos otra vez con su
id: el objeto que devuelve la lectura sirve tal cual. - Al leer, las URLs son de
v5.airtableusercontent.comy caducan a las dos horas. Son para descargar, no para incrustar en otra web. - Límites del plan: hasta 5 GB por fichero, con un almacenamiento por base que va de 1 GB en Free a 1 TB en Enterprise. La referencia completa está en https://airtable.com/developers/web/api/field-model.
Crea el token personal
Entra en https://airtable.com/create/tokens, añade los permisos data.records:write (y schema.bases:read si quieres listar los campos de la tabla) y da acceso a la base concreta. Se envía en la cabecera Authorization: Bearer pat.... Guarda el token y el identificador de la base en variables de entorno, nunca en el código.
Flujo directo con Python
import os
import requests
SC = "https://api.socialcutter.theboomer.dev"
BASE = os.environ["AIRTABLE_BASE_ID"]
TABLE = os.environ["AIRTABLE_TABLE_ID"]
sc = requests.Session()
sc.headers["X-API-Key"] = os.environ["SOCIALCUTTER_API_KEY"]
at = requests.Session()
at.headers["Authorization"] = f"Bearer {os.environ['AIRTABLE_TOKEN']}"
# 1. Generar todos los formatos de una vez
resp = sc.post(f"{SC}/api/v1/images/process", json={
"source": {"type": "url", "value": "https://example.com/maestro.jpg"},
"destinations": [
{"platform": "instagram", "format": "post"},
{"platform": "instagram", "format": "story"},
{"platform": "twitter", "format": "post"},
],
}, timeout=60)
resp.raise_for_status()
salidas = resp.json()["outputs"]
# 2. Adjuntar las salidas al registro: Airtable descarga y rehospeda
adjuntos = [
{"url": out["url"], "filename": f"{out['platform']}-{out['format']}.webp"}
for out in salidas
]
r = at.patch(f"https://api.airtable.com/v0/{BASE}/{TABLE}/{os.environ['RECORD_ID']}",
json={"fields": {"Adjuntos": adjuntos}}, timeout=60)
r.raise_for_status()
for att in r.json()["fields"]["Adjuntos"]:
print(att["filename"], att["size"], att["type"])
# 3. Alta de un registro nuevo con la imagen cuadrada ya adjunta
nuevo = at.post(f"https://api.airtable.com/v0/{BASE}/{TABLE}", json={
"records": [{"fields": {
"Nombre": "Campana de septiembre",
"Adjuntos": [{"url": salidas[0]["url"], "filename": "instagram-post.webp"}],
}}],
}, timeout=60)
nuevo.raise_for_status()
Los endpoints de lote admiten 10 registros por petición, y conviene espaciarlos para no pasar de 5 peticiones por segundo y base.
Flujo directo con curl
curl -s -X PATCH "https://api.airtable.com/v0/$BASE_ID/$TABLE_ID/$RECORD_ID" \
-H "Authorization: Bearer $AIRTABLE_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"fields\":{\"Adjuntos\":[{\"url\":\"$OUTPUT_URL\",\"filename\":\"instagram-post.webp\"}]}}" \
| python3 -m json.tool
Sustituye $BASE_ID por app..., $TABLE_ID por tbl... y $RECORD_ID por rec.... Para el nombre del campo puedes usar el identificador fld... en lugar del nombre, que es lo más estable si alguien renombra la columna.
Cuando Airtable no puede descargar la URL
Si el campo no se rellena y la respuesta habla de un fallo de subida, casi siempre es que Airtable no ha podido descargar el fichero. Comprueba que la URL es pública, que no depende de una sesión y que devuelve la imagen con su Content-Type. El aviso típico de la interfaz es «Couldn’t upload. Try adding again» y detrás hay un 403 del dominio de subida de Airtable; el soporte lo documenta en https://support.airtable.com/docs/attachment.
Cuando la URL no se puede exponer, queda la subida directa:
curl -s -X POST \
"https://content.airtable.com/v0/$BASE_ID/$RECORD_ID/$FIELD_ID/uploadAttachment" \
-H "Authorization: Bearer $AIRTABLE_TOKEN" \
-H "Content-Type: application/json" \
--data '{"contentType":"image/webp","file":"<base64>","filename":"instagram-post.webp"}'
Ese endpoint acepta hasta 5 MB por fichero, exactamente el mismo techo que el maestro que admite SocialCutter, así que el respaldo cubre el mismo rango que el flujo por URL.
Coste
- 1 uso por destino (plataforma y formato) por petición a SocialCutter. Los 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 MCP.
- La API de Airtable no se cobra por llamada, pero sí cuenta en el límite mensual de tu plan (1.000 llamadas al mes en Free).
Errores típicos
| Código | Origen | Significado |
|---|---|---|
| 400 | SocialCutter | Payload inválido: plataforma o formato desconocido |
| 401 | SocialCutter | Falta la cabecera X-API-Key o la clave no vale |
| 413 | SocialCutter | El maestro supera 5 MB |
| 429 | SocialCutter | Cuota agotada: consulta GET /api/v1/wallet |
| 401 | Airtable | Token ausente, mal formado o sin acceso a esa base |
| 403 | Airtable | Airtable no ha podido descargar la URL del adjunto |
| 404 | Airtable | La base, la tabla o el registro no existen |
| 422 | Airtable | Campo desconocido o valor que no encaja con el tipo attachment |
| 429 | Airtable | Más de 5 peticiones por segundo y base: espera unos 30 segundos |
Siguientes pasos
- Camino con código: Procesa imágenes con la API de SocialCutter desde Python y desde la terminal con curl
- Sin código: Automatiza el recorte de imágenes con n8n, con Zapier y con Make
- Panorama: Automatizar imágenes para redes sociales: los 4 caminos
- Referencia de la API de SocialCutter: https://docs.socialcutter.theboomer.dev
- Campo de tipo attachment en Airtable: https://airtable.com/developers/web/api/field-model
Preguntas frecuentes
¿Airtable guarda la URL o el fichero?
El fichero. Al escribir una URL en un campo de tipo attachment, Airtable la descarga y rehospeda su propia copia, así que la URL de SocialCutter no tiene que seguir viva después de la escritura.
¿Puedo subir el binario directamente en vez de una URL?
Sí, con el endpoint uploadAttachment, que acepta el fichero en base64 hasta 5 MB. Por encima de ese tamaño hay que pasar por una URL pública, que es justo lo que devuelve SocialCutter.
¿Qué límite tiene la API de Airtable?
5 peticiones por segundo y base en todos los planes, con un máximo de 10 registros por petición en los endpoints de lote. Al pasarte responde 429 y conviene esperar unos 30 segundos antes de reintentar.
¿Qué pasa con los adjuntos que ya había en el campo?
Al escribir, la lista que envías es la que queda: los adjuntos que no incluyas se eliminan. Si quieres conservarlos, mándalos también en el mismo array con su id, tal y como te los devolvió la lectura.
¿Cuánto cuesta preparar los formatos de un registro?
1 uso por destino, es decir por cada combinación de plataforma y formato. Los planes son 0, 3, 9 y 29 EUR al mes e incluyen API y MCP.