1. Go to this page and download the library: Download omnisocials/omnisocials-php library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
omnisocials / omnisocials-php example snippets
use OmniSocials\Client;
$client = new Client(); // reads OMNISOCIALS_API_KEY from env
$post = $client->posts->create([
'content' => 'Hello from the SDK',
'channels' => ['instagram', 'linkedin'],
'scheduled_at' => '2026-08-01T09:00:00Z',
]);
$client->posts->create([
'content' => [
'default' => 'New drop this Friday',
'x' => 'New drop this Friday. RT to spread the word',
],
'channels' => ['instagram', 'x'],
'scheduled_at' => '2026-08-01T09:00:00Z',
]);
$proposal = $client->posts->create([
'content' => 'Proposed for Friday morning',
'channels' => ['instagram', 'linkedin'],
'scheduled_at' => '2026-08-01T09:00:00Z',
'draft' => true,
]);
echo $proposal['data']['status'] . ' ' . $proposal['data']['schedule_at']; // draft, the time is kept
// The human agrees: schedule it at the time it already carries
$client->posts->update($proposal['data']['id'], ['draft' => false]);
$post = $client->posts->create([
'content' => 'Comment GUIDE and I will send you the link',
'channels' => ['instagram'],
'scheduled_at' => '2026-08-01T09:00:00Z',
'media_urls' => ['https://example.com/guide-cover.jpg'],
'comment_dm_automation' => [
'trigger' => ['keywords' => ['guide'], 'match' => 'word'],
'actions' => [
'dm' => ['text' => 'Here is the guide: https://example.com/guide'],
'public_reply' => ['enabled' => true, 'variations' => ['Sent you a DM!', 'Check your inbox']],
],
'limits' => ['max_sends' => 500],
],
]);
$automationId = $post['data']['comment_dm_automation']['id'];
// Later: who was answered, and why someone was skipped
$events = $client->automations->listEvents($automationId, ['outcome' => 'sent']);
print_r($events['counts']); // ['sent' => 12, 'skipped' => 3]
foreach ($events['data'] as $event) {
echo $event['person']['username'] . ' ' . $event['outcome'] . ' ' . $event['reason_label'] . "\n";
}
$client->posts->createAndPublish([
'content' => 'Going live right now',
'channels' => ['x', 'bluesky'],
]);
$client->posts->create([
'content' => 'Sunrise over the harbor',
'channels' => ['mastodon', 'bluesky'],
'scheduled_at' => '2026-08-01T09:00:00Z',
'media_urls' => [
[
'url' => 'https://example.com/harbor.jpg',
'alt' => 'A small sailboat crossing a calm harbor at sunrise, sky in deep orange',
],
],
]);
$client->posts->create([
'content' => 'Behind the scenes of our summer shoot',
'channels' => ['instagram', 'youtube', 'x'],
'scheduled_at' => '2026-08-01T09:00:00Z',
'media_urls' => ['https://example.com/bts.mp4'],
'instagram' => ['share_to_feed' => true],
'youtube' => ['title' => 'Summer shoot BTS', 'privacy' => 'public'],
'x' => ['reply_settings' => 'following', 'made_with_ai' => false],
// Not yet released (coming in 0.10.0): a poll on X (the text is the question); also threads.poll and mastodon.poll:
// 'x' => ['poll' => ['options' => ['Polls', 'Reports'], 'duration_minutes' => 1440]],
]);
$client->posts->create([
'content' => 'The new collection is live. Tap the button to shop.',
'channels' => ['telegram'],
'scheduled_at' => '2026-11-02T09:00:00Z',
'media_urls' => ['https://example.com/collection.jpg'],
'telegram' => [
'silent' => true,
'pin' => true,
'buttons' => [['text' => 'Shop now', 'url' => 'https://example.com/shop']],
'first_comment' => 'Questions? Reply to this message.',
],
]);
// A native poll: the text is the question.
$client->posts->create([
'content' => 'Which day suits the live Q&A?',
'channels' => ['telegram'],
'telegram' => ['poll' => ['options' => ['Tuesday', 'Thursday', 'Saturday'], 'open_period' => 86400]],
]);
$client->posts->create([
'content' => 'How we grew to 10k followers in 90 days',
'channels' => ['x'],
'scheduled_at' => '2026-08-01T09:00:00Z',
'x' => [
'thread_parts' => [
['text' => 'How we grew to 10k followers in 90 days. A thread:'],
['text' => '1. We posted every single day, even when it felt pointless.'],
['text' => '2. We replied to every comment within an hour.'],
['text' => '3. Full breakdown on our blog. Link in bio.'],
],
],
]);
// Meta Threads chain with a carousel on the first part
$client->posts->create([
'content' => 'Behind the scenes of our summer shoot',
'channels' => ['threads'],
'threads' => [
'thread_parts' => [
['text' => 'Behind the scenes of our summer shoot. A few highlights:', 'media_urls' => ['https://example.com/shoot-1.jpg', 'https://example.com/shoot-2.jpg']],
['text' => 'Day one: scouting locations at sunrise.'],
['text' => 'Day two: the full crew, 14 hours, zero regrets.'],
],
],
]);
$res = $client->posts->create([
'content' => 'Read the full story: https://example.com/post',
'channels' => ['x'],
]);
foreach ($res['warnings'] ?? [] as $warning) {
if ($warning['code'] === 'x_url_post_credits') {
echo $warning['credits_
use OmniSocials\Exception\ApiException;
try {
$client->posts->create([
'content' => 'Read the full story: https://example.com/post',
'channels' => ['x'],
'scheduled_at' => '2026-08-15T09:00:00Z',
]);
} catch (ApiException $e) {
if ($e->getErrorCode() === 'x_credits_insufficient') {
$details = $e->getBody()['error']['details'] ?? [];
echo "Needs {$details['credits_
$page = $client->posts->list(['status' => 'scheduled', 'limit' => 50]);
$posts = $page['data'];
$one = $client->posts->get($posts[0]['id']);
$client->posts->update($one['data']['id'], ['scheduled_at' => '2026-08-02T10:00:00Z']);
$client->posts->publish($one['data']['id']); // publish a draft/scheduled post now
$client->posts->retry($one['data']['id']); // retry only the failed platforms of a failed/warning post
$client->posts->delete($one['data']['id']); // returns null (204)
$client->posts->approve($id); // approve the current approval-workflow step
$client->posts->reject($id, "Wrong CTA link, please fix."); // reject and stop the workflow (comment optional, or omit / pass null)
$review = $client->posts->getApproval($id)['data'];
if ($review['status'] === 'rejected' && $review['rejection'] !== null) {
echo "Rejected by {$review['rejection']['by']['name']}: {$review['rejection']['reason']}\n";
}
foreach ($review['steps'] as $step) {
echo "{$step['order']} {$step['name']} {$step['status']}\n";
}
// From a path
$client->media->upload(['file' => './photos/product.jpg', 'name' => 'product-hero']);
// Or from raw bytes (pass a filename so the API can detect the type)
$bytes = file_get_contents('./photos/product.jpg');
$client->media->upload(['file' => $bytes, 'filename' => 'product.jpg']);
$client->media->uploadFromBase64([
'data' => $base64String, // no data URI prefix
'mime_type' => 'image/png',
'filename' => 'chart.png',
]);
// List conversations (all filters optional)
$conversations = $client->inbox->listConversations([
'platform' => 'instagram', // instagram | facebook | linkedin | tiktok | youtube | x | threads
'type' => 'dm', // dm | comment | mention
'unread' => true,
'limit' => 25, // 1-100
]);
foreach ($conversations['data'] as $conversation) {
// Full message history for one conversation.
// LinkedIn ids contain ":" and "()" - they are URL-encoded for you.
$messages = $client->inbox->getMessages($conversation['conversation_id']);
// Mark the whole conversation as read.
$client->inbox->markRead($conversation['conversation_id']);
// Reply (text ved_reply_ids).
$client->inbox->deleteMessage($messages['data'][0]['id']);
}
// Page through with the cursor.
$cursor = $conversations['pagination']['next_cursor'] ?? null;
while ($cursor !== null) {
$page = $client->inbox->listConversations(['cursor' => $cursor]);
// ... handle $page['data'] ...
$cursor = ($page['pagination']['has_more'] ?? false)
? $page['pagination']['next_cursor']
: null;
}
$next = $client->inbox->next(['platform' => 'instagram']);
while ($next['data'] !== null) {
$message = $next['data']['message'];
echo "{$next['remaining']} left. {$message['sender']['username']}: {$message['text']}\n";
if (!$next['data']['reply_window']['open']) {
// An Instagram/Facebook DM past Meta's 24-hour window: reply() would
// throw 422 outside_messaging_window. Answer it in the app, or skip it.
$client->inbox->markRead($message['conversation_id']);
$next = $client->inbox->next(['platform' => 'instagram']);
continue;
}
$reply = $client->inbox->reply($message['conversation_id'], [
'text' => 'Thanks! DM sent.',
'message_id' => $message['id'], // the comment being answered, not the newest one
'
use OmniSocials\Exception\ApiException;
try {
$client->inbox->reply($conversation['conversation_id'], ['text' => 'Thanks for the DM!']);
} catch (ApiException $e) {
if ($e->getErrorCode() === 'insufficient_credits') {
echo "Balance can't cover the 2-credit send, top up in the dashboard\n";
} elseif ($e->getErrorCode() === 'x_inbox_suspended') {
echo "This workspace's X inbox is suspended, top up and re-enable it to resume\n";
}
}
$webhook = $client->webhooks->create([
'url' => 'https://example.com/omnisocials/webhook',
'events' => ['post.published', 'post.failed'],
]);
echo $webhook['data']['secret']; // save it, it is only shown once
$client->webhooks->list();
$client->webhooks->get($webhook['data']['id']);
$client->webhooks->update($webhook['data']['id'], ['is_active' => false]);
$rotated = $client->webhooks->rotateSecret($webhook['data']['id']);
echo $rotated['data']['secret']; // the old secret stops working
$client->webhooks->delete($webhook['data']['id']);