Skip to main content

1. Overview

Instagram publishing uses the Meta Graph API two-step flow: SocialAPI creates a media container, polls until the container is ready, then publishes it. All post types (image, video, reel, carousel, story) go through this same pipeline.

2. Supported media

content_type is required when publishing or scheduling an Instagram post. Without it, validation returns an error. When saving a draft (without publishing), content_type can be omitted and SocialAPI auto-detects at publish time: multiple media_ids produce a carousel, a single entry produces a feed image or reel depending on file extension.
For Instagram feed images, use JPEG. PNG uploads can be rejected by Meta at the container-creation step. This is a Meta-side constraint, so SocialAPI does not block a PNG in advance; if a feed image fails to publish, re-encode it as JPEG.
Story publishing is supported via the API using content_type: "stories". Note that stories expire after 24 hours and the Instagram platform does not support captions on stories. Caption limit: 2200 characters. Carousel limits: 2 to 10 items. Carousel child containers do not accept captions; only the parent container carries the caption.
Attach media by uploading it first and passing the returned media_id in the media_ids array. There is no image_url, video_url, or media_urls field: passing a raw public URL is silently ignored, and the post publishes with no media (Instagram then returns The parameter image_url is required). Upload in one step with POST /v1/media/upload (multipart), or use the presigned-URL flow (GET /v1/media/upload-urlPUT the file → POST /v1/media/:id/verify). The verify step is required: without it the media stays pending and publishing fails with Media not found.

3. Create post

Use POST /v1/posts with targets targeting an Instagram account. The text field becomes the caption.

Platform data fields

Pass these inside platform_data.instagram: SocialAPI forwards any additional keys in platform_data.instagram directly to the underlying platform API. These fields are not validated by SocialAPI and may break if the platform changes its API. See Instagram Publishing API reference for the full list of supported parameters.

Scheduling

Set scheduled_at to an ISO 8601 timestamp (UTC) to defer publishing:

First comment

Set first_comment to a string to post an automated comment immediately after publish. This is best-effort: if the comment fails (for example due to a temporary rate limit), the post is still considered published.

4. Update post

Instagram does not support editing a published post’s caption or media via the API. PATCH /v1/posts/:pid for an Instagram target returns 501 Not Implemented. If you need to correct a caption, delete the post and recreate it.

5. Delete post

Or, to delete only the Instagram target of a cross-platform post:
Deletion calls DELETE /{ig-media-id} on the Meta Graph API. If the media ID no longer exists on Instagram, the API returns success.

6. Retrieve posts

Use GET /v1/posts to list posts. Filter by platform or account:
Each post includes a targets array with per-platform status and engagement metrics:
Metrics notes:
  • likes, comments, and shares are synced periodically from the Meta Graph API.
  • saves is not available from the Instagram API and is always 0.
  • shares is 0 because SocialAPI does not yet sync the shares_count field from the Graph API.
  • metrics_synced_at reflects when SocialAPI last refreshed the metrics from Instagram.

7. Quirks, errors, and recovery

Container polling

After creating a media container, SocialAPI polls the container status before publishing. Instagram processes images almost instantly, but videos and reels can take up to 5 minutes (60 attempts at 5-second intervals). If the container does not reach FINISHED within that window, the publish fails with 504 Gateway Timeout and the post target is marked failed. Because presigned S3 URLs do not reliably expose file extensions in the path, SocialAPI polls all containers unconditionally, not only video ones. Only the parent carousel container accepts a caption. Child item containers are created without captions. Passing a caption on a carousel child is silently ignored by the Meta Graph API; SocialAPI does not forward captions to child containers.

First comment is non-blocking

If first_comment is set and the comment fails after publish, the post remains published. The comment failure is logged but does not roll back or change the post status.

Stories expire

Instagram Stories expire 24 hours after posting. The post record in SocialAPI is not automatically removed when the story expires on Instagram.

Error shapes

When a publish fails, the post target’s error field contains a structured error:

Recovery

  • Rate limit: Retry the post via POST /v1/posts/:pid/retry after waiting. SocialAPI applies exponential backoff for scheduled retries.
  • Auth error: Disconnect and reconnect the Instagram account through the OAuth flow to obtain a fresh token.
  • Container timeout: Usually caused by a large video file or a slow upstream URL. Re-upload the media and retry.

8. Full worked example

The following example publishes a Reel with a cover image, a collaborator tag, and a first comment. Step 1: Upload media
Response:
Upload the file, then verify:
Step 2: Publish the post
Step 3: Check status
Response once published:

9. Required OAuth scopes

SocialAPI’s managed Meta App requests the following scopes on your behalf during the OAuth flow. This is informational — you do not need to configure anything. To verify which scopes your connected account has granted, call GET /v1/accounts/:id/limits.