Instagram Stories API: Publish Stories and Read Insights
The Instagram Stories API is the content publishing flow with media_type=STORIES: create a container from a public JPEG or video URL, wait for video to finish processing, then call media_publish. Stories take no stickers or captions, video runs 3 to 60 seconds, and Story insights vanish after 24 hours. Adeli publishes image and video Stories through one API.
The Instagram Stories API is Meta's content publishing flow with media_type=STORIES: you create a container from a public image or video URL, wait for the video to process, then publish it with media_publish. A Story goes live for 24 hours, and its insights disappear on the same clock.
Most of the trouble comes from what the API won't do. Developers keep finding out that stickers, links, and polls can't be added, that Creator accounts hit walls, and that Story metrics expire before a daily report job gets to them. This guide covers the publishing calls, the spec, which accounts can post, mentions, and Story insights. Our guide to posting to Instagram via API compares all four formats side by side, and the Instagram Reels API post covers Reels.
What do you need to publish an Instagram Story through the API?
Publishing an Instagram Story needs a professional Instagram account, a token with the content publishing permission, and the media at a public URL (or uploaded through Meta's resumable upload). Meta's content publishing guide lists three setups:
| Instagram Login | Facebook Login | Unified Login | |
|---|---|---|---|
| Host | graph.instagram.com |
graph.facebook.com |
graph.facebook.com |
| Token | Instagram User access token | Facebook Page access token | Business Integration System User access token |
| Permissions | instagram_business_basic, instagram_business_content_publish |
instagram_basic, instagram_content_publish, pages_read_engagement |
instagram_basic, instagram_content_publish |
| Resumable file upload | No | Yes | Yes |
Use a Business account if you can. Meta opened the Content Publishing API to Creator accounts in June 2023, a month after Stories arrived. But developers on Meta's forum report that Story containers fail for Creator accounts while Reels and images from the same account work. The current reference doesn't state a rule either way. If your users include creators, run a Story through a Creator account in testing before you promise the feature.
Publishing for accounts you don't own also needs Advanced Access, which means Meta app review. The Instagram API permissions guide explains each scope.
What are the Instagram Story specs?
Instagram Story images must be JPEG up to 8 MB, and Story videos must be MP4 or MOV, 3 to 60 seconds, up to 100 MB. Meta recommends 9:16 for both. The full spec comes from the IG User media reference:
| Spec | Image Story | Video Story |
|---|---|---|
| Format | JPEG only | MP4 or MOV with the moov atom first and no edit lists |
| File size | 8 MB maximum | 100 MB maximum |
| Duration | — | 3 to 60 seconds |
| Aspect ratio | 9:16 recommended | 0.1:1 to 10:1 allowed, 9:16 recommended |
| Codecs | sRGB (other color spaces get converted) | HEVC or H.264, AAC audio at 48 kHz max, 128 kbps |
| Frame rate and width | — | 23 to 60 FPS, 1,920 pixels wide at most |
| Bitrate | — | VBR, 25 Mbps maximum |
Two limits are tighter than the feed: a Story video caps at 60 seconds, where a Reel can run 15 minutes, and at 100 MB, a third of the Reels ceiling. Trim long clips before you create the container, because Meta rejects the file rather than cutting it.
Step 1: Create a Story container
POST to /<IG_ID>/media with media_type=STORIES and either image_url or video_url. This is the "Instagram API for posting stories" call. It returns a container ID, not a live Story.
curl -X POST "https://graph.facebook.com/v26.0/<IG_ID>/media" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <ACCESS_TOKEN>" \
-d '{
"media_type": "STORIES",
"video_url": "https://example.com/story.mp4"
}'{ "id": "<IG_CONTAINER_ID>" }For an image Story, swap video_url for image_url with a JPEG. With Instagram Login, call graph.instagram.com with an Instagram User access token instead.
Step 2: Wait for the video to finish processing
For a video Story, GET the container's status_code until it reads FINISHED. Meta's guide suggests checking once a minute for no more than 5 minutes.
curl "https://graph.facebook.com/v26.0/<IG_CONTAINER_ID>?fields=status_code" \
-H "Authorization: Bearer <ACCESS_TOKEN>"ERROR means the file broke the spec. EXPIRED means nobody published the container within 24 hours, so create a new one. The Reels guide has the full status table and the upload error subcodes, which are the same for Stories.
Step 3: Publish the Story
POST the container ID to /<IG_ID>/media_publish as creation_id. The response holds the Instagram Media ID of the live Story.
curl -X POST "https://graph.facebook.com/v26.0/<IG_ID>/media_publish" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <ACCESS_TOKEN>" \
-d '{"creation_id": "<IG_CONTAINER_ID>"}'Save that media ID right away. You need it for Story insights, and Meta stops serving the Story after 24 hours. When you read it back, media_product_type returns STORY, while media_type only says IMAGE or VIDEO.
Can I upload a Story file instead of a URL?
Yes, with Facebook Login or Unified Login, through Meta's resumable upload on rupload.facebook.com. Create the container with upload_type=resumable, then send the file's bytes to the upload URL Meta returns. Meta's publishing guide says every media type shares that same video upload flow, Stories included.
With Instagram Login, there is no upload endpoint. Host the file somewhere Meta can fetch it, such as a short-lived signed URL from your storage bucket, and pass it as video_url or image_url. Meta has to reach the file when you create the container, so a link that expires in seconds fails.
Can I add stickers, links, or mentions to a Story?
The Instagram API publishes mentions on Stories but not stickers. Meta's IG User media reference says publishing link, poll, and location stickers is not supported. Here's what a Story container accepts:
| Feature | Through the API? | Notes |
|---|---|---|
| Link sticker | No | No API field adds a link to a Story |
| Poll, quiz, question stickers | No | Add them in the Instagram app instead |
| Location sticker | No | Covered by the same sticker restriction |
| Mentions | Yes | user_tags with a username; x and y are optional on Stories (added July 2025) |
| Collaborators | No | Meta marks collaborators as not supported for Stories |
| Alt text | No | alt_text excludes Reels and Stories |
| Shopping tags and filters | No | Not supported on any API-published media |
A mention looks like this. Include coordinates only if you want to place the tag:
{
"media_type": "STORIES",
"image_url": "https://example.com/story.jpg",
"user_tags": [{ "username": "partneraccount", "x": 0.5, "y": 0.8 }]
}If your product needs a swipe-up link, put it somewhere the API can reach: the caption of a feed post or Reel, or the account's bio. A Story can't carry it.
Common mistakes with the Instagram Stories API
Most failed Stories in developer threads come from three things: features the API doesn't publish, the account type, and old forum answers that predate Meta's changes.
Posting a story via graph.instagram.com works fine - but as soon as I add the parameter "user_tags" I get an error
— Eric on the Meta Developer Community
same problem, i cannot manage to add any info (location, user tags...) on story, only a plain photo.
— Grégoire on the Meta Developer Community
Old but in the actual documentation facebook is expliciting that's only available for business accounts
— Manoel, answering a Creator account Stories question on the Meta Developer Community
Those threads predate the July 2025 change that made Story mentions work, so tagging a username is fine now; location still isn't. The account type issue hasn't gone away: test Creator accounts before you rely on them, as covered in the prerequisites above.
How do I list an account's live Stories?
Call GET /<IG_ID>/stories on an account that authorized your app. The stories edge reference returns the Story media IDs that are still live. The regular /media edge leaves Stories out.
curl -G "https://graph.facebook.com/v26.0/<IG_ID>/stories" \
-H "Authorization: Bearer <ACCESS_TOKEN>" \
--data-urlencode "fields=id,media_type,media_product_type,timestamp,permalink"The edge has gaps worth knowing:
- No Live Video Stories. Meta leaves them out of the response.
- No reshared Stories. A Story the account created by resharing another Story isn't returned.
- No updates or deletes through this edge. It only reads.
- No other accounts. You can only read Stories for accounts that authorized your app. Business discovery, the endpoint for reading other accounts, has no Stories field; see our Instagram business discovery API guide for what it does return.
How does the Instagram story insights API work?
The Instagram story insights API is the media insights endpoint, GET /<IG_MEDIA_ID>/insights, called with a Story's media ID within 24 hours of posting. It needs instagram_manage_insights (or instagram_business_manage_insights with Instagram Login). Our Instagram insights API guide covers account metrics and feed posts; this section stays on Stories.
curl -G "https://graph.facebook.com/v26.0/<IG_MEDIA_ID>/insights" \
-H "Authorization: Bearer <ACCESS_TOKEN>" \
--data-urlencode "metric=views,reach,replies,shares,link_clicks"The navigation metric counts every action taken from the Story. Request it on its own with the story_navigation_action_type breakdown, which Meta says works only with navigation:
curl -G "https://graph.facebook.com/v26.0/<IG_MEDIA_ID>/insights" \
-H "Authorization: Bearer <ACCESS_TOKEN>" \
--data-urlencode "metric=navigation" \
--data-urlencode "breakdown=story_navigation_action_type"The response splits into the four actions Meta tracks, per the media insights reference. Added together, they equal the navigation total:
| Breakdown value | What the viewer did |
|---|---|
TAP_FORWARD |
Tapped to the next frame |
TAP_BACK |
Tapped back to the previous frame |
TAP_EXIT |
Left the Stories viewer |
SWIPE_FORWARD |
Swiped to the next Story |
That breakdown replaced the old taps_forward, taps_back, and exits metrics. link_clicks arrived in June 2026 and counts taps on links in the Story, such as a link sticker added in the app.
Plan for these Story-specific rules:
- 24-hour window. Story metrics stop being available after 24 hours. A nightly reporting job will miss Stories posted the previous morning.
- The 5-viewer floor. A metric with a value under 5 returns error 10,
(#10) Not enough viewers for the media to show insights. Show it as too small to report. - Regional zeros. Meta says
repliesdoesn't include replies from users in some regions, and returns0for Stories created in those regions.
Getting Story insights before they expire
Subscribe to the story_insights webhook field so Meta pushes the numbers to you. Meta's insights reference recommends it for exactly this reason. Per Meta's webhook fields table, the field works with Facebook Login and Unified Login, and not with Instagram Login. On Instagram Login, poll each live Story's insights on a schedule shorter than 24 hours and store what you get.
Can the API show who viewed a Story?
No. The Instagram API returns Story view counts, not the viewers. The media insights reference documents views (how many times the Story played) and reach (an estimate of unique accounts that saw it). No endpoint in Meta's references returns the list of accounts that watched a Story, so the closest thing to a story viewers endpoint is the reach count.
Is there a faster way to publish Instagram Stories?
Yes. Adeli publishes image and video Stories to Instagram through one API call, with no Meta developer app, app review, or token refresh job on your side. Adeli connects accounts through Meta's Unified Login and holds the Meta app, so you hold one API key. The request uses the same endpoint as every other network:
curl -X POST "https://app.tryadeli.com/api/v1/posts" \
-H "Authorization: Bearer $ADELI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"platform": "instagram",
"accountId": "<ADELI_ACCOUNT_ID>",
"story": {
"url": "https://media.example.com/story.mp4",
"userTags": [{ "username": "partneraccount" }]
}
}'What Adeli does with a Story, per the Instagram publishing reference:
- Checks the spec first. A video Story must run 3 to 60 seconds, and fields Stories don't take (caption, collaborators, alt text) are rejected with a
400instead of being silently dropped. - Handles the upload. Stage a local file with direct uploads and Adeli delivers it to Meta, so you don't host public URLs.
- Reports status. Staged uploads return
202with a status URL you poll while Meta processes the video.
Adeli's analytics API reads account-level Instagram insights, which include Story interactions. Per-Story metrics still come from Meta's insights endpoint within the 24-hour window. Adeli is free to start with no per-post fees; see pricing for the details.