Why Reels get their own guide

The Instagram integration guide covers the full Content Publishing API — images, videos, carousels, stories. But Reels have enough unique requirements (video specifications, cover image handling, audio constraints, duration quirks) that developers keep hitting the same problems.

This guide covers the Reels-specific publishing flow in detail. If you need the broader Instagram API overview, start with the integration guide first.

Before you start: account type and permissions

Reels publishing through the API only works with Instagram Business accounts. Creator accounts are not supported for content publishing via the API — this is a common source of confusion.

Your app needs these permissions approved through Meta’s app review:

  • instagram_business_basic — access basic account information
  • instagram_business_content_publish — create and publish media

These replaced the older instagram_basic and instagram_content_publish scopes, which were deprecated on January 27, 2025. If your app still references the old scope names, update them before submitting for review.

Each permission requires a separate app review submission with a screencast demonstrating the complete user flow. Expect 2–4 weeks for review.

The Reels publishing flow

Like all Instagram content, Reels use the container model — create a container, wait for processing, then publish. But Reels add an important middle step that you cannot skip.

Step 1 — Create the container

POST to /{ig-user-id}/media:

{

"media_type": "REELS",

"video_url": "https://example.com/video.mp4",

"caption": "Your caption text",

"cover_url": "https://example.com/cover.jpg",

"share_to_feed": true

}

The video_url must point to a publicly accessible file. Meta’s servers fetch the video from your URL directly — there is no direct file upload through the standard container flow.

For large files or unreliable hosting, use the resumable upload flow instead. POST to /{ig-user-id}/media with upload_type set to resumable and media_type set to REELS, then upload the binary to https://rupload.facebook.com/ig-api-upload/{api-version}/{ig-container-id}.

Returns: {"id": "<CONTAINER_ID>"}

Step 2 — Poll for processing status

This step is critical. Do not skip it.

GET /{container-id}?fields=status_code:

{

"status_code": "IN_PROGRESS",

"id": "<CONTAINER_ID>"

}

Wait until status_code returns FINISHED. If you call the publish endpoint before the container is ready, you get a 400 error.

Possible status values:

Status Meaning
IN_PROGRESS Video is still being processed
FINISHED Ready to publish
PUBLISHED Already published
EXPIRED Not published within 24 hours
ERROR Processing failed

Meta recommends polling once per minute for no more than 5 minutes. In practice, most Reels containers finish processing within 30 seconds to 2 minutes depending on file size and server load.

Step 3 — Publish

POST to /{ig-user-id}/media_publish:

{

"creation_id": "<CONTAINER_ID>"

}

Returns the published Instagram Media ID on success.

Video specifications

Spec Requirement
Format MP4 or MOV. No edit lists, moov atom at the front of the file
Video codec H.264 or HEVC, progressive scan, closed GOP, 4:2:0 chroma subsampling
Audio codec AAC, 48 kHz max sample rate, mono or stereo
Frame rate 23–60 FPS
Aspect ratio 9:16 required for Reels tab eligibility
Duration 5–90 seconds for Reels tab eligibility
Max file size 100 MB

The API technically accepts videos up to 15 minutes, but only videos between 5 and 90 seconds with a 9:16 aspect ratio are eligible to appear in the Reels tab. Anything outside that range publishes as a regular video post instead.

The native Instagram app now supports Reels up to 3 minutes (and longer for some accounts), but the Graph API has not caught up. If your workflow generates videos longer than 90 seconds, they cannot be published as Reels through the API.

Cover image handling

You have three options for the Reel’s cover/thumbnail:

Option 1 — Custom cover image (cover_url):
Provide a URL to an external image. Recommended size is 1080 × 1920 pixels (9:16). If the image does not match 9:16, Instagram crops the middlemost 9:16 rectangle.

The cover displays as a center-cropped 1080 × 1080 square on the profile grid, so the center of your image needs to look good at that crop.

Option 2 — Frame selection (thumb_offset):
Specify a millisecond offset into the video to select a specific frame as the thumbnail. Default is 0 (first frame).

