Cross-post to Facebook, Instagram, LinkedIn, TikTok, YouTube and X from one API
Publish the same message to every connected account with one request body, adapt it per network, and respect each platform's media and caption rules.
Updated · 7 min read
Cross-posting sounds simple: say the same thing everywhere. In practice each network has its own API, its own sign-in, its own caption limits and its own idea of what a post needs. SocialCannon puts Facebook, Instagram, LinkedIn, TikTok, YouTube and X behind one request format, so the hard part becomes deciding what to say on each network. This guide shows both ways to cross-post and the rules that decide whether a post can go out.
One request format for every network
Every connected account, whatever the network, takes the same body on POST /api/v1/posts: accountId, content, optional mediaUrls, optional scheduledAt and optional platformOptions for network features such as Reels or Stories. You authenticate once with your API credentials; SocialCannon holds each network’s tokens, encrypted, and refreshes them when they expire.
Option 1: One post per account
When the same text works everywhere, send one request per account. This is the most predictable approach, because every post has its own ID, status and retry path.
// Credentials come from the environment, never from source code.
const auth = await fetch('https://socialcannon.app/api/v1/auth/token', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
grant_type: 'client_credentials',
client_id: process.env.SOCIALCANNON_CLIENT_ID,
client_secret: process.env.SOCIALCANNON_CLIENT_SECRET,
}),
}).then((res) => res.json());
const token = auth.data?.access_token;
if (!token) throw new Error(auth.error ?? 'Authentication failed');
const accounts = ['FACEBOOK_ACCOUNT_ID', 'LINKEDIN_ACCOUNT_ID', 'INSTAGRAM_ACCOUNT_ID'];
// A fixed UTC time within the next 30 days, for example 2026-11-04T14:00:00Z. Keep it
// unchanged when you re-run the script so each Idempotency-Key replays its original post.
const scheduledAt = process.env.SCHEDULED_AT;
if (!scheduledAt) throw new Error('Set SCHEDULED_AT to a UTC time within the next 30 days');
const body = {
content: 'We just shipped dark mode. Try it today.',
mediaUrls: ['https://example.com/dark-mode.png'],
scheduledAt,
};
let failed = false;
for (const accountId of accounts) {
try {
const res = await fetch('https://socialcannon.app/api/v1/posts', {
method: 'POST',
headers: {
Authorization: 'Bearer ' + token,
'Content-Type': 'application/json',
// One key per post: campaign plus account. Replaying this exact request never creates a
// second post; if you change the post or SCHEDULED_AT, change the campaign part too.
'Idempotency-Key': 'dark-mode-launch-' + accountId,
},
body: JSON.stringify({ ...body, accountId }),
});
const json = await res.json();
if (res.ok && json.success) {
console.log(accountId, 'scheduled', json.data.id);
} else {
// Keep both: an error can come with the ID of a post that already exists.
failed = true;
console.error(accountId, res.status, json.code ?? '', json.error, json.data?.id ?? '');
}
} catch (error) {
// No response means the outcome is unknown: re-run later to replay with the same key.
failed = true;
console.error(accountId, 'no response', error.message);
}
}
if (failed) process.exitCode = 1;Replace the account IDs and the example image URL with your own and set SCHEDULED_AT; the image must be publicly reachable. Each request succeeds or fails on its own. If Instagram rejects a post because the image is missing, Facebook and LinkedIn are unaffected. The Idempotency-Key protects the case where a response is lost: repeat the identical request with the same key and you get the original post back, or a 409 with its ID if it is still in progress or needs recovery, never a second post. When you fix and change a request, send it with a new key, because a changed body under a used key is refused with 409 IDEMPOTENCY_CONFLICT. If a 409 includes a post ID, that post already exists; check it with GET /api/v1/posts/POST_ID before sending anything new.
Option 2: Adapt and publish in one call
The same words rarely suit every network. An X post has 280 characters, a LinkedIn post can run to 3,000 and reads best with line breaks, and Instagram captions cannot contain clickable links. The repurpose endpoint rewrites one source text for each target and, in post mode, publishes the results to the accounts you name. Networks are named in lowercase, and X is written as twitter:
curl -X POST https://socialcannon.app/api/v1/posts/repurpose \
-H "Authorization: Bearer TOKEN" \
-H "Content-Type: application/json" \
-d '{
"sourceContent": "We just shipped dark mode. It follows your system setting and is on for everyone today.",
"targetPlatforms": ["linkedin", "instagram"],
"mode": "post",
"accountIds": {
"linkedin": "LINKEDIN_ACCOUNT_ID",
"instagram": "INSTAGRAM_ACCOUNT_ID"
},
"mediaUrls": { "instagram": ["https://example.com/dark-mode.png"] }
}'The Free plan allows two networks per repurpose request; Pro allows five. The response has one result per platform, each with its own post ID or error. Run it in the default preview mode first if you want to read the variants before anything is published. The repurposing guide covers tone, appended text and limits.
What each network requires
Most cross-posting failures come from a post that one network cannot accept. SocialCannon checks these rules before publishing and returns a clear error instead of sending something that would fail upstream.
| Network | Text only? | Main rules |
|---|---|---|
| Yes | Posts to a Page you manage. Text, images or video; Reels and Stories through platformOptions.mediaType. | |
| No | Needs an image or video on a professional account. Up to 10 items in a carousel. Caption up to 2,200 characters. | |
| Yes | Text and images. Up to 3,000 characters. | |
| TikTok | No | Needs video or photos, and an explicit privacy level in platformOptions. Check allowed values with GET /api/v1/accounts/ACCOUNT_ID/tiktok/creator-info. |
| YouTube | No | Publishes video, including Shorts with platformOptions.mediaType "short". |
| X (Twitter) | Yes | Paid plans only. Up to 280 characters including links; up to 4 images. |
Media URLs must be publicly reachable. If your files are local, upload them first through the media endpoints in the API reference; each upload is checked against the limits of the account you name, so an oversized video is refused before you schedule anything.
Plans and networks
- Free covers two connected accounts on Facebook, Instagram, LinkedIn, TikTok and YouTube, with unlimited posts and scheduling.
- Pro adds X and more connected accounts, plus analytics on Instagram, X and YouTube, A/B testing and timing suggestions.
- Agency and Enterprise are for many brands or clients.
Current prices and limits are on the pricing page.
Next steps
To post later instead of now, add scheduledAt to the POST /api/v1/posts requests in option 1. The repurpose endpoint has no schedule and publishes at once in post mode, so to schedule adapted text, preview it first and send each variant to POST /api/v1/posts with a scheduledAt. The scheduling guide covers time formats and how to change queued posts. To find out which wording works best on one network, try an A/B test.
Frequently asked questions
- Is there one request that posts to every network?
- Two options. Send one POST /api/v1/posts per connected account with the same body, or call POST /api/v1/posts/repurpose in post mode to adapt and publish to several platforms in one call.
- Can I post text only everywhere?
- Facebook, LinkedIn and X accept text-only posts. Instagram and TikTok need media, and YouTube publishes video. Each post is checked just before it is published, so one that is missing required media is refused without affecting the others.
- How do I avoid duplicate posts when retrying?
- Send an Idempotency-Key header with each POST /api/v1/posts request, a different key for each post (for example campaign plus account). Replaying the same request with the same key never publishes again: it returns the original post, or a 409 with its ID if it is still in progress or needs recovery.
- Which networks are on the Free plan?
- Facebook, Instagram, LinkedIn, TikTok and YouTube, for up to two connected accounts. Twitter/X needs a paid plan.
Start with a free account
Free includes two connected accounts, unlimited posts and scheduling, and a sandbox for testing. Some features in this guide need Pro; the pricing page lists what each plan includes.