Publishing to Instagram via API: A technical guide

Understanding permissions, the container model, video uploads, and API endpoints for Instagram content publishing.

Publishing to Instagram via API: A technical guide

Before you start: App review

Before your app can publish to Instagram professional accounts in production, your permissions need to pass Meta’s app review:

  1. App Review - Each permission requires a separate app review submission with a screencast demonstrating how your app uses that specific permission
  2. Advanced Access - Required if your app publishes on behalf of Instagram accounts you don’t own or manage

The review process takes 2-4 weeks per Meta’s documentation. Each screencast must show the complete user journey for that permission in your app.

Required permissions

To publish content and access insights on an Instagram professional account, your app needs these permissions approved:

  • instagram_business_basic - Access basic account information
  • instagram_business_content_publish - Create and publish media
  • instagram_business_manage_comments - Manage comments on media
  • instagram_business_manage_insights - Access account and media analytics

Each of these permissions needs its own app review submission with a screencast.

The container model

Instagram publishing uses a two-step process that differs from Facebook’s direct endpoints:

  1. Create a container — POST to /{ig-user-id}/media to create the media container and upload the content
  2. Publish the container — POST to /{ig-user-id}/media_publish with the container ID to make it live

All media must be hosted on a publicly accessible URL at the time of the create request. Meta will cURL your media directly from that URL.

Publishing images

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

{
"image_url": "https://example.com/photo.jpg",
"caption": "Your caption text"
}

Returns a container ID on success. Publish it with a POST to /{ig-user-id}/media_publish:

{
"creation_id": "<IG_CONTAINER_ID>"
}

Only JPEG is supported. Extended JPEG formats such as MPO and JPS are not.

Publishing videos

Videos use the same create-then-publish flow with an additional media_type parameter:

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

{
"video_url": "https://example.com/video.mp4",
"media_type": "VIDEO",
"caption": "Your caption text"
}

For large videos or unreliable connections, use the resumable upload flow instead:

Step 1: Create a resumable upload container

POST to /{ig-user-id}/media with upload_type set to resumable:

{
"media_type": "VIDEO",
"upload_type": "resumable"
}

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

Step 2: Upload the video

POST to https://rupload.facebook.com/ig-api-upload/{api-version}/{ig-container-id} with headers:

Authorization: OAuth <ACCESS_TOKEN>
offset: 0
file_size: <file_size_in_bytes>

Include the video as binary data in the request body.

Returns: {"success": true, "message": "Upload successful."}

Step 3: Publish the container

POST to /{ig-user-id}/media_publish with the container ID from step 1.

Publishing carousels

Carousels allow up to 10 images and/or videos in a single post. This requires three steps: create containers for each item, create a parent carousel container, then publish.

Step 1: Create item containers

Create a container for each image or video with is_carousel_item set to true:

{
"image_url": "https://example.com/photo1.jpg",
"is_carousel_item": true
}

Repeat for each item, up to 10.

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

{
"media_type": "CAROUSEL",
"children": "<CONTAINER_1>,<CONTAINER_2>,<CONTAINER_3>",
"caption": "Carousel caption"
}

Step 3: Publish

POST to /{ig-user-id}/media_publish with the carousel container ID.

All carousel images are cropped to match the aspect ratio of the first image, defaulting to 1:1.

Reels and stories

Reels and stories use the same create-then-publish flow with different media_type values:

  • Reels: Set media_type to REELS and provide video_url
  • Stories: Set media_type to STORIES and provide image_url or video_url

Trial reels — shared only to non-followers initially — are supported via the trial_params parameter:

{
"media_type": "REELS",
"video_url": "https://example.com/video.mp4",
"trial_params": {
"graduation_strategy": "MANUAL"
}
}

graduation_strategy accepts MANUAL (graduated in-app by the user) or SS_PERFORMANCE (automatically graduated based on performance).

Checking container status

If a publish request doesn’t return a media ID, check the container’s status:

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

Possible values:

  • IN_PROGRESS — Still processing
  • FINISHED — Ready to publish
  • PUBLISHED — Successfully published
  • EXPIRED — Container was not published within 24 hours
  • ERROR — Publishing failed

Query once per minute, for no more than 5 minutes.

Rate limits

Instagram accounts are limited to 100 API-published posts per 24-hour moving period. Carousels count as a single post. The limit is enforced at the media_publish endpoint.

To check current usage before publishing, GET /{ig-user-id}/content_publishing_limit.

The same video, through Postproxy

Here’s how it’s done with Postproxy. One simple request with only what matters:

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/video.mp4"]
}'

One request. Postproxy handles the container creation, the resumable upload, the status polling, and the publish step.

What Postproxy handles

Postproxy maintains approved permissions and handles the complexity:

  • All required permissions approved through app review
  • Instagram User access token exchange and refresh
  • The two-step container creation and publishing flow
  • Resumable video uploads via rupload.facebook.com
  • Unified API for images, videos, carousels, reels, and stories
  • Rate limit monitoring and request pacing

Your system sends content. Postproxy handles the Instagram-specific implementation.

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.