Skip to main content
Instagram is visually demanding. The API reflects that. If you don’t follow their rules on aspect ratios and media types, they will reject your content without mercy.

Supported Content Types

  • Posts: Single image, single video, or carousel (mixed images + videos). 1-10 files.
  • Reels: Video only. Must be vertical.
  • Stories: Image or video. Expire after 24 hours. Gone like your motivation on Monday morning.

Quirks & Gotchas

Aspect Ratios are Law

Instagram is very strict here.
  • Stories/Reels: Must be 9:16 (vertical). Technically the API accepts wider ratios, but they’ll look terrible.
  • Feed Posts: 4:5 (vertical) or 1:1 (square) for images. Videos are more flexible.
Don’t try to cheat. If you upload a 16:9 (landscape) video as a Reel, it might technically “work” but it will look terrible (awkwardly cropped) or be rejected entirely. Your marketing team will not be happy. Your users’ marketing teams will not be happy. Nobody will be happy.

What if I have non-standardized content?

Instagram feed Posts must fall within a specific aspect ratio range (4:5 to 1.91:1). If your users upload wide landscape photos or tall portrait shots that fall outside this range, you have two automatic correction options instead of rejecting the upload outright:
OptionFieldBehavior
FitautoFitImage: trueAdds padding around the image to fit the target ratio. No pixels are lost. The same way Instagram does this natively.
CropautoCropImage: trueCenter-crops the image to fit the target ratio. No padding, but edges are cut.
These two options are mutually exclusive. Sending both as true will fail validation. They only apply to type: "POST" and have no effect on Reels or Stories.

Stories vs. Reels vs. Posts

  • Stories are ephemeral. They disappear after 24 hours. Great for FOMO content.
  • Reels are for growth. They’re public, discoverable, and the algorithm loves them.
  • Posts are for the feed grid. The permanent collection.

Media Limits

See Platform Limits for the full breakdown of file sizes, resolutions, and aspect ratios.

Text & Field Limits

FieldLimit
textMax 2,000 characters
collaboratorsMax 3 usernames, each max 30 chars
taggedMax 20 users per media, username max 30 chars
carouselItemsMax 10 items
locationIdMax 64 characters

Instagram Misc Endpoints

GET /misc/instagram/tags

  • Purpose: business discovery by username (public profile data for discoverable business/creator accounts).
  • Important: works only when the Instagram account is connected via FACEBOOK login flow.
  • If the account is connected via direct INSTAGRAM method, API returns explicit 400 with reconnection guidance.
  • Private accounts and some non-business/non-creator accounts may not be discoverable and can return exists: false.
  • In our tests, business discovery can sometimes return false for accounts that are still valid for publishing tags. In other words: lookup may fail, while tagging that same username in publish payload can still work.

GET /misc/instagram/locations

  • Purpose: search Facebook Pages with physical location data and return IDs for data.INSTAGRAM.locationId.
  • Important: works only for Instagram accounts connected via FACEBOOK method.
  • Uses the account page token (socialAccount.accessToken).
  • Missing page permissions/features (for example pages_read_engagement) return explicit 400 with actionable message.
Meta location search can be inconsistent. If you hit the permission/error path, there is usually nothing we can reliably fix from API side right now (this behavior is widely reported in Meta developer threads). The good news: locationId tagging itself still works when you already have a valid location/page ID, so known IDs found externally can still be used in publish payloads. We hope this endpoint becomes stable for all accounts over time.

Publishing Payload & Validation Rules

locationId mapping

  • data.INSTAGRAM.locationId is mapped to location_id in Instagram publish payload.
  • Supported in single image, reel/single-video flow, and carousel parent container.

shareToFeed

  • Accepted only for reel-like payloads:
    • type = REEL, or
    • type = POST with exactly one video upload.
  • Rejected for image posts, carousels, and stories (400).

Person tags (tagged)

  • Reel/single-video: provide usernames only (no x/y coordinates).
  • Single image: each tagged user must include x and y in range 0-1.
  • Carousel: top-level tagged is rejected; use carouselItems[].tagged per item.
  • Carousel video item: person tags are not supported and are rejected.
  • carouselItems is allowed only for real carousel posts (at least 2 uploads).
  • Every carouselItems[].uploadId must exist in provided uploadIds.
  • Use each uploadId only once in carouselItems.
{
  "socialAccountTypes": ["INSTAGRAM"],
  "data": {
    "INSTAGRAM": {
      "type": "POST",
      "text": "Carousel with per-item tags",
      "uploadIds": ["upl_img_1", "upl_img_2", "upl_vid_1"],
      "carouselItems": [
        {
          "uploadId": "upl_img_1",
          "tagged": [{ "username": "alice", "x": 0.25, "y": 0.4 }]
        },
        {
          "uploadId": "upl_img_2",
          "tagged": [{ "username": "bob", "x": 0.6, "y": 0.35 }]
        },
        {
          "uploadId": "upl_vid_1"
        }
      ]
    }
  }
}

