从 Node 发布到社交平台,通常意味着每个平台各有一套 OAuth 流程、一条媒体处理流水线和一种发布模型,而且每一套都在不停变化。这篇文章教你通过一个统一的客户端来完成这一切。
安装并完成认证
npm install bulkpublish
import { BulkPublish } from 'bulkpublish';
const bp = new BulkPublish({ apiKey: process.env.BULKPUBLISH_API_KEY });
从你账号的开发者设置里获取一个密钥。把它放在环境变量里,不要写进源代码。
创建一条草稿
先从这里开始,而不是直接发布。草稿在应用里是可见的,所以在任何内容触达受众之前,你能准确看到自己的代码生成了什么。
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',
});
每个频道都是一个带有 channelId 和 platform 的对象。要查找你自己的频道:
const channels = await bp.channels.list();
不要把一次性脚本里的频道 ID 硬编码进任何长期运行的代码里。要去查询它们,或者把它们存在配置里,这样改动就不需要重新部署。
排期一条帖子
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',
});
有两个字段值得放在一起理解。scheduledAt 是一个 ISO-8601 时间戳,timezone 是一个 IANA 时区名称。显式传入时区,能让循环逻辑在夏令时切换前后依然表现得合理,而不是每年偏移一小时两次。
媒体
媒体要先上传,然后在创建帖子时通过 id 引用:
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',
});
每个平台的媒体规则各不相同,而它们会在帖子被排入队列之前就完成校验,而不是等到发布时才校验。这正是你希望脚本具备的行为:一个你现在就能捕获并记录下来的拒绝,而不是明天早上九点一次悄无声息的失败。
可用的资源
这个客户端暴露了帖子、频道、频道集、媒体、标签、排期、RSS 订阅源、数据分析和平台。所以一个脚本能做的远不止创建:查看排队中的内容、检查配额、在发布后拉取指标数据。
值得注意的几件事
第一个版本永远不要直接发布。 先创建草稿,看一看,再切换成 scheduled。这几乎没有成本,却能捕获那些在代码里根本看不出来的格式问题。
要处理速率限制。 你套餐的额度是一道真实的天花板:
| 免费版 | Pro | Business | |
|---|---|---|---|
| 每日 API 请求数 | 30 | 5,000 | 50,000 |
| API key 数量 | 1 | 5 | 10 |
| 免费版每天 30 次的额度,是给试用 API 用的,不是给正式运行任何东西用的。一个处于重试循环里的脚本,几秒钟就能把它耗尽。 |
不要让脚本自己生成产品事实数据。 如果你的脚本要写帖子文案,不要把产品数字写死在里面。任何事实性的内容都应该来自一个数据源,而不是一个下次价格一变就会出错的模板。
简而言之
npm install bulkpublish,用你的 API key 创建一个客户端,调用 bp.posts.create 传入内容和频道。先从草稿开始,去查询频道 ID 而不是硬编码它们,任何排期操作都要传入时区。