Publicar en plataformas sociales desde Node normalmente significa un flujo de OAuth, una canalización de medios y un modelo de publicación por plataforma, cada uno de los cuales sigue cambiando. Esto lo hace a través de un único cliente.
Instalar y autenticar
npm install bulkpublish
import { BulkPublish } from 'bulkpublish';
const bp = new BulkPublish({ apiKey: process.env.BULKPUBLISH_API_KEY });
Consigue una clave en la configuración de desarrollador de tu cuenta. Guárdala en una variable de entorno, no en el código fuente.
Crear un borrador
Empieza aquí en lugar de con la publicación inmediata. Un borrador es visible en la app, así que puedes ver exactamente qué produjo tu código antes de que llegue a ninguna audiencia.
const post = await bp.posts.create({
content: 'Check out our latest update!',
channels: [
{ channelId: 1, platform: 'facebook' },
{ channelId: 2, platform: 'x' },
{ channelId: 3, platform: 'linkedin' },
],
status: 'draft',
});
Cada canal es un objeto con un channelId y una platform. Para encontrar los tuyos:
const channels = await bp.channels.list();
No dejes con código fijo los IDs de canal de un script puntual en nada que vaya a durar. Búscalos, o guárdalos en configuración donde se puedan cambiar sin un despliegue.
Programar una
const post = await bp.posts.create({
content: 'Check out our new feature!',
channels: [{ channelId: 1, platform: 'instagram' }],
mediaFiles: [uploadedFile.id],
postFormat: 'reel',
status: 'scheduled',
scheduledAt: '2026-04-10T14:00:00Z',
timezone: 'America/New_York',
});
Dos campos que merece la pena entender juntos. scheduledAt es una marca de tiempo ISO-8601, y timezone es un nombre de zona IANA. Pasar la zona horaria explícitamente es lo que hace que la lógica recurrente se comporte con sensatez a través de los cambios de horario de verano, en lugar de desviarse una hora dos veces al año.
Medios
Los medios se suben primero, y después se referencian por id al crear la publicación:
const file = await bp.media.upload(/* … */);
await bp.posts.create({
content: 'New drop.',
mediaFiles: [file.id],
channels: [{ channelId: 1, platform: 'instagram' }],
status: 'scheduled',
scheduledAt: '2026-04-10T14:00:00Z',
});
Las reglas de medios de cada plataforma difieren, y se validan antes de que la publicación se ponga en cola en lugar de al publicar. Ese es el comportamiento que quieres de un script: un rechazo que puedas capturar y registrar ahora, no un fallo silencioso a las 9 de la mañana de mañana.
Los recursos disponibles
El cliente expone posts, channels, channel sets, media, labels, schedules, RSS feeds, analytics y platforms. Así que un script puede hacer más que crear: consultar qué hay en cola, comprobar la cuota, extraer métricas después de publicar.
Cosas que conviene hacer bien
No publiques nunca directamente en la primera versión. Crea borradores, míralos, y después cambia a scheduled. El coste es nulo y detecta problemas de formato invisibles en el código.
Gestiona los límites de frecuencia. La asignación de tu plan es un techo real:
| Free | Pro | Business | |
|---|---|---|---|
| Solicitudes de API/día | 30 | 5.000 | 50.000 |
| Claves de API | 1 | 5 | 10 |
| Las 30 al día de Free están pensadas para probar la API, no para ejecutar nada. Un script en un bucle de reintentos la agotará en segundos. |
No generes tus propios datos de plan. Si tu script escribe el texto de la publicación, mantén los números de producto fuera de él. Cualquier cosa factual debería venir de una fuente en lugar de una plantilla que estará equivocada después del siguiente cambio de precios.
La versión corta
npm install bulkpublish, crea un cliente con tu clave de API, llama a bp.posts.create con contenido y canales. Empieza con borradores, busca los IDs de canal en lugar de fijarlos en el código, pasa una zona horaria con cualquier cosa programada.