Skip to content
Schedule Social Media

Press Esc to close.

Instagram Content Publishing API: posts, reels, carousels

How the Instagram Content Publishing API works on both logins: containers, reels, carousels of up to 10, stories, and why Meta gives 100, 50 or 25 posts a day.

The Instagram Content Publishing API posts in two steps: you create a media container with POST /{ig-user-id}/media, then publish it with POST /{ig-user-id}/media_publish. The same flow covers single images, reels, carousels of up to 10 items and stories, on both Instagram Login and Facebook Login, and Meta's own GitHub sources state three different daily caps: 100, 50 and 25 posts.

This guide belongs to Meta API use cases: which one your app needs. It is built from Meta's official GitHub repositories (the Instagram Platform Postman collection, the Reels publishing sample and the Python Business SDK) and from our own Instagram changelog entries. Where those sources disagree, the page says so.

What this means for you

When a scheduling tool posts to Instagram for you, it first hands Instagram your photo or video, then tells Instagram to post it. Instagram fetches the file from a public web address, so the tool has to host it. You need a Business or Creator account, and every account has a daily limit on posts made this way.

The details: how the Instagram Content Publishing API works

Container, then publish

Every format follows the same steps:

  1. Create a container. POST /{ig-user-id}/media with image_url or video_url, an optional caption, and media_type for anything that isn't a single image. The response is { "id": "<IG_CONTAINER_ID>" }.
  2. Wait for video to finish. For video, read GET /{container-id}?fields=status_code until it returns FINISHED.
  3. Publish. POST /{ig-user-id}/media_publish with creation_id set to the container ID. The response is the new media ID.
POST https://graph.instagram.com/{api-version}/{ig-user-id}/media
  image_url=<PUBLIC_JPEG_URL>
  caption=<CAPTION>
→ { "id": "<IG_CONTAINER_ID>" }

POST https://graph.instagram.com/{api-version}/{ig-user-id}/media_publish
  creation_id=<IG_CONTAINER_ID>
→ { "id": "<IG_MEDIA_ID>" }

Meta's guide says it cURLs the media, so the file "must be hosted on a publicly accessible server at the time of the attempt". The container's status_code takes one of five values:

status_codeWhat Meta's guide says it means
IN_PROGRESSStill in the publishing process
FINISHEDReady to publish
PUBLISHEDAlready published
ERRORFailed to complete the publishing process
EXPIREDNot published within 24 hours

The guide recommends checking a container's status once per minute for no more than 5 minutes. Meta's Reels sample app polls faster: every 3 seconds, giving up after about 90 seconds. Both are Meta's own code, so pick an interval that fits your video sizes and watch your call budget (see Meta Graph API rate limits).

Both login paths

Instagram LoginFacebook Login
Hostgraph.instagram.comgraph.facebook.com
Token in Meta's examplesInstagram User access tokenPage access token in the Postman requests; the Facebook user token in the Reels sample app
Permissions in Meta's examplesinstagram_business_basic, instagram_business_content_publishinstagram_basic, instagram_content_publish, pages_show_list, pages_read_engagement, plus business_management in the Reels sample
Facebook PageNot neededMust be linked to the Instagram account

Which path to build on, and why, is covered in Instagram Login or Facebook Login?. Token lifetimes are in Meta access tokens.

One trap if you use the Python Business SDK: on the Instagram Login class, the publish call points at /mediapublish, while the Facebook Login class and every Postman request use /media_publish. Test that call before you rely on the SDK for Instagram Login.

Formats: images, reels, carousels and stories

FormatContainer settingsWhat Meta's sources addLast change on our changelog
Imageimage_urlJPEG only; MPO and JPS aren't supportedAI info label, June 22, 2026
Reelmedia_type=REELS, video_url or upload_type=resumableshare_to_feed, cover_url, thumb_offsetAI info label, June 22, 2026
CarouselOne container per item with is_carousel_item=true, then media_type=CAROUSEL with childrenUp to 10 items; one caption on the carousel containerAI info label, June 22, 2026
Storymedia_type=STORIES with video_url in Meta's examplesBusiness accounts only on Facebook LoginTrial Reels and media deletion, December 3, 2025

Instagram API: publish reels

Set media_type=REELS and pass the video. The VIDEO media type stopped working on November 9, 2023. One Meta source hasn't caught up: the Postman collection's image container description still lists VIDEO as an option, while its video request, updated the same day, lists only REELS and STORIES.

  • share_to_feed=true puts the reel in both Feed and the Reels tab; false keeps it in the Reels tab only.
  • cover_url is a public image for the Reels tab cover. thumb_offset picks a frame in milliseconds (default 0). If you send both, cover_url wins.
  • Video specs in Meta's Reels sample: MOV or MP4, AAC audio at up to 48 kHz, HEVC or H.264 video, 23 to 60 FPS, at most 1920 horizontal pixels, 9:16 recommended, video bitrate up to 25 Mbps, audio bitrate 128 kbps, 3 seconds to 15 minutes, 1 GB at most.
  • A published reel returns media_type VIDEO. Read media_product_type to tell reels apart.
  • Newer options: trial_params for Trial Reels, and audio from the Instagram Audio API, which our entry lists as Facebook Login.

A carousel takes one call per item plus two more. Create a container for each image or video with is_carousel_item=true. Then create the carousel container with media_type=CAROUSEL, children set to a comma-separated list of up to 10 container IDs, and the caption. Publish the carousel container once. Meta's collection says carousel images are all cropped based on the first image, 1:1 by default. If you label AI content, our entry on is_ai_generated says it goes on the carousel container only.

Stories

Set media_type=STORIES. Meta's Postman request and its Reels sample both create a video story; neither shows an image story. The collection's Facebook Login description says content publishing works for all professional accounts "except Stories, which are only available to business accounts". It says nothing on this for Instagram Login.