Story constraints

  • Stories do not support collaborators.
  • Stories do not support locationId.

Collaborators behavior

  • Collaborators are normalized before publish (@ stripped, trim, lowercase).
  • Automatic fallback retry without unavailable collaborators was removed.
  • Retry behavior now follows standard BullMQ worker retry policy.

Trial Reels

Trial reels are shared only with non-followers first. If the content performs well, it can be graduated to a regular reel that appears to everyone. Send data.INSTAGRAM.trialParams.graduationStrategy in the publish payload:
ValueBehavior
MANUALThe trial reel stays in trial until you manually graduate it from the native Instagram app.
SS_PERFORMANCEInstagram automatically graduates the reel if it meets a performance threshold.
Requirements and caveats:
  • Only valid for type: "REEL". Ignored for Posts and Stories.
  • Requires a public professional (Creator or Business) account with at least around 1,000 followers. Instagram has not published an official threshold and some users report access starting at 200 followers.
  • Not all professional accounts will have access to this feature regardless of follower count.
{
  "socialAccountTypes": ["INSTAGRAM"],
  "data": {
    "INSTAGRAM": {
      "type": "REEL",
      "text": "Testing this reel with non-followers first",
      "uploadIds": ["upl_vid_1"],
      "trialParams": {
        "graduationStrategy": "SS_PERFORMANCE"
      }
    }
  }
}

Analytics

For general analytics concepts (refresh rates, data retention, what “Returns 0” means), see the Analytics Overview.

Refresh Rate & Limits

  • Default Refresh: Every 24 hours.
  • Force Refresh: Available (max Teams × 5 per day).
  • Data Retention: 30 days. Details.

Profile Analytics

Period: Rolling window (30 days).
MetricDescriptionNote
impressionsTotal times profile content was shown
impressionsUniqueUnique accounts that saw contentCalled “Reach” by Instagram
viewsProfile views
viewsUnique-Returns 0 (not provided by API)
likesTotal likes
commentsTotal comments
postCountTotal posts published
followersTotal followers
followingTotal following

Post Analytics

Period: Lifetime (Snapshot).
MetricDescriptionNote
impressionsTotal viewsCalled “views” in Instagram API
impressionsUniqueUnique accounts reachedCalled “reach” in Instagram API
viewsVideo playsVideos/Reels only
viewsUnique-Returns 0 (not provided by API)
likesTotal likes
commentsTotal comments
sharesTotal sharesReels only
savesTotal saves

Raw Analytics - Demographics & Audience Data

Instagram provides some of the richest demographic data via raw analytics. Here’s what the raw payload looks like when enabled for your organization:
{
  "profileInfo": { /* basic account info */ },
  "totals30d": [ /* 30-day daily breakdown */ ],
  "demographics": {
    "follows_and_unfollows": {
      "data": [{
        "name": "follows_and_unfollows",
        "period": "day",
        "title": "Follows and unfollows",
        "total_value": { "value": { "follows": 142, "unfollows": 23 } }
      }]
    },
    "follower_demographics": {
      "country": {
        "data": [{
          "name": "follower_demographics",
          "total_value": {
            "breakdowns": [{
              "dimension_keys": ["country"],
              "results": [
                { "dimension_values": ["US"], "value": 4521 },
                { "dimension_values": ["GB"], "value": 1893 },
                { "dimension_values": ["DE"], "value": 1247 }
              ]
            }]
          }
        }]
      },
      "city": {
        "data": [{
          "name": "follower_demographics",
          "total_value": {
            "breakdowns": [{
              "dimension_keys": ["city"],
              "results": [
                { "dimension_values": ["New York, New York"], "value": 892 },
                { "dimension_values": ["London, England"], "value": 654 }
              ]
            }]
          }
        }]
      },
      "gender": {
        "data": [{
          "name": "follower_demographics",
          "total_value": {
            "breakdowns": [{
              "dimension_keys": ["gender"],
              "results": [
                { "dimension_values": ["M"], "value": 5234 },
                { "dimension_values": ["F"], "value": 4891 },
                { "dimension_values": ["U"], "value": 312 }
              ]
            }]
          }
        }]
      },
      "age": {
        "data": [{
          "name": "follower_demographics",
          "total_value": {
            "breakdowns": [{
              "dimension_keys": ["age"],
              "results": [
                { "dimension_values": ["18-24"], "value": 3421 },
                { "dimension_values": ["25-34"], "value": 4102 },
                { "dimension_values": ["35-44"], "value": 1893 },
                { "dimension_values": ["45-54"], "value": 721 }
              ]
            }]
          }
        }]
      }
    },
    "engaged_audience_demographics": {
      "country": { /* same structure as follower_demographics */ },
      "city": { /* same structure */ },
      "gender": { /* same structure */ },
      "age": { /* same structure */ }
    }
  }
}
Raw demographics include both follower demographics (lifetime, who follows you) and engaged audience demographics (this month, who interacts with your content). These are two different audiences and both are useful for understanding your reach.