Post to Instagram via API Reels, carousels and Stories

Schedule Instagram photos, carousels, Reels and Stories from your backend or your AI agent. Upload the media, send one POST /v1/posts, and get a signed webhook when it is live.

Base URL https://api.so-me.studio/v1 · Auth X-API-Key · socialMedia: INSTAGRAM

What you can publish to Instagram

Send one of these values as postType. Every post needs text, and photos or videos are attached by fileId from your media library.

IMAGE

A single photo in the feed.

CAROUSEL

2 to 10 photos in one swipeable post. MULTIPLE_IMAGES is accepted as well.

REEL

One video, published as a Reel.

VIDEO

One video, which Instagram also publishes as a Reel. Its size rules are looser than those of REEL.

STORY

One photo or video as a Story. Instagram shows no caption on Stories.

Schedule a Instagram post

Upload the media, then create the post. Leave out scheduledAt to publish right away.

  1. Reserve an upload URL

    POST /v1/media/presign-upload adds the file to your media library and returns a fileId and a presigned uploadUrl.

    Reserve an upload URL
    curl -X POST https://api.so-me.studio/v1/media/presign-upload \
      -H "X-API-Key: $SOME_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{"files":[{"filename":"launch-reel.mp4","mimetype":"video/mp4","size":48211904}]}'
    
    # → [{ "fileId": "…", "uploadUrl": "https://…", "fileSrc": "…", "s3Key": "…" }]
  2. Upload the file

    PUT the bytes to uploadUrl with exactly the Content-Type you declared. The URL is valid for one hour.

    Upload the file
    curl -X PUT "$UPLOAD_URL" \
      -H "Content-Type: video/mp4" \
      --upload-file ./launch-reel.mp4
  3. Create the post

    POST /v1/posts with the fileId. The response is the post with status SCHEDULED, and it publishes at scheduledAt through a queue that retries on failure.

    Create the post
    curl -X POST https://api.so-me.studio/v1/posts \
      -H "X-API-Key: $SOME_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "socialMedia": "INSTAGRAM",
        "postType": "REEL",
        "text": "Behind the scenes of launch week",
        "fileIds": ["<fileId>"],
        "scheduledAt": "2026-11-03T15:00:00Z",
        "firstComment": "#launchweek #buildinpublic"
      }'

accountId is optional when the workspace has one Instagram account. Otherwise pass an id from GET /v1/accounts.

Files attached with fileIds are checked against the Instagram limits below before anything is queued. A file that breaks a rule returns 400 with a report per file.

Instagram options

The fields that change how a post is published on Instagram.

FieldWhat it does
firstCommentA comment posted under the post right after it goes live, up to 2,200 characters. Good for hashtags or a link.
metaData.taggedPeopleAn array of public Instagram usernames to tag on photos, carousel photos and Reels. Tagging is best effort: a wrong username never blocks the post.
accountIdThe Instagram account to post from, as listed by GET /v1/accounts. Optional when the workspace has only one.

Instagram media limits

Social media studio checks each file against these limits before it publishes. They are our configured limits, not a promise from Instagram: GET /v1/media/rules returns the live table, and POST /v1/media/validate checks a file without posting it.

Post type IMAGE

Formats
JPEG, PNG, WebP
Max file size
8 MB
Files per post
1
Dimensions
≥ 320 px wide
Aspect ratio
4:5 to 1.91:1

Post type CAROUSEL

Formats
JPEG, PNG, WebP
Max file size
8 MB each
Files per post
2–10
Dimensions
≥ 320 px wide
Aspect ratio
4:5 to 1.91:1

Post type REEL

Formats
MP4, MOV
Max file size
300 MB
Files per post
1
Max duration
15 min
Dimensions
≥ 540 × 960 px, ≤ 1920 px wide
Video codecs
H.264, H.265
Frame rate
≤ 60 fps

Post type VIDEO

Formats
MP4, MOV
Max file size
300 MB
Files per post
1
Max duration
15 min
Dimensions
320–1920 px wide
Video codecs
H.264, H.265
Frame rate
≤ 60 fps

Post type STORY

Formats
JPEG, PNG, MP4, MOV
Max file size
100 MB
Files per post
1
Max duration
60 s
Dimensions
≥ 320 px wide
Aspect ratio
1:2 to 1.91:1

Know when it is live

Publishing is asynchronous. Subscribe to post.published and post.failed, or poll GET /v1/posts/:id until postStatus is POSTED or FAILED.

Subscribe once
curl -X POST https://api.so-me.studio/v1/webhooks/subscriptions \
  -H "X-API-Key: $SOME_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/hooks/social",
    "categories": ["post"],
    "events": ["post.published", "post.failed"]
  }'

# The response includes the secret that signs every delivery.
What each delivery looks like
POST /hooks/social
X-Webhook-Event: post.published
X-Webhook-Signature: <hex HMAC-SHA256 of the raw body>

{
  "event": "post.published",
  "category": "post",
  "timestamp": "2026-11-03T15:00:07.412Z",
  "data": { "postId": "…", "platform": "INSTAGRAM" }
}

Every delivery is signed with HMAC-SHA256 in X-Webhook-Signature. post.failed fires after the last retry; fix the cause and call POST /v1/posts/:id/retry. A first comment reports on its own with post.first_comment_posted or post.first_comment_failed.

Building an AI agent?

The same API key drives an MCP server with 200+ tools and a CLI, so an agent can post to Instagram without hand-written HTTP calls.

MCP server

Add the server to Claude, Cursor or any MCP client with your API key. OAuth works too. For Instagram, the agent calls these tools with the same fields as the REST request:

  • presign_media_upload
  • validate_post_media
  • create_post
mcp.json
{
  "mcpServers": {
    "so-me-studio": {
      "url": "https://api.so-me.studio/mcp",
      "headers": { "X-API-Key": "sk_live_…" }
    }
  }
}

CLI

Install it with npm i -g @social-media-scheduler/cli. It uploads local files for you and prints JSON, so a script or a CI job can schedule a Instagram post in one command.

so-me
so-me posts:create --platform INSTAGRAM --post-type REEL \
  -m ./launch-reel.mp4 \
  -c "Behind the scenes of launch week" \
  -s 2026-11-03T15:00:00Z \
  --first-comment "#launchweek #buildinpublic"

API, CLI and MCP access is included on every paid plan: Lite, Creator, Standard, Advanced and Lifetime. See plans and limits

Keep reading

Other platform guides

An Instagram professional account, Business or Creator. Instagram does not let apps publish to personal accounts. You connect the account once in the Social media studio dashboard.

No. Instagram needs a photo or video on every post, so a text-only Instagram post fails. Attach media with fileIds, and the media check runs before the post is queued.

Yes. Send postType STORY with one photo or video and a scheduledAt time. The API still requires text, but Instagram does not display captions on Stories.

No. You connect the Instagram account once in the Social media studio dashboard through the Instagram sign-in. Its tokens are stored encrypted and refreshed on our side, and your code only sends your Social media studio API key in the X-API-Key header.

No. It returns as soon as the post is queued. Publishing runs in a worker that retries on failure, so listen for post.published and post.failed, or poll GET /v1/posts/:id.

The REST API, the CLI and the MCP server are included on every paid plan: Lite, Creator, Standard, Advanced and Lifetime. Lite, Creator, Standard and Advanced start with a 7-day trial (card required), and Lifetime is a one-time payment.

Schedule once.
Post everywhere.

Stop juggling tabs, draft, customize, and publish to 20 platforms from a single calendar.

Post to Instagram via API: Reels, Carousels & Stories