没有 PHP SDK,所以这里直接使用 REST API。这听起来是个限制,实际上没那么严重:这个 API 就是通过 HTTPS 传输的纯 JSON,用一个 bearer token 认证,而 PHP 标准库里就有做这件事所需的一切。
如果你具体是要从 WordPress 发布,那里有一个插件和一条 RSS 路径,可能比自己写这些代码省事。
认证
每个请求都要把你的 API key 作为 bearer token 携带:
$apiKey = getenv('BULKPUBLISH_API_KEY');
$baseUrl = 'https://app.bulkpublish.com';
把这个 key 放在环境变量里,而不是源代码或提交到仓库的配置文件中。
创建草稿
$payload = [
'content' => 'Check out our latest update!',
'channels' => [
['channelId' => 1, 'platform' => 'x'],
['channelId' => 2, 'platform' => 'linkedin'],
],
'status' => 'draft',
];
$ch = curl_init("$baseUrl/api/posts");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
"Authorization: Bearer $apiKey",
],
CURLOPT_POSTFIELDS => json_encode($payload),
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($status >= 400) {
error_log("BulkPublish error $status: $response");
} else {
$post = json_decode($response, true);
}
先从 draft 开始。它会出现在应用里,这样你就能在任何东西真正发布之前,看到你的代码到底生成了什么。
用 Guzzle 做同一件事
如果你已经在用 Guzzle,写法会更整洁:
use GuzzleHttp\Client;
$client = new Client([
'base_uri' => 'https://app.bulkpublish.com',
'headers' => [
'Authorization' => 'Bearer ' . getenv('BULKPUBLISH_API_KEY'),
'Content-Type' => 'application/json',
],
]);
$response = $client->post('/api/posts', [
'json' => [
'content' => 'Check out our new feature!',
'channels' => [['channelId' => 1, 'platform' => 'instagram']],
'status' => 'scheduled',
'scheduledAt' => '2026-04-10T14:00:00Z',
'timezone' => 'America/New_York',
],
]);
$post = json_decode((string) $response->getBody(), true);
查找频道 ID
$response = $client->get('/api/channels');
$channels = json_decode((string) $response->getBody(), true);
去查一下,或者把它们放进配置里。把某个一次性脚本里的 ID 硬编码进一个会长期运行的系统,正是导致某次部署把帖子发到错误账号的原因。
排期相关字段
scheduledAt 是一个 ISO-8601 时间戳,timezone 是一个 IANA 时区名称。对任何周期性任务都要显式传递时区,否则夏令时切换时,你的发布时间会整整偏移一个小时。
妥善处理错误
服务器端发布特有的失败模式是:没有人在盯着它。凌晨三点因校验失败而失败的帖子,如果你没让它发出声音,就会悄无声息地失败。
- 检查状态码,不要假设收到响应体就等于成功
- 失败时记录响应体,因为它会说明问题出在哪里
- 遵守速率限制,而不是立刻重试
| Free | Pro | Business | |
|---|---|---|---|
| 每日 API 请求数 | 30 | 5,000 | 50,000 |
| API key 数量 | 1 | 5 | 10 |
| Free 版每天 30 次是用来评估的。任何按计划运行的任务都需要付费套餐。 |
简而言之
不需要 SDK。用 bearer token 把带有 content、channels 和 status 的 JSON POST 到 /api/posts。先用草稿开始,查好频道 ID,为排期帖子传递时区,并妥善记录失败情况,因为服务器端发布默认就是悄无声息地失败的。