How to Automate Carousel Posting on Five Networks

To automate carousel posting, put the slides in order once and send them in a single request that holds each network to its own ceiling. PostWharf accepts a carousel of up to 10 items on Instagram, 20 on Threads, 20 images on LinkedIn, 10 photos on Facebook and 35 images as a TikTok photo post, from one API call, one wharf command or one plain-language prompt to an MCP agent. Telegram has no carousel shape but sends up to 10 photos and videos as one album. X, Bluesky and Pinterest take fewer files, so you send them the opening slides as an ordinary post: four on X and Bluesky, one on Pinterest.

By · · 9 min read

Drafted with AI assistance from our own research and Search Console data, and reviewed by Rahul A before publishing. Rules and prices change; check the linked official source before you act.

A carousel counts once against your plan however many networks it goes to, and PostWharf charges per brand rather than per channel. See per-brand pricing.

What each network accepts in one carousel

The figures below are the ceilings PostWharf checks a post against before it is queued. GET /v1/platforms and wharf platforms return them as data, so a script can read them instead of hard-coding them. The last column draws on each network's own developer documentation, PostWharf's own settings and, for Pinterest, a test post.

NetworkMost items in one postPhotos and videos togetherShape to ask forWorth knowing
Instagram10YescarouselMeta crops every image to the first image's aspect ratio, square by default
Threads20YescarouselMeta's docs ask for at least two items
LinkedIn20 images, or 1 videoNocarouselLinkedIn's multi-image post takes 2 to 20 images
Facebook10 photos, or 1 videoNocarouselEach image carries the caption unless you switch that off
TikTok35 images, or 1 videoNoNone needed: images alone make a photo postTikTok adds a music track unless you switch it off
Telegram10YesNo carousel shapeThe six slides go as one album; the caption limit is 1,024 characters with files
X4 images, or 1 videoNoNo carousel shapeSend the first four as an ordinary post
Bluesky4 imagesNo video hereNo carousel shapeSend the first four as an ordinary post. Each image must be 1 MB or less
Pinterest1NoNo carousel shapeA five-image test post arrived as a single pin

YouTube takes no images at all, so a carousel reaches it only as a video made from the slides, which the composer's "Make a video from these" button builds.

The mix column decides more than the count. A set with one clip among the photos fits Instagram and Threads, but LinkedIn, Facebook and TikTok take either photos or a single video, so those channels need a stills-only list. Pinterest is the network where the documented limit and the result differ: a test post sent with five images arrived as one pin, so PostWharf accepts one image there until a real post comes back as a carousel.

Prepare the slides before you automate anything

PostWharf does not crop, resize or convert a picture. It publishes the exact image file you give it, so the decisions that shape how a carousel looks are made before the upload.

  • Export every slide at one size. Instagram crops the whole set to the shape of the first slide, so a square cover followed by portrait slides loses the top and bottom of every portrait one.
  • Number the files in reading order. The order of the media list is the order a reader swipes, not the order the files finished uploading.
  • Stay inside PostWharf's upload rules. JPEG, PNG, WebP, GIF, MP4, MOV or WebM, up to 25 MB per image and 512 MB per video, except on Bluesky, where PostWharf caps each image at 1 MB.
  • Write alt text as you register each slide. It stays with the file. So far only Bluesky carries it through as an image description, but it is far easier to write once than to add later.

The upload checks that catch most failed media posts, from file type to reachable addresses, are covered in what to check before a social media API upload.

Step 1: Register the slides

Each slide becomes a media id. If the slides already sit at a public https address, POST /v1/media registers each one by link and nothing is uploaded. If they are on your disk, POST /v1/media/upload-url returns a signed address to PUT the bytes to, together with the media id.

POST https://api.postwharf.com/v1/media
Authorization: Bearer wf_live_...

{ "url": "https://cdn.example.com/oct/01.jpg", "kind": "image", "alt": "Cover: six changes in the October release" }

Keep the ids in slide order. That list is the carousel.

Step 2: Send one post with a shape for each network

A post_type set at the top of the request applies to every channel, and a network without that shape refuses the whole post. On a list that mixes networks, set the shape per channel inside overrides, which also takes a different caption, file list or setting for one network.

POST https://api.postwharf.com/v1/posts
Authorization: Bearer wf_live_...
Idempotency-Key: oct-release-carousel

{
  "text": "Six things we changed in the October release.",
  "media": ["med_01", "med_02", "med_03", "med_04", "med_05", "med_06"],
  "channels": ["ch_ig", "ch_li", "ch_th", "ch_fb", "ch_tt", "ch_x"],
  "publish_at": "2026-11-03T09:00",
  "overrides": {
    "ch_ig": { "post_type": "carousel" },
    "ch_li": { "post_type": "carousel" },
    "ch_th": { "post_type": "carousel" },
    "ch_fb": { "post_type": "carousel", "options": { "set_caption_for_each_image": false } },
    "ch_x":  { "media": ["med_01", "med_02", "med_03", "med_04"] }
  }
}

