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.
| Network | Most items in one post | Photos and videos together | Shape to ask for | Worth knowing |
|---|---|---|---|---|
| 10 | Yes | carousel | Meta crops every image to the first image's aspect ratio, square by default | |
| Threads | 20 | Yes | carousel | Meta's docs ask for at least two items |
| 20 images, or 1 video | No | carousel | LinkedIn's multi-image post takes 2 to 20 images | |
| 10 photos, or 1 video | No | carousel | Each image carries the caption unless you switch that off | |
| TikTok | 35 images, or 1 video | No | None needed: images alone make a photo post | TikTok adds a music track unless you switch it off |
| Telegram | 10 | Yes | No carousel shape | The six slides go as one album; the caption limit is 1,024 characters with files |
| X | 4 images, or 1 video | No | No carousel shape | Send the first four as an ordinary post |
| Bluesky | 4 images | No video here | No carousel shape | Send the first four as an ordinary post. Each image must be 1 MB or less |
| 1 | No | No carousel shape | A 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_musicis 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_atwithout 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-Keyheader 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:
- Trigger: a new row with a caption, a publish time and the slide links in reading order.
- 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. - One request to
POST /v1/postswith the ids, the channels,publish_atfrom the row and the per-channeloverridesfrom Step 2. Send the row's id as theIdempotency-Key, so a re-run of the scenario does not queue the carousel twice. - 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.