How do I send one post to several platforms?
curl -X POST https://api.socifyr.com/api/content/text \
-H "Authorization: Bearer sk_your_key" \
-H "X-Workspace-Id: <workspaceId>" \
-H "Content-Type: application/json" \
-d '{
"connections": [
"linkedin-myhandle",
"x-myhandle",
"threads-myhandle",
"bluesky-myhandle-bsky-social"
],
"text": "Monorepos are great if you have one tooling team."
}'connections takes slugs, never raw platform names or database IDs. Run socifyr connections or list_connections to see them. Socifyr has no wildcard such as "all Instagram accounts", so to post to every account on one platform, filter the list and pass the slugs:
const all = await socifyr.workspaces.listConnections(workspaceId)
const instagram = all.filter((c) => c.platform === 'instagram').map((c) => c.slug)
await socifyr.uploads.text({ connections: instagram, text: 'Announcement for every brand account' })Which caption length should I write for?
The shortest limit among the platforms you target. The example above includes X (280) and Bluesky (300), so 280 is the safe number. Threads auto-threads at 500, so it will take 280 easily. Check ahead with getEffectiveCaptionLimit from @socifyr/shared. See the full table in caption length limits by platform.
If you send a long caption to a mix of platforms, platforms with thread support split it, Discord truncates it, and the rest reject it. Do not rely on that. Shorten, or override per account.
How do I use a different caption or format per platform?
await socifyr.uploads.photos({
connections: ['instagram-mybrand', 'linkedin-myhandle', 'x-myhandle'],
medias: [fs.readFileSync('banner.jpg')],
text: 'Default caption for any account without an override',
platformOptions: {
'instagram-mybrand': { text: 'Long Instagram caption with hashtags #design #branding' },
'x-myhandle': { text: 'Short version. Link in bio.' },
},
})
// Different video destinations per platform
await socifyr.uploads.video({
connections: ['instagram-mybrand', 'linkedin-myhandle'],
medias: [fs.readFileSync('demo.mp4')],
text: 'New product demo',
platformOptions: { 'instagram-mybrand': { mediaType: 'REELS' } },
})platformOptions is keyed by connection slug. Beyond text, each platform has its own options, such as mediaType for Instagram, privacyLevel for TikTok, videoType for YouTube and visibility for Mastodon. Media rules also differ by platform; see image size and aspect ratio requirements and video specs.
What happens when one platform fails?
A post with N connections produces N channels, and each publishes independently. If one fails, the others are unaffected. The overall status becomes partial_failure when some succeed and some fail, failed when all fail, and completed when all succeed.
const upload = await socifyr.uploads.text({ connections, text })
const result = await socifyr.uploads.waitForCompletion(upload.id!)
if (result.status === 'partial_failure') {
for (const ch of result.channels.filter((c) => c.result?.status === 'failed')) {
console.warn(`${ch.platform}: ${ch.result?.error}`)
}
await socifyr.uploads.retry(upload.id!) // re-queues failed channels only
}Retry is idempotent for succeeded channels. They are skipped through an idempotency guard, so you cannot double-post. Decide what to retry from the error: a rate limit or timeout is worth another attempt, an expired token needs a reconnect, and a too-long caption needs an edit first.
Does cross-posting cost more uploads?
No. One request is one upload against your monthly allowance (30 on Free, unlimited on Pro and Business) however many accounts it targets. Two other limits do scale with the number of channels: the platform daily caps (see daily posting limits per platform) and, for X, the monthly allowance, which counts each X channel.
What does one announcement look like across eight platforms?
Take a product announcement going to LinkedIn, X, Threads, Bluesky, Mastodon, Telegram, Discord and Slack. The numbers below come straight from the platform constants and show what each channel will do with the same text.
| Platform | Text limit | Long text behavior | First comment |
|---|---|---|---|
| 3,000 | Not rewritten | Yes | |
| X | 280 | Split into a thread | Yes |
| Threads | 500 | Split into a thread | Yes |
| Bluesky | 300 | Split into a thread | Yes |
| Mastodon | 500 | Not rewritten | No |
| Telegram | 4,096 | Not rewritten | No |
| Discord | 2,000 | Truncated | No |
| Slack | 40,000 | Not rewritten | No |
A 250-character announcement fits all eight untouched. A 450-character one still fits LinkedIn, Threads, Mastodon, Telegram, Discord and Slack, but X and Bluesky turn it into threads. Anything over 500 breaks Mastodon. The simplest rule is to keep the shared text under the smallest limit and put detail behind a link or in a first comment on the platforms that support it.
What should I check before I cross-post?
- Run
list_connectionsorsocifyr connectionsand confirm every slug exists and is notneeds_reconnect. - Compute the shortest caption limit for the set with
getEffectiveCaptionLimit. - Check media limits: size, count and format per platform.
- Consider the platform daily caps if you post often.
- Decide how you will handle
partial_failurebefore you ship, not after.
An AI agent can run that checklist through the MCP server before it posts, which is a good first instruction to give it.
Frequently asked questions
Can I post to Instagram, X and LinkedIn at the same time?
connections. Each account publishes independently and the result lists a status per account.What if one platform rejects my post?
partial_failure. Fix the cause and call retry to re-queue just the failed channels.Can I use a different caption per platform in one call?
platformOptions keyed by connection slug and set text for each account that needs its own version.