Platform-Specific Content
Use the
platformContent object to customize content and settings per platform. This is a top-level field in the Create Post and Update Post request body.
How it works:
- The top-level text field is the canonical default — every platform without an override uses it as-is.
- To override text for a specific platform (including LinkedIn), set platformContent.<platform>.text. This automatically marks that platform as unsynced from the default.
- Some platforms accept additional settings (privacy, content type, etc.) inside platformContent.<platform>.
- If you don't include a platform in platformContent, it uses the default text.
Several accounts on one platform — a post can go to several accounts on the same platform (e.g. three X accounts in platforms). To give some of them their own text, set platformContent.<platform>.accounts.<accountId>.text. Each account uses its own text if it has one, otherwise the platform text, otherwise the default text. The account must be one of the post's accounts on that platform. On update, accounts you leave out keep their text, and an empty text sends an account back to the platform text. X doesn't allow posting the same or very similar text to several accounts you control, so give each X account its own text.
Media is always top-level — images, videos, and PDFs are passed via the media object, not inside platformContent. All platforms in the post share the same media. See Publishing with Media.
Threads — for Twitter, Threads, and Bluesky threads, separate each post with triple newlines (\n\n\n) in that platform's text. Threading is auto-detected per platform from the separator: the same request can thread on X (because platformContent.twitter.text contains \n\n\n) while staying as a single long-form post on LinkedIn (because text or platformContent.linkedin.text doesn't contain it). No isThread flag is required.| Platform | Fields |
|---|---|
text — defaults to top-level text, override via platformContent.linkedin.text, 3,000 chars accounts — own text per account, { [accountId]: { text } }. Available on every platform. auto-plug — schedule follow-up comments on the published post via top-level isAutoPlug + autoPlug fields. See Auto-plug (LinkedIn). | |
text — 280 chars per tweet (\n\n\n splits threads) | |
| threads | text — 500 chars per post (\n\n\n splits threads) |
| bluesky | text — 300 chars per post (\n\n\n splits threads) |
text — 2,200 chars contentType — feed / reel / story / carousel aiGenerated — boolean, default false. Self-discloses AI-generated content (Meta is_ai_generated); Instagram may add an "AI info" label. Applies to image / reel / carousel posts. | |
text — 63,206 chars | |
| youtube | text — description, 5,000 chars title — required, 100 chars tags — array privacy — public / unlisted / private videoType — long / short thumbnail — optional custom thumbnail URL (JPG/PNG/GIF, ≤30 MB; server compresses to YouTube's 2 MB limit). Long-form only — ignored on Shorts. Requires a verified YouTube channel; otherwise the thumbnail step is skipped and you get an email notification (the video still publishes). |
| tiktok | text — caption, 2,200 chars privacyLevel — PUBLIC_TO_EVERYONE / MUTUAL_FOLLOW_FRIENDS / FOLLOWER_OF_CREATOR / SELF_ONLY allowComments — boolean allowDuet — boolean, video only allowStitch — boolean, video only postMode — direct / draft autoAddMusic — boolean, carousels only, default true |
Example request
// Post to LinkedIn + Twitter with different text
curl --request POST \
--url https://server.posthero.ai/api/v1/posts \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"text": "Excited to announce our new feature! Here is a deep dive into how we built it and what it means for the industry...",
"platforms": [
{ "platform": "linkedin", "accountId": "acc_li_1" },
{ "platform": "twitter", "accountId": "acc_tw_1" }
],
"platformContent": {
"twitter": {
"text": "We just launched something big. Check it out!"
}
},
"media": { "images": ["https://s3.amazonaws.com/..."] },
"publishNow": true
}'
// Thread on X, single long-form on LinkedIn — from the same POST.
// Threading is auto-detected per platform from \n\n\n separators.
curl --request POST \
--url https://server.posthero.ai/api/v1/posts \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"platforms": [
{ "platform": "linkedin", "accountId": "acc_li_1" },
{ "platform": "twitter", "accountId": "acc_tw_1" }
],
"platformContent": {
"linkedin": {
"text": "Long-form LinkedIn post. Multiple paragraphs are fine — no triple newlines means LinkedIn publishes this as a single post."
},
"twitter": {
"text": "Tweet 1 — punchy hook.\n\n\nTweet 2 — supporting detail.\n\n\nTweet 3 — call to action."
}
}
}'
// Three X accounts. acc_tw_1 has no own text, so it posts platformContent.twitter.text;
// acc_tw_2 and acc_tw_3 post their own text from accounts.
curl --request POST \
--url https://server.posthero.ai/api/v1/posts \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"platforms": [
{ "platform": "twitter", "accountId": "acc_tw_1" },
{ "platform": "twitter", "accountId": "acc_tw_2" },
{ "platform": "twitter", "accountId": "acc_tw_3" }
],
"platformContent": {
"twitter": {
"text": "We just launched something big. Check it out!",
"accounts": {
"acc_tw_2": { "text": "Our team shipped it — here is what changed." },
"acc_tw_3": { "text": "New release is live. Try it today." }
}
}
}
}'