Non esiste un SDK PHP, quindi qui si usa direttamente la REST API. È una limitazione minore di quanto sembri: l’API è semplice JSON su HTTPS con un bearer token, e PHP ha già tutto il necessario nella libreria standard.
Se pubblichi da WordPress in particolare, esiste un plugin e una via RSS che potrebbero richiedere meno lavoro di scrivere tutto questo da zero.
Autenticazione
Ogni richiesta porta la tua API key come bearer token:
$apiKey = getenv('BULKPUBLISH_API_KEY');
$baseUrl = 'https://app.bulkpublish.com';
Tieni la chiave nell’ambiente piuttosto che nel codice sorgente o in un file di configurazione versionato.
Creare una bozza
$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);
}
Inizia con draft. Compare nell’app, così puoi vedere cosa ha prodotto il tuo codice prima che qualcosa venga pubblicato.
La stessa cosa con Guzzle
Se hai già Guzzle, è più ordinato:
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);
Trovare gli ID dei canali
$response = $client->get('/api/channels');
$channels = json_decode((string) $response->getBody(), true);
Cercali oppure tienili in configurazione. Inserire nel codice l’ID di uno script una tantum e portarselo in qualcosa di duraturo è il modo in cui un deploy inizia a pubblicare sull’account sbagliato.
Campi di programmazione
scheduledAt è un timestamp ISO-8601 e timezone è un nome IANA. Passa il fuso orario esplicitamente per qualsiasi cosa ricorrente, altrimenti l’orario di pubblicazione si sposta di un’ora quando cambia l’ora legale.
Gestisci gli errori come si deve
La modalità di fallimento specifica della pubblicazione lato server è che nessuno sta guardando. Un post che fallisce la validazione alle 3 del mattino è silenzioso a meno che tu non l’abbia reso rumoroso.
- Controlla i codici di stato, non dare per scontato che una risposta significhi successo
- Registra il corpo della risposta in caso di errore, perché indica cosa non ha funzionato
- Rispetta i rate limit e rallenta invece di riprovare immediatamente
| Free | Pro | Business | |
|---|---|---|---|
| Richieste API/giorno | 30 | 5.000 | 50.000 |
| API key | 1 | 5 | 10 |
| Le 30 al giorno del piano Free servono per la valutazione. Qualsiasi cosa funzioni su una programmazione ha bisogno di un piano a pagamento. |
La versione breve
Nessun SDK necessario. Fai una POST JSON a /api/posts con un bearer token, content, channels e uno status. Inizia con le bozze, cerca gli ID dei canali, passa un fuso orario con i post programmati e registra gli errori come si deve, perché la pubblicazione lato server fallisce silenziosamente per impostazione predefinita.