Platforms
Connect an Instagram professional account, publish photos, carousels, Reels and Stories, moderate comments, answer direct messages and read post and account analytics.
Publish photos, carousels, Reels and Stories, answer comments and direct messages, and read post and account analytics.
Quick Reference
| Property | Value |
|---|---|
| Account types | Business or Creator accounts |
| Connection method | OAuth, Instagram Login or Facebook Login |
| Post types | image, multi_image, video (published as reel), reel, stories |
| Max media per post | 10 |
| Text limit | 2,200 characters |
| Threads | No |
| Quotes | No |
| Remote delete | Facebook Login only |
| Comments | |
| Likes | No |
| Reposts | No |
| Bookmarks | No |
| Direct messages | |
| Post analytics | |
| Account analytics | Stats and insights |
Every post needs media. video and reel publish the same Reel. Deleting posts, catalog audio and the paid partnership label need Facebook Login.
Connect
You need a Business or Creator account, not a personal one. Connect it in Dashboard → Connections, or from your app with a connect session for platform: "instagram", as described in Connect Accounts.
Login Methods
loginMethod defaults to instagram_login. Facebook Login needs a linked Facebook Page and unlocks the extra features below.
| Feature | Instagram Login | Facebook Login |
|---|---|---|
| Publish, comments, messages, analytics | ||
| Catalog audio on Reels | No | |
| Paid partnership label | No | |
| Delete published posts | No |
On Instagram Login, those options return 400 VALIDATION_ERROR.
import { Configuration, ConnectApi } from "@onepostly/sdk";
const connectApi = new ConnectApi(
new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })
);
const response = await connectApi.createConnectSession({
createConnectSessionBody: {
"platform": "instagram",
"loginMethod": "facebook_login",
"redirectUrl": "https://app.example.com/onepostly/connected"
},
});
console.log(response);{
"url": "https://www.facebook.com/v26.0/dialog/oauth?client_id=2938475610293847&response_type=code&scope=instagram_basic%2Cinstagram_content_publish%2Cinstagram_manage_comments%2Cinstagram_manage_insights%2Cinstagram_manage_messages%2Cinstagram_manage_contents%2Cpages_show_list%2Cpages_read_engagement%2Cbusiness_management%2Cpublic_profile&state=eyJwIjoiaW5zdGFncmFtIiwibiI6IjNmOWMxYTJiIn0.Xk2pQ8vRt4mN7sL1&auth_type=rerequest",
"expiresAt": "2027-03-15T09:10:00.000Z"
}Facebook Login shows an account picker of the Instagram accounts linked to the person's Pages. For your own picker, add headless: true, see Pick a Page or Account. To switch an account to Facebook Login, connect it again.
Permissions
| Scope | Used for |
|---|---|
instagram_business_basic | Id, username and avatar |
instagram_business_content_publish | Publishing |
instagram_business_manage_comments | Comments |
instagram_business_manage_insights | Analytics |
instagram_business_manage_messages | Messages and private replies |
Staying Connected
Access renews itself, so canAutoRenew is true. You only need to reconnect in the cases below, and the account id stays the same.
statusis notactive, or you getTOKEN_INVALID, such as after a password change.- A
*_PERMISSIONcode, which a reconnect grants. CONNECTION_BROKENon Facebook Login, when the Page is unlinked.
Publish
import { Configuration, PostsApi } from "@onepostly/sdk";
const postsApi = new PostsApi(
new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })
);
const response = await postsApi.createPost({
createPostBody: {
"text": "Golden hour at the harbor #sunset",
"mediaKind": "image",
"media": [
{
"url": "https://cdn.onepostly.com/media/harbor.jpg"
}
],
"accounts": [
{
"accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID"
}
]
},
});
console.log(response);{
"groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45",
"data": [
{
"id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73",
"groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45",
"accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID",
"platform": "instagram",
"source": "onepostly",
"status": "publishing",
"text": "Golden hour at the harbor #sunset",
"mediaKind": "image",
"media": [
{
"url": "https://cdn.onepostly.com/media/harbor.jpg"
}
],
"thread": [],
"scheduledFor": null,
"timezone": null,
"options": {},
"platformPostId": null,
"url": null,
"error": null,
"publishedAt": null,
"metrics": null,
"createdAt": "2027-03-15T09:00:00.000Z",
"updatedAt": "2027-03-15T09:00:00.000Z"
}
]
}Once published, url is the Instagram permalink. See Post Status.
Post Types
mediaKind | Publishes | Media |
|---|---|---|
image | Feed photo | 1 image |
multi_image | Carousel | 2 to 10 images or videos, mixed |
video, reel | Reel | 1 video |
stories | Story, for 24 hours | 1 image or video |
- Captions go up to 2,200 characters. Stories show no caption.
- The files set the kind, so set
mediaKindonly forstories. - A Reel always reads
mediaKind: "reel", even sent asvideo. - A carousel follows the order of
media. Over 10 items fails withINVALID_MULTI_IMAGE.
Reel
A Reel shows on the Reels tab and the grid. shareToFeed: false keeps it off the grid. The cover is coverUrl or the thumbOffset frame, and coverUrl wins. audioName sets a new name for the audio, once.
Reel options work only on reel or video. Elsewhere, including a video in a carousel or Story, they return 400 VALIDATION_ERROR.
import { Configuration, PostsApi } from "@onepostly/sdk";
const postsApi = new PostsApi(
new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })
);
const response = await postsApi.createPost({
createPostBody: {
"text": "How we pack an order in 30 seconds",
"mediaKind": "reel",
"media": [
{
"url": "https://cdn.onepostly.com/media/packing.mp4"
}
],
"accounts": [
{
"accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID",
"instagram": {
"coverUrl": "https://cdn.onepostly.com/media/packing-cover.jpg",
"audioName": "Packing day"
}
}
]
},
});
console.log(response);{
"groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45",
"data": [
{
"id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73",
"groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45",
"accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID",
"platform": "instagram",
"source": "onepostly",
"status": "publishing",
"text": "How we pack an order in 30 seconds",
"mediaKind": "reel",
"media": [
{
"url": "https://cdn.onepostly.com/media/packing.mp4"
}
],
"thread": [],
"scheduledFor": null,
"timezone": null,
"options": {
"instagram": {
"coverUrl": "https://cdn.onepostly.com/media/packing-cover.jpg",
"audioName": "Packing day"
}
},
"platformPostId": null,
"url": null,
"error": null,
"publishedAt": null,
"metrics": null,
"createdAt": "2027-03-15T09:00:00.000Z",
"updatedAt": "2027-03-15T09:00:00.000Z"
}
]
}Story
A Story takes only userTags. Any other option returns 400 VALIDATION_ERROR. Stories have no comments, so a comment list returns UNSUPPORTED_MEDIA.
import { Configuration, PostsApi } from "@onepostly/sdk";
const postsApi = new PostsApi(
new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })
);
const response = await postsApi.createPost({
createPostBody: {
"mediaKind": "stories",
"media": [
{
"url": "https://cdn.onepostly.com/media/flash-sale.jpg"
}
],
"accounts": [
{
"accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID"
}
]
},
});
console.log(response);{
"groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45",
"data": [
{
"id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73",
"groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45",
"accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID",
"platform": "instagram",
"source": "onepostly",
"status": "publishing",
"text": "",
"mediaKind": "stories",
"media": [
{
"url": "https://cdn.onepostly.com/media/flash-sale.jpg"
}
],
"thread": [],
"scheduledFor": null,
"timezone": null,
"options": {},
"platformPostId": null,
"url": null,
"error": null,
"publishedAt": null,
"metrics": null,
"createdAt": "2027-03-15T09:00:00.000Z",
"updatedAt": "2027-03-15T09:00:00.000Z"
}
]
}Options
Options go under instagram. On the wrong media kind, they return 400.
Prop
Type
firstComment, commentsEnabled, collaborators, locationId, isAiGenerated and the paid partnership fields work on photos, carousels and Reels. If Instagram refuses firstComment or commentsEnabled, the post still publishes.
Tags and Location
userTags takes a username, @ optional, and x and y from 0 to 1, from the top left. A photo needs x and y. Without them it passes on create but fails at publish. They are optional on Stories and ignored on Reels.
locationId and tags cover a whole carousel.
import { Configuration, PostsApi } from "@onepostly/sdk";
const postsApi = new PostsApi(
new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })
);
const response = await postsApi.createPost({
createPostBody: {
"text": "Opening night with the team",
"mediaKind": "image",
"media": [
{
"url": "https://cdn.onepostly.com/media/opening.jpg"
}
],
"accounts": [
{
"accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID",
"instagram": {
"userTags": [
{
"username": "studio.north",
"x": 0.32,
"y": 0.6
}
],
"collaborators": [
"studio.north"
],
"locationId": "110843418940484"
}
}
]
},
});
console.log(response);{
"groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45",
"data": [
{
"id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73",
"groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45",
"accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID",
"platform": "instagram",
"source": "onepostly",
"status": "publishing",
"text": "Opening night with the team",
"mediaKind": "image",
"media": [
{
"url": "https://cdn.onepostly.com/media/opening.jpg"
}
],
"thread": [],
"scheduledFor": null,
"timezone": null,
"options": {
"instagram": {
"userTags": [
{
"username": "studio.north",
"x": 0.32,
"y": 0.6
}
],
"collaborators": [
"studio.north"
],
"locationId": "110843418940484"
}
},
"platformPostId": null,
"url": null,
"error": null,
"publishedAt": null,
"metrics": null,
"createdAt": "2027-03-15T09:00:00.000Z",
"updatedAt": "2027-03-15T09:00:00.000Z"
}
]
}Trial Reels
trialReel: true shows a Reel to non-followers first.
trialGraduationStrategy | Followers see it when |
|---|---|
manual (default) | You share it in the Instagram app |
ss_performance | It performs well |
A trial Reel with sponsors fails with INVALID_TRIAL_REEL.
Catalog Audio
audioId adds a track to a Reel on Facebook Login. Find ids with Search Instagram Audio. Omit q for trending tracks or set type=original_sound.
import { Configuration, PostsApi } from "@onepostly/sdk";
const postsApi = new PostsApi(
new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })
);
const response = await postsApi.createPost({
createPostBody: {
"text": "Weekend mood",
"mediaKind": "reel",
"media": [
{
"url": "https://cdn.onepostly.com/media/beach.mp4"
}
],
"accounts": [
{
"accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID",
"instagram": {
"audioId": "587784541076604",
"audioVolume": 80,
"videoVolume": 30
}
}
]
},
});
console.log(response);{
"groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45",
"data": [
{
"id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73",
"groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45",
"accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID",
"platform": "instagram",
"source": "onepostly",
"status": "publishing",
"text": "Weekend mood",
"mediaKind": "reel",
"media": [
{
"url": "https://cdn.onepostly.com/media/beach.mp4"
}
],
"thread": [],
"scheduledFor": null,
"timezone": null,
"options": {
"instagram": {
"audioId": "587784541076604",
"audioVolume": 80,
"videoVolume": 30
}
},
"platformPostId": null,
"url": null,
"error": null,
"publishedAt": null,
"metrics": null,
"createdAt": "2027-03-15T09:00:00.000Z",
"updatedAt": "2027-03-15T09:00:00.000Z"
}
]
}Paid Partnership
On Facebook Login, isPaidPartnership: true adds the label. brandedContentSponsors adds it with up to 2 named sponsors.
A sponsor username must be a public professional account, or the post fails with INVALID_SPONSOR. A numeric id always works.
import { Configuration, PostsApi } from "@onepostly/sdk";
const postsApi = new PostsApi(
new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })
);
const response = await postsApi.createPost({
createPostBody: {
"text": "Our new spring line, made with Fieldwork",
"mediaKind": "multi_image",
"media": [
{
"url": "https://cdn.onepostly.com/media/spring-1.jpg"
},
{
"url": "https://cdn.onepostly.com/media/spring-2.jpg"
}
],
"accounts": [
{
"accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID",
"instagram": {
"brandedContentSponsors": [
"fieldwork.co"
]
}
}
]
},
});
console.log(response);{
"groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45",
"data": [
{
"id": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73",
"groupId": "grp_7d2e5b1a9c4f4a68b3e07f1c2d9a6e45",
"accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID",
"platform": "instagram",
"source": "onepostly",
"status": "publishing",
"text": "Our new spring line, made with Fieldwork",
"mediaKind": "multi_image",
"media": [
{
"url": "https://cdn.onepostly.com/media/spring-1.jpg"
},
{
"url": "https://cdn.onepostly.com/media/spring-2.jpg"
}
],
"thread": [],
"scheduledFor": null,
"timezone": null,
"options": {
"instagram": {
"brandedContentSponsors": [
"fieldwork.co"
]
}
},
"platformPostId": null,
"url": null,
"error": null,
"publishedAt": null,
"metrics": null,
"createdAt": "2027-03-15T09:00:00.000Z",
"updatedAt": "2027-03-15T09:00:00.000Z"
}
]
}Media Requirements
These are Instagram's limits, on top of the Media URL Requirements.
| Media | Formats | Max size |
|---|---|---|
| Images | JPEG | 8 MB |
| Reels | MP4 and MOV | 300 MB |
| Story videos | MP4 and MOV | 100 MB |
| Carousel videos | MP4 and MOV | 1 GB |
A file outside these formats and sizes is refused. See Platform Limits.
Images
| Property | Requirement |
|---|---|
| Aspect ratio | 4:5 to 1.91:1 on feed and carousel |
| Width | 320 to 1440, resized outside it |
| Common sizes | 1080 × 1350, 1080 × 1080, 1080 × 566 |
| Stories | 1080 × 1920 (9:16) |
A 3:4 image, such as 1080 × 1440, is too narrow for the feed.
Videos
| Property | Reel | Story |
|---|---|---|
| Duration | 3 s to 15 min | 3 to 60 s |
| Aspect ratio | 9:16 | 9:16 |
| Max width | 1920 | 1920 |
| Video | H.264 or HEVC, 23 to 60 fps | Same |
| Audio | AAC, up to 48 kHz | Same |
A URL ending in .mp4, .mov, .m4v, .webm or .avi is a video, anything else an image. Slow processing fails with MEDIA_PROCESSING_TIMEOUT.
Scheduling, Editing and Deleting
Scheduling and editing work as usual. Published posts cannot be edited.
Only Facebook Login can delete a published post, including one made outside Onepostly. Instagram Login returns MEDIA_DELETE_UNSUPPORTED, so delete it in the app.
Engagement
See Comments for the requests. Instagram has no likes, reposts or bookmarks.
| Action | Supported | Notes |
|---|---|---|
| List comments | Not on Stories, which return UNSUPPORTED_MEDIA | |
| Comment or reply | Up to 2,200 characters | |
| Delete a comment | On the account's own media | |
| Hide or unhide | ||
| Private reply | One per comment, within 7 days, up to 1,000 characters | |
| Like a comment | No | UNSUPPORTED_PLATFORM |
| Like, repost, bookmark | No | UNSUPPORTED_PLATFORM |
Outside posts work once synced. New comments send comment.received.
import { Configuration, CommentsApi } from "@onepostly/sdk";
const commentsApi = new CommentsApi(
new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })
);
const response = await commentsApi.sendPrivateReply({
id: "cmt_YOUR_COMMENT",
privateReplyBody: {
"text": "Hi! Here is the size chart you asked about."
},
});
console.log(response);{
"id": "aWdfZAG1faXRlbToxOklHTWVzc2FnZAUlEOjE3ODQxNDAwMTIzNDU2Nzg5OjM0MDI4MjM2Njg0MTcxMDMwMTI0NDI1OTc5NjAzNjg0NTQ0NDQ1NgZDZD",
"commentId": "cmt_YOUR_COMMENT",
"text": "Hi! Here is the size chart you asked about.",
"createdAt": "2027-03-15T10:00:00.000Z"
}Inbox
Both logins have an inbox. See Inbox for the requests and rich messages.
| Action | Supported | Notes |
|---|---|---|
| List and read | muted is always false | |
| Start a conversation | By username or user id | |
| Send text | Up to 1,000 characters, within 24 hours | |
| Rich messages | Attachments, quick replies, buttons, cards | |
| Automations | A comment_to_dm uses the comment's private reply | |
| Outside the 24-hour window | No |
Use a username for public professional accounts, or else a senderId.
import { Configuration, InboxApi } from "@onepostly/sdk";
const inboxApi = new InboxApi(
new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })
);
const response = await inboxApi.createConversation({
id: "acc_YOUR_INSTAGRAM_ACCOUNT_ID",
createConversationBody: {
"recipient": "17841400987654321"
},
});
console.log(response);{
"id": "cnv_BBh0Fb9Jm3kot2rw9sXz01Wph6BsppQzHdFeEz3M57nTn5Hq1Vaxue9BreJNIcZngbmoCxHC",
"accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID",
"members": [
{
"id": "17841400123456789",
"username": null,
"displayName": null
},
{
"id": "17841400987654321",
"username": null,
"displayName": null
}
],
"muted": false,
"unreadCount": 0,
"lastMessage": null
}A new conversation opens with its first message. Until then you get CONVO_NOT_FOUND. The person must have written in the last 24 hours, or you get MESSAGE_WINDOW_EXPIRED and must wait for them to write.
With attachmentUrl, Instagram shows only the attachment and not your text, so send anything important as its own message.
Inbox webhooks cover received, sent, read, reactions, postbacks and unsent messages. Their conversationId may differ from List Conversations, and both work everywhere. See Conversation Ids for which call returns which.
Analytics
Metrics
| Field | Instagram metric | Notes |
|---|---|---|
impressions | views | Instagram dropped impressions |
reach | reach | Unique accounts |
views | views | |
likes | likes | null on Stories |
comments | comments | null on Stories |
shares | shares | |
saves | saved | null on Stories |
engagement | total_interactions | A count. Else the sum of the four |
A metric the media type lacks is null, not 0.
Read Post Analytics
import { Configuration, AnalyticsApi } from "@onepostly/sdk";
const analyticsApi = new AnalyticsApi(
new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })
);
const response = await analyticsApi.getPostAnalytics({
id: "pst_YOUR_INSTAGRAM_POST",
});
console.log(response);{
"postId": "pst_YOUR_INSTAGRAM_POST",
"accountId": "acc_1699f4157fb643f49d2ac447491f32a8",
"platform": "instagram",
"status": "ready",
"metrics": {
"impressions": 2140,
"reach": 1630,
"likes": 184,
"comments": 21,
"shares": 9,
"saves": 37,
"views": 2140,
"engagement": 251
},
"fetchedAt": "2027-03-15T10:00:00.000Z",
"error": null
}Outside posts work once synced. A fresh post often reads pending. A deleted one reads unavailable with POST_NOT_FOUND, for good. Posts follow the shared freshness. Stories update about hourly while live, then keep their last values.
Account Stats
Get Account Stats returns the account's live counts. videoCount counts all media, photos included. likesCount is always null.
Account Insights
Get Account Analytics reads insights live. By default it returns views, reach, accounts_engaged and total_interactions. See Account Insights.
import { Configuration, AnalyticsApi } from "@onepostly/sdk";
const analyticsApi = new AnalyticsApi(
new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })
);
const response = await analyticsApi.getAccountAnalytics({
id: "acc_YOUR_INSTAGRAM_ACCOUNT_ID",
metrics: "follower_demographics",
period: "lifetime",
breakdown: "country",
timeframe: "this_month",
});
console.log(response);{
"accountId": "acc_YOUR_INSTAGRAM_ACCOUNT_ID",
"platform": "instagram",
"metrics": [
{
"name": "follower_demographics",
"period": "lifetime",
"values": []
}
],
"demographics": {
"follower_demographics": {
"US": 4120,
"GB": 1380,
"DE": 960,
"TR": 845,
"BR": 610
}
}
}| Parameter | Instagram values |
|---|---|
metrics | Up to 20 Instagram metric names |
period | day (default), week, days_28, lifetime |
breakdown | age, city, country, gender, or a metric's own breakdown |
timeframe | this_week or this_month |
metricType | total_value or time_series |
- Demographics are
follower_demographicsandengaged_audience_demographics. - They need
period=lifetime, abreakdownand atimeframe. follower_countandonline_followerscome only as a daily series.- Leave out
metricTypeto get each metric in its native form. - A value Instagram refuses returns
400 VALIDATION_ERRORwith its reason.
Recent Posts
List Account Media lists recent posts with likes and comments. Their shares and views are null. Add kind=stories for active Stories.
import { Configuration, AccountsApi } from "@onepostly/sdk";
const accountsApi = new AccountsApi(
new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })
);
const response = await accountsApi.listAccountMedia({
id: "acc_YOUR_INSTAGRAM_ACCOUNT_ID",
kind: "stories",
});
console.log(response);{
"data": [
{
"id": "18063412987650214",
"title": null,
"description": null,
"coverUrl": "https://scontent.cdninstagram.com/v/t51.29350-15/story-thumbnail.jpg",
"url": "https://www.instagram.com/stories/yourbrand/3581234567890123456/",
"createdAt": "2027-03-15T08:30:00.000Z",
"durationSec": null,
"metrics": {
"likes": null,
"comments": null,
"shares": null,
"views": null
}
},
{
"id": "18047129563820471",
"title": null,
"description": null,
"coverUrl": null,
"url": "https://www.instagram.com/stories/yourbrand/3580987654321098765/",
"createdAt": "2027-03-14T19:05:00.000Z",
"durationSec": null,
"metrics": {
"likes": null,
"comments": null,
"shares": null,
"views": null
}
}
],
"nextCursor": null,
"hasMore": false
}Limitations
Not available for Instagram through Onepostly.
- Text-only posts
- Editing a published post
- Likes, reposts, quotes, bookmarks and threads
- Comments on Stories
- Story stickers, product tags and Live
- Messages outside the 24-hour window
- Deletes, catalog audio and paid partnership on Instagram Login
Errors
Breaking a rule on this page returns 400 VALIDATION_ERROR and creates nothing. Instagram's own limits are checked at publish and fail the post. The tables below list the Instagram codes, and every code is in Errors.
Publish Errors
| Code | Cause | Fix |
|---|---|---|
INVALID_MULTI_IMAGE | Over 10 carousel items | Send 2 to 10 |
INVALID_TRIAL_REEL | A trial Reel with sponsors | Drop the sponsors |
INVALID_AUDIO | audioId, but the account moved to Instagram Login | Reconnect with Facebook Login |
INVALID_SPONSOR | A sponsor is not public and professional, or the account moved to Instagram Login | Use a numeric id, or Facebook Login |
INVALID_MEDIA | Instagram rejected the file | See Media Requirements |
CONTAINER_FAILED | Instagram could not process the media | Check format, size and dimensions |
MEDIA_PROCESSING_TIMEOUT | The video took too long | Use a smaller or shorter file |
MEDIA_DELETE_UNSUPPORTED | A delete on Instagram Login | Use Facebook Login, or the app |
DELETE_PERMISSION | Instagram refused the delete | Reconnect with Facebook Login |
PUBLISH_FAILED | Instagram rejected the post | Read error.message |
Engagement and Inbox Errors
| Code | Cause | Fix |
|---|---|---|
UNSUPPORTED_MEDIA | The post is a Story | Use a photo, carousel or Reel |
UNSUPPORTED_PLATFORM | A like, repost or bookmark | Not offered on Instagram |
COMMENTS_PERMISSION | A missing permission, or not your media | Reconnect, or delete only your own |
PRIVATE_REPLY_FAILED | A second reply, or after 7 days | One per comment, within 7 days |
RECIPIENT_NOT_FOUND | The username is not public and professional | Use the numeric user id |
RECIPIENT_UNREACHABLE | The person blocked or turned off messages | Wait for them to write |
CONVO_NOT_FOUND | No conversation, or no message yet | Send the first message |
MESSAGE_WINDOW_EXPIRED | Their last message is over 24 hours old | Wait for them to write |
CONNECTION_BROKEN | Facebook Login lost its Page | Reconnect and pick the Page |
Analytics Errors
| Code | Cause | Fix |
|---|---|---|
ANALYTICS_PENDING | No metrics yet | Read again later |
POST_NOT_FOUND | Deleted on Instagram | None, this is final |
VALIDATION_ERROR | Instagram refused an insights parameter | Fix the one in the message |
STATS_FAILED | Stats did not load | Read again later |
X (Twitter)
Connect an X account, publish posts, threads and quotes, like, repost, bookmark and reply to posts, and read post metrics, all paid from your wallet.
Connect a Facebook Page, publish text, photo, album, video, Reel and Story posts, manage comments and Messenger conversations, and read post and Page analytics.