Genera banners desde tu código, tu asistente o tu diseño.
Una API REST, webhooks firmados, un servidor MCP para Claude y SDK. Cada petición crea un concepto en todos los tamaños e idiomas que pidas, y se cobra una sola vez, según esos tamaños e idiomas.
- OpenAPI 3.1
- Claves de prueba sin créditos
- Idempotency-Key
- CORS abierto
curl -X POST https://app.bannermotion.com/api/v1/banners \
-H "Authorization: Bearer bm_live_..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 7f3c9a10-5b2e-4c1d-9a77-0e1f2a3b4c5d" \
-d '{
"prompt": "Banner para un café de altura, tono cálido",
"sizes": ["300x250", "728x90"],
"locales": ["es-CR", "en-US"]
}'{
"jobId": "job_x4k2m9q1a7bz",
"status": "queued",
"campaignId": "cmp_8f2a1c3d4e5f",
"statusUrl": "/api/v1/jobs/job_x4k2m9q1a7bz",
"eventsUrl": "/api/v1/jobs/job_x4k2m9q1a7bz/events"
}Dirección base: https://app.bannermotion.com [ … ] confirmar dominio definitivo
Cuatro maneras de conectar BannerMotion.
API REST v1
JSON sobre HTTPS bajo /api/v1: crea conceptos, corrígelos, agrega tamaños e idiomas, exporta y descarga el .zip.
Ver la APIWebhooks
Recibe un POST firmado cuando termina una generación, se aprueba una revisión o una exportación queda lista.
Ver los webhooksServidor MCP
Conecta Claude, Cursor o ChatGPT: generan, corrigen, previsualizan y exportan con los permisos y créditos de tu workspace.
Conectar ClaudeSDK
Clientes mínimos de TypeScript y Python, con reintentos, idempotencia automática y verificación de webhooks.
Ver los SDKDel brief al .zip en cuatro pasos.
Crear, corregir, agregar tamaños o idiomas y exportar responden con un trabajo. Lo consultas, lo sigues en vivo con SSE o esperas el webhook.
- Crear
POST /api/v1/bannersResponde 202 con un trabajo. Envía
Idempotency-Keypara reintentar sin cobrar dos veces. - Esperar
GET /api/v1/jobs/:idConsulta el estado, o síguelo en vivo con SSE en
/events. También llega el webhookbanner.generated. - Leer
GET /api/v1/banners/:idDevuelve el spec, la versión, las piezas (tamaño por idioma) y los textos, más el enlace al estudio (
appUrl). - Exportar
POST /api/v1/exportsArma el paquete para la plataforma y descarga el .zip; verifica el encabezado
X-Content-SHA256.
curl -X POST https://app.bannermotion.com/api/v1/banners \
-H "Authorization: Bearer bm_live_..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 7f3c9a10-5b2e-4c1d-9a77-0e1f2a3b4c5d" \
-d '{
"prompt": "Banner para un café de altura, tono cálido",
"sizes": ["300x250", "728x90"],
"locales": ["es-CR", "en-US"]
}'Todas las rutas
Permiso mínimo de la clave en cada ruta. Las claves con generate, export o assets también pueden leer.
Banners
Trabajos
Campañas
Exportaciones
X-Content-SHA256).Biblioteca
Créditos
Ver la referencia completa · https://app.bannermotion.com/api/v1/openapi.json · https://app.bannermotion.com/api/v1/llms.txt
Pruébalo sin gastar créditos.
Crea las claves en Integraciones y API, dentro de tu workspace (solo el Propietario y las personas Admin). El valor se muestra una sola vez. Úsalas solo desde tu servidor.
Producción
Claves bm_live_…. Generan de verdad y gastan los créditos del workspace. Si el trabajo falla, los créditos se devuelven.
Pruebas
Claves bm_test_…. Devuelven siempre el mismo concepto de muestra, sin IA ni créditos. Los ids de prueba (job_test_…, crt_test_…) solo se leen con claves de prueba.
Permisos
generate· crear, corregir, tamaños e idiomasread· leer conceptos, trabajos y campañasexport· exportar paquetesassets· gestionar la biblioteca
60 por minuto y por clave. Al pasarte: 429 con Retry-After, en segundos. [ … ] confirmar en producción
Idempotency-Key de hasta 200 caracteres. Misma clave y mismo cuerpo: la misma respuesta, con Idempotent-Replayed: true, sin generar ni cobrar otra vez.
Los listados responden data, hasMore y nextCursor. Pasa nextCursor como cursor; limit va de 1 a 100.
Toda ruta responde OPTIONS y admite cualquier origen. La clave viaja solo en Authorization: Bearer, nunca en cookies.
Errores con el mismo formato
| HTTP | code | Cuándo |
|---|---|---|
| 400 | bad_request | JSON inválido o campos inválidos o desconocidos; mira details. |
| 401 | unauthorized | Falta la clave, es inválida o fue revocada. |
| 402 | insufficient_credits | El workspace no tiene créditos suficientes. |
| 403 | forbidden | La clave no tiene el permiso o el workspace no está activo. |
| 404 | not_found | No existe o es de otro workspace (no se distingue a propósito). |
| 409 | conflict | Idempotency-Key en proceso, exportación sin aprobar o recurso no listo. |
| 413 | payload_too_large | Cuerpo de más de 64 KB (256 KB en POST /banners) o archivo de más de 5 MB. |
| 422 | idempotency_mismatch | Esa Idempotency-Key ya se usó con otra petición. |
| 429 | rate_limited | Demasiadas peticiones o trabajos a la vez; lee Retry-After. |
| 500 | internal_error | Falla nuestra; reintenta con la misma Idempotency-Key. |
Cuerpo de un error 400
{
"code": "bad_request",
"message": "prompt no puede estar vacío.",
"details": [
{ "path": "prompt", "message": "prompt no puede estar vacío." }
]
}Un aviso firmado cada vez que pasa algo importante.
Registra una dirección de tu servidor, elige los eventos y recibe un POST con JSON firmado con Standard Webhooks. Hasta 3 intentos por envío y pausa automática tras 5 fallos seguidos.
Los 13 eventos
Verifica la firma con el SDK
import { verifyWebhook } from "@bannermotion/sdk";
// rawBody: el cuerpo EXACTO recibido, como texto (antes de convertirlo a JSON).
// Durante una rotación del secreto pasa los dos: [nuevo, anterior].
const event = await verifyWebhook(process.env.BM_WEBHOOK_SECRET, req.headers, rawBody);
// lanza BannerMotionError ("invalid_signature") si la firma o la hora no valen
if (alreadyProcessed(event.id)) return; // las entregas pueden repetirseSin SDK, el código de Node y Python está en la página de webhooks.
Conecta Claude a BannerMotion.
BannerMotion es un servidor MCP remoto (Streamable HTTP). Claude genera, corrige, previsualiza, adapta y exporta conceptos con los mismos permisos y créditos que tienes en la app.
[ … ] dominio definitivo (hoy app.bannermotion.com; mcp.bannermotion.com más adelante)
- Abre Settings → Connectors.
- Pulsa Add custom connector.
- Pega la dirección del servidor y pulsa Connect.
- Se abre BannerMotion: elige el workspace y aprueba la conexión.
En planes de equipo de Claude, un administrador agrega el conector para la organización.
https://app.bannermotion.com/mcpEl cliente se registra solo (registro dinámico), abre la pantalla de BannerMotion y eliges el workspace. El acceso dura 1 hora y se renueva solo; el refresco dura 30 días. La conexión aparece en tu cuenta como sesión «MCP · cliente» y se desconecta cerrándola.
Envíala en Authorization: Bearer. Los permisos de la clave limitan las herramientas (read, generate, export). Las claves bm_test_ no sirven con MCP.
Las 10 herramientas
- generate_banner
- get_job
- preview_banner
- edit_banner / add_sizes
- export_banners
Campañas con sus tamaños, idiomas y piezas.
Los conceptos de una campaña, con sus piezas y su aprobación.
Concepto nuevo desde un brief; devuelve el trabajo (wait_seconds para esperar). Gasta créditos.
Estado de un trabajo, con espera opcional.
Corrige con una instrucción, opcionalmente solo en algunos tamaños. Gasta créditos.
Imagen de un cuadro y un enlace firmado de 1 hora para ver la animación.
Adapta el concepto a tamaños nuevos. Créditos por tamaño.
Paquetes .zip para una plataforma, con enlace de descarga de 1 hora.
Estado de la exportación y un enlace de descarga nuevo.
Saldo, plan, renovación y costo de cada operación por modelo.
Las reglas son las de la app: si el workspace exige aprobación antes de exportar, o falta la URL del clic, la herramienta lo dice y no exporta.
Clientes mínimos, sin dependencias.
Reintentan los 429 (respetan Retry-After), los 5xx y los cortes de red; ponen una Idempotency-Key en cada POST que crea trabajo; esperan el trabajo por SSE y verifican webhooks.
TypeScript · @bannermotion/sdk
import { BannerMotion } from "@bannermotion/sdk";
const bm = new BannerMotion({ apiKey: process.env.BM_API_KEY! });
const { jobId } = await bm.banners.create({
prompt: "Café helado para verano. Pídelo ahora",
sizes: ["300x250", "728x90"],
});
const job = await bm.jobs.wait(jobId); // por SSE; cae a sondeo si el flujo se corta
if (job.status === "succeeded") {
console.log(job.appUrl); // el banner en el estudio de la app
console.log(await bm.banners.get(job.creativeId!));
}Python · bannermotion
import os
from bannermotion import BannerMotion
bm = BannerMotion(os.environ["BM_API_KEY"])
acc = bm.banners.create("Café helado para verano. Pídelo ahora", sizes=["300x250", "728x90"])
job = bm.jobs.wait(acc["jobId"]) # por SSE; cae a sondeo si el flujo se corta
if job["status"] == "succeeded":
print(job["appUrl"]) # el banner en el estudio de la app
print(bm.banners.get(job["creativeId"]))Plugin de Figma
En desarrollo · sin publicar [ … ]- Seleccionas uno o varios frames; cada frame es un tamaño.
- El plugin sube imágenes y logos a la biblioteca (
POST /api/v1/assets). - Crea el banner con tu composición en
reference(POST /api/v1/banners). - Sigue el trabajo y abre el banner en el estudio (
appUrl).
Necesita una clave con permisos generate y read. Hasta 12 frames y 60 capas por frame. Los textos del frame son los del banner; las imágenes subidas son obligatorias.
Skill de Claude Code
Canal de descarga [ … ]Una carpeta que enseña a Claude Code el flujo con el servidor MCP: revisar créditos, generar, mirar el resultado, corregir con una instrucción por vez, agregar tamaños y exportar.
Se copia a ~/.claude/skills/ (o a .claude/skills/ del proyecto). Requiere el servidor MCP conectado.
API y webhooks: planes Equipo, Agencia y Empresa; el plan Starter no los incluye. Servidor MCP: [ … ] planes por confirmar.
Preguntas frecuentes
¿Gasto créditos al probar?
No con las claves bm_test_: devuelven siempre un concepto de muestra, sin IA ni créditos. Las claves bm_live_ usan los mismos créditos que la app.
¿Puedo reintentar sin cobrar dos veces?
Sí. Envía Idempotency-Key en los POST: la misma clave con el mismo cuerpo devuelve la respuesta anterior, con Idempotent-Replayed: true, sin generar ni cobrar de nuevo.
¿Cómo verifico que un webhook es de BannerMotion?
Cada entrega lleva webhook-id, webhook-timestamp y webhook-signature (Standard Webhooks). Se firma el cuerpo exacto con el secreto whsec_… y se compara en tiempo constante.
¿Hay SDK?
Hay clientes de TypeScript y Python, todavía sin publicar en npm ni PyPI; se piden a soporte@bannermotion.com. Con cualquier otro lenguaje, usa un cliente generado desde la especificación OpenAPI 3.1.
Empieza con una clave de pruebas.
No gasta créditos. Cuando todo funcione, cambia a una clave real.