What each line does:

  • Instagram, LinkedIn, Threads and Facebook get all six slides as a carousel. Facebook's override switches off the caption on each image, so only the carousel carries the text.
  • TikTok needs no override. A TikTok post carrying only images is a photo post, with TikTok's automatic music on unless auto_add_music is set to false.
  • X has no carousel and takes four images, so its override sends the first four. Keep the opening slides rather than picking favourites: the order is the story.
  • publish_at without an offset is read in the workspace's own time zone, so 09:00 stays 09:00 through a clock change. Leave it out and the post goes at once.
  • The Idempotency-Key header makes a repeat of the same call return the first post instead of making a second one, which is what you want from a scheduler that retries.

Every field and refusal is set out in the REST API, MCP server and CLI documentation.

Step 3: Rehearse it with a dry run

Add "dry_run": true to the same body and PostWharf runs every check the real call would run, then writes nothing: no post, no upload, and nothing counted against the month. A set that breaks a network's rule, such as seven slides for X or a clip among LinkedIn's photos, is refused in the rehearsal exactly as it would be for real, and a refusal over files names each channel and the override that fixes it. Run the rehearsal once per new template, and again whenever the slide count changes.

The same carousel from the command line

The wharf CLI sends the same request from a terminal, a cron job or a CI step. Local paths are uploaded for you, and --media repeats in the order the slides should appear.

npm i -g postwharf
export POSTWHARF_API_KEY=wf_live_...

wharf post "Six things we changed in the October release." \
  --media ./oct/01.jpg --alt "Cover: six changes" \
  --media ./oct/02.jpg --media ./oct/03.jpg --media ./oct/04.jpg \
  --media ./oct/05.jpg --media ./oct/06.jpg \
  --to instagram,linkedin,threads,facebook,tiktok \
  --type carousel \
  --set-for facebook:set_caption_for_each_image=false \
  --at "tue 9am" --dry-run

--type carousel works here because every network on the list has that shape. Add X and the whole post would be refused, so on a mixed list use --type-for instagram:carousel once per network instead. The CLI has no per-network file list, which means X gets its four slides from a second command or from the API's override. --dry-run reports each network's count against its own ceiling; drop it to queue the post. The command exits non-zero when a delivery fails, so a scheduled job fails loudly instead of going quiet.

The same carousel from an MCP agent

Point any MCP client that speaks Streamable HTTP at https://mcp.postwharf.com/mcp with a workspace key. One key reaches one brand, so an agent cannot put a client's carousel on another client's accounts. Then ask in plain words:

Schedule these six slides as a carousel for Tuesday at 9am on every channel, in this order: (six links). Caption: "Six things we changed in the October release."

The server's own instructions tell the agent how to fit a set of pictures to each network, so you do not do the arithmetic. It reads each network's ceiling and shapes with describe_networks, registers the links with upload_media (or stage_upload for a file it made itself), puts the full set on the post and then decides per channel: a carousel where the set fits and the network has the shape, the first few slides where the network takes fewer, and a native photo post on TikTok. It schedules with schedule_post, and checks health and get_status before it reports anything as published.

Schedule carousels from n8n or Make

Neither tool needs a custom node. In n8n it is an HTTP Request node with the workspace key as a bearer token; in Make, an HTTP module. A sheet-driven build looks like this:

  1. Trigger: a new row with a caption, a publish time and the slide links in reading order.
  2. One request per slide to POST /v1/media, with the link, "kind": "image" and the alt text. Collect the ids in the row's slide order, not in the order the responses come back.
  3. One request to POST /v1/posts with the ids, the channels, publish_at from the row and the per-channel overrides from Step 2. Send the row's id as the Idempotency-Key, so a re-run of the scenario does not queue the carousel twice.
  4. Optional: a webhook for delivery receipts that writes each network's post link back to the row.

Check what went out

An accepted request is not yet a carousel in anyone's feed. Poll GET /v1/posts/:id, subscribe to the webhook, or run wharf status. Each delivery gains a link to the post on the network, or a url_state saying why it has none: pending means it went out and the address is not known yet. wharf status also marks a delivery that was recorded but never sent. If one network failed, wharf retry <id> (or retry_post from an agent) sends the post again to that network only, so the others do not get a duplicate. Why an API acknowledgement on its own proves little is covered in posting to Instagram from the command line.

In the dashboard the same rules apply without any code: the composer card for a network that cannot take the whole set offers to keep the first few slides for that network alone.

Sources consulted: Meta for Developers (developers.facebook.com): Instagram content publishing, Threads posts · TikTok for Developers (developers.tiktok.com): Content Posting API, photo post · LinkedIn Marketing API documentation: MultiImage API

Common questions

Can the Instagram API post a carousel with videos in it?

Yes. Meta's content publishing API takes up to 10 images, videos or a mix in one carousel, and counts it as one post against the account's publishing limit. PostWharf accepts the same mix on Instagram. Every image is cropped to the first one's aspect ratio, so export the set at one size.

How many images can a LinkedIn multi-image post carry through the API?

Between 2 and 20, according to LinkedIn's MultiImage API documentation, and PostWharf accepts up to 20. A LinkedIn post carries either images or one video, never both, so a carousel with a clip in it needs a stills-only set for LinkedIn.

Can I schedule a TikTok photo carousel through an API?

Yes. TikTok's Content Posting API has a photo post that takes up to 35 images. Through PostWharf, a TikTok post carrying only images goes out as a photo post at the time you set, and TikTok adds a music track unless you switch auto_add_music off.

PostWharf is priced per workspace rather than per connected channel, and every plan carries unlimited channels. See per-brand pricing.