Não existe SDK para PHP, então isso usa a API REST diretamente. Isso é menos uma limitação do que parece: a API é JSON simples sobre HTTPS com um token de portador, e o PHP já tem tudo o que é necessário na biblioteca padrão.
Se você está publicando a partir do WordPress especificamente, existe um plugin e uma rota de RSS que podem dar menos trabalho do que escrever isso do zero.
Autenticação
Toda requisição carrega sua chave de API como um token de portador:
$apiKey = getenv('BULKPUBLISH_API_KEY');
$baseUrl = 'https://app.bulkpublish.com';
Mantenha a chave no ambiente, e não no código-fonte ou em um arquivo de configuração versionado.
Criar um rascunho
$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);
}
Comece com draft. Ele aparece no app, então você pode ver o que seu código produziu antes que qualquer coisa seja publicada.
A mesma coisa com Guzzle
Se você já tem o Guzzle, fica mais organizado:
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);
Encontrando os IDs dos canais
$response = $client->get('/api/channels');
$channels = json_decode((string) $response->getBody(), true);
Consulte-os ou mantenha-os na configuração. Fixar um ID vindo de um script pontual em algo de vida longa é como um deploy passa a publicar na conta errada.
Campos de agendamento
scheduledAt é um timestamp ISO-8601 e timezone é um nome IANA. Passe o fuso horário explicitamente para qualquer coisa recorrente, ou seu horário de publicação vai andar uma hora quando o horário de verão mudar.
Trate os erros de forma adequada
O modo de falha específico da publicação no lado do servidor é que ninguém está observando. Um post que falha na validação às 3h da manhã é silencioso, a menos que você o torne visível.
- Verifique os códigos de status, não assuma que uma resposta significa sucesso
- Registre o corpo da resposta em caso de falha, já que ele diz o que deu errado
- Respeite os limites de taxa e recue em vez de tentar novamente de imediato
| Free | Pro | Business | |
|---|---|---|---|
| Requisições de API/dia | 30 | 5.000 | 50.000 |
| Chaves de API | 1 | 5 | 10 |
| As 30 do plano Free por dia servem para avaliação. Qualquer coisa rodando em um cronograma precisa de um plano pago. |
A versão curta
Nenhum SDK necessário. Faça POST de JSON para /api/posts com um token de portador, content, channels e um status. Comece com rascunhos, consulte os IDs de canal, passe um fuso horário com publicações agendadas e registre falhas corretamente, porque a publicação do lado do servidor falha silenciosamente por padrão.