Option 3 — Auto-generated:
If you provide neither cover_url nor thumb_offset, Instagram auto-selects a frame.

If you set both cover_url and thumb_offset, the cover image takes precedence.

Audio limitations

You cannot add Instagram’s music library tracks through the API. No trending sounds, no catalogue music, no sound effects from Instagram’s library. If your Reel needs music, it must be embedded in the video file before upload.

The audio_name parameter lets you name the Reel’s audio, but you can only name it once — either during container creation or afterward from the audio page in the app.

Audio specifications:

  • Codec: AAC
  • Sample rate: 48 kHz maximum
  • Channels: mono or stereo
  • Max audio file size: 8 MB

The share_to_feed parameter

This controls whether the Reel appears in the main profile feed in addition to the Reels tab:

  • share_to_feed=true — Reel appears in both the Reels tab and the main feed
  • share_to_feed=false or omitted — Reel appears only in the Reels tab

This is a hint, not a guarantee. Instagram may override this based on the account’s settings.

Trial Reels

Trial Reels are shared only to non-followers initially, letting you test content before committing to your full audience:

{

"media_type": "REELS",

"video_url": "https://example.com/video.mp4",

"caption": "Testing this format",

"trial_params": {

"graduation_strategy": "MANUAL"

}

}

graduation_strategy accepts:

  • MANUAL — you graduate the Reel to your full audience manually in the app
  • SS_PERFORMANCE — Instagram automatically graduates the Reel based on engagement performance

Common errors

Error Cause Fix
400 on media_publish Container not yet FINISHED Poll status before publishing
Error 2207001 Server-side upload failure Retry 1–2 times within 30 seconds to 2 minutes, then create a new container
Error 9, subcode 2207042 Publishing rate limit exceeded Back off and check content_publishing_limit
Format/spec errors Video does not meet technical requirements Validate codec, resolution, duration, file size before upload
Creator Account error Instagram Creator account, not Business Switch the account type to Business

Meta’s recommendation for upload failures: retry only 1–2 times within 30 seconds to 2 minutes. If it still fails, generate a new media container rather than retrying the same one.

Rate limits

Instagram accounts are limited to 100 API-published posts per rolling 24-hour window. This includes all content types — Reels, images, carousels, stories. Carousels count as a single post.

Check current usage before publishing:

GET /{ig-user-id}/content_publishing_limit

The limit is enforced at the media_publish endpoint, not at container creation. You can create containers freely, but publishing is throttled.

Reels vs. feed videos vs. stories

Reels Feed videos Stories
media_type REELS VIDEO STORIES
Duration 5–90s (Reels tab) Up to 60 min Up to 60s
Aspect ratio 9:16 Flexible 9:16
Cover image cover_url / thumb_offset N/A N/A
share_to_feed Yes N/A No
Upload host (resumable) rupload.facebook.com rupload.facebook.com graph.facebook.com
Carousel support No No No

The same Reel, through Postproxy

Here is what publishing a Reel looks like through Postproxy:

curl -X POST "https://api.postproxy.dev/api/posts" \
     -H "Authorization: Bearer YOUR_API_KEY" \
     -H "Content-Type: application/json" \
     -d '{
       "post": {
         "body": "3 tips that changed how we approach customer onboarding"
       },
       "profiles": ["instagram"],
       "media": ["https://example.com/reel.mp4"]
     }'

One request. Postproxy handles the container creation, the resumable upload to rupload.facebook.com, the status polling loop, the publish call, and returns the result.

If you want to publish the same video as a Reel on Instagram, a TikTok, and a YouTube Short simultaneously, add the other profiles:

curl -X POST "https://api.postproxy.dev/api/posts" \
     -H "Authorization: Bearer YOUR_API_KEY" \
     -H "Content-Type: application/json" \
     -d '{
       "post": {
         "body": "3 tips that changed how we approach customer onboarding"
       },
       "profiles": ["instagram", "tiktok", "youtube"],
       "media": ["https://example.com/reel.mp4"]
     }'

For a comparison of how the three short-form video platforms differ, see Instagram Reels vs TikTok vs YouTube Shorts: publishing via API.