Large videos: resumable upload

Instead of a video_url, you can create the container with upload_type=resumable. Meta's Reels sample shows what happens next: the response carries the container ID and a uri, and the app posts the video file to that address on rupload.facebook.com with the headers Authorization: OAuth <token>, offset: 0 and file_size. Then it polls and publishes as usual. The README says to use a video URL or a file, not both.

Meta's sources disagree on who can use this. The Postman collection's publishing guide says resumable upload is "only for apps that have implemented Facebook Login for Business", yet that guide is for Instagram Login and its own story request sends upload_type=resumable to graph.instagram.com. The Python SDK accepts upload_type on both login classes.

What isn't supported

The collection's Instagram Login publishing guide lists: image formats other than JPEG, shopping tags, branded content tags and filters. The two SDK classes also differ: the Facebook Login media call accepts parameters the Instagram Login one doesn't, including is_paid_partnership and branded_content_sponsor_ids (the paid partnership label), cross_post_to_threads and poll_attachment. Meta's GitHub sources don't describe the last two, so treat them as unconfirmed.

Instagram publishing limit: 100, 50 or 25 posts a day?

SourceWhat it saysWritten
Postman collection, publishing guide100 API-published posts within a 24-hour moving period; a carousel counts as oneSeptember 10, 2025
Postman collection, carousel request50 published posts within a 24-hour period; a carousel counts as oneSeptember 10, 2025
Reels sample README25 API-published posts within a 24-hour moving periodFebruary 14, 2023

The dates come from the git history of each line. The two newer figures were written in the same commit and still disagree. The 100 and 25 figures both say the limit is enforced on media_publish, not on container creation, and the guide asks apps to enforce it themselves, "especially if your app allows app users to schedule posts to be published in the future".

Checking content_publishing_limit

Don't hard-code any of the three numbers. Ask the account:

GET /{ig-user-id}/content_publishing_limit?fields=config,quota_usage

Meta's Reels sample reads data[0].config.quota_total and data[0].quota_usage and subtracts one from the other to show the publishes left. The Python SDK offers this call on both login classes and accepts an optional since date. The sample also calls it right after login, using the response code to check that each account has access to content publishing at all.

Schedule Instagram posts with the API

There is no publish-time parameter. Neither SDK class lists one on its media creation call, so scheduling is your app's job: store the post, then create the container and publish it when it's due. Since an unpublished container expires after 24 hours, don't create it more than a day ahead. Count your own publishes against the account's quota before you queue more.

The Facebook Login class in the SDK also has a read-only GET /scheduled_media edge (caption, media type, media URL, publish_timestamp, thumbnail). Meta's GitHub sources don't say how media gets there, so don't build a scheduler on it. For the non-developer side, see how to schedule Instagram posts, and check caption length with the character counter.

Errors and status checks

Meta's GitHub sources point to an error codes reference but list no publishing error codes, so this page doesn't either. What they do show:

  • The container's status field carries a readable message next to status_code, such as "Finished: Media has been uploaded and it is ready to be published."
  • Meta's Reels sample reads id,status,status_code,video_status while a resumable upload runs. In the SDK, video_status has uploading_phase and processing_phase, and the container also has copyright_check_status with status and matches_found.
  • If you re-read media after publishing, media_url can be missing: since July 30, 2026 it is left out for protected or download-disabled media.

To hear about new comments and messages instead of polling for them, see Meta webhooks.

Changes by date

All Instagram changes are on the Instagram network page, and API versions are in Instagram API versions. Threads has its own publishing flow: see Threads API publishing.

What to do next

  • Business owners: Use a Business account if you want to schedule Stories through a tool that connects with Facebook. A tool can't publish more than your account's daily quota, whatever its plan says.
  • Marketers and agencies: Ask your tool how it handles the daily cap and failed posts, and whether it supports Stories and carousels for your account type.
  • Developers: Read content_publishing_limit before each publish, poll container status before media_publish, create containers less than 24 hours ahead, use REELS (never VIDEO), and plan for Advanced Access through Meta App Review if you'll publish for accounts you don't manage.

Questions people ask

How many posts a day can the Instagram API publish?

Meta's GitHub sources give three numbers. Its Postman collection says 100 API-published posts in a 24-hour moving period in its publishing guide and 50 in its carousel request, both added in September 2025; its Reels sample, written in February 2023, says 25. A carousel counts as one post. Read the account's real quota from content_publishing_limit instead of hard-coding any of them.

How many items can an Instagram API carousel have?

Up to 10 images, videos or a mix of the two. You create one container per item with is_carousel_item set to true, then a carousel container with media_type CAROUSEL and the item IDs in children, and you publish that one container. Meta's collection says carousel images are all cropped based on the first image, 1:1 by default.

Can you schedule Instagram posts with the API?

Not with a publish-time setting: neither of the Python SDK's media creation calls takes one. Your app stores the post and runs the container and publish steps when it is due. Meta's guide says an unpublished container expires after 24 hours and recommends that apps which schedule posts enforce the daily limit themselves.

Can the Instagram API publish Stories?

Yes, with media_type set to STORIES on the container. Meta's Postman collection says that on the Facebook Login path Stories publishing is only available to business accounts, not creator accounts. It doesn't say whether the same rule applies to Instagram Login.

Why does a reel I published come back as media_type VIDEO?

That's expected. Meta's collection says a published reel returns VIDEO in media_type, and that you read media_product_type to tell whether a video is a reel. You still create it with media_type REELS, since the VIDEO publishing type stopped working on November 9, 2023.

Sources

Related

Get an email when a platform changes its API

One email per new entry: what changed, who is affected, and the deadline.

Follow with RSS, or per platform, for example X or Meta.