How to Publish Instagram Reels via API: Upload, Schedule, and Automate Short-Form Video

A deep technical guide to publishing Instagram Reels through Meta's Content Publishing API — container creation, video specs, cover images, audio limitations, and common errors.

How to Publish Instagram Reels via API: Upload, Schedule, and Automate Short-Form Video

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:

StatusMeaning
IN_PROGRESSVideo is still being processed
FINISHEDReady to publish
PUBLISHEDAlready published
EXPIREDNot published within 24 hours
ERRORProcessing 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

SpecRequirement
FormatMP4 or MOV. No edit lists, moov atom at the front of the file
Video codecH.264 or HEVC, progressive scan, closed GOP, 4:2:0 chroma subsampling
Audio codecAAC, 48 kHz max sample rate, mono or stereo
Frame rate23–60 FPS
Aspect ratio9:16 required for Reels tab eligibility
Duration5–90 seconds for Reels tab eligibility
Max file size100 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

ErrorCauseFix
400 on media_publishContainer not yet FINISHEDPoll status before publishing
Error 2207001Server-side upload failureRetry 1–2 times within 30 seconds to 2 minutes, then create a new container
Error 9, subcode 2207042Publishing rate limit exceededBack off and check content_publishing_limit
Format/spec errorsVideo does not meet technical requirementsValidate codec, resolution, duration, file size before upload
Creator Account errorInstagram Creator account, not BusinessSwitch 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

ReelsFeed videosStories
media_typeREELSVIDEOSTORIES
Duration5–90s (Reels tab)Up to 60 minUp to 60s
Aspect ratio9:16Flexible9:16
Cover imagecover_url / thumb_offsetN/AN/A
share_to_feedYesN/ANo
Upload host (resumable)rupload.facebook.comrupload.facebook.comgraph.facebook.com
Carousel supportNoNoNo

The same Reel, through Postproxy

Here is what publishing a Reel looks like through Postproxy:

Terminal window
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:

Terminal window
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.

What Postproxy handles

Postproxy manages the Reels-specific complexity so your system does not have to:

  • Meta app review and approved permissions
  • Instagram Business account token exchange and refresh
  • Container creation with correct media_type and video parameters
  • Resumable video uploads via rupload.facebook.com
  • Status polling loop until FINISHED
  • Cover image and share_to_feed configuration
  • Rate limit monitoring via content_publishing_limit
  • Per-platform error reporting with actionable failure reasons

Your system sends a video. Postproxy publishes it as a Reel.

Connect your Instagram account and start publishing through the Postproxy API.

Ready to get started?

Start with our free plan and scale as your needs grow. No credit card required.