> ## Documentation Index
> Fetch the complete documentation index at: https://docs.social-api.ai/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Base URL: https://api.social-api.ai/v1. Send your API key in the Authorization header: Authorization: Bearer <your API key>.
> Every error response from /v1 is JSON: { "error": { "code", "message", "meta" (optional) }, "request_id" }. Branch on error.code; use error.message only for logs.
> A 429 response carries a Retry-After header, in seconds, when the limit has a known wait.
> Paginated list endpoints return next_cursor, at the top level or inside pagination (see /guides/pagination). Pass it as the cursor query parameter to get the next page. An absent or empty next_cursor means you have the last page.
> Treat every ID as an opaque string: do not parse it or assume a format.
> Support differs by platform and by operation. Check /platforms/overview before assuming an operation works on a platform. An unsupported operation returns 501 with error.code resource.not_supported.

# Instagram API

> Connect Instagram Business and Creator accounts to publish, moderate comments, send DMs, and read mentions, stories, and insights through one API.

The Instagram API in SocialAPI connects an Instagram Business or Creator account through Instagram Login by default, or through Facebook Login when the account has a linked Facebook Page: see [Connect through Facebook Login](#connect-through-facebook-login). It publishes posts, Reels, carousels, and Stories, reads and moderates comments, sends private replies and direct messages (DMs), and reads mentions, stories, and insights. SocialAPI's own Meta app connects the account, so you register nothing: see [Platform apps](/guides/platform-credentials).

## At a glance

| Field | Value |
| - | - |
| Platform slug | `instagram` |
| Auth | OAuth 2.0 with Instagram Login (default): the account needs no linked Facebook Page. Or OAuth 2.0 with Facebook Login, selected with `metadata.connection_type: "facebook_login"`: the account needs a linked Facebook Page |
| Platform API | Instagram API with Instagram Login, or Instagram API with Facebook Login for Business (Meta) |
| Status | Available |

## Capabilities

An unsupported call returns `501 resource.not_supported`. Read the `capabilities` object on each comment instead of assuming (`can_like`, `can_private_reply`).

| Feature | Status | Condition |
| - | - | - |
| Publish feed image, Reel, carousel, Story | Yes | See [Instagram publishing](/platforms/instagram/publishing) |
| Schedule a post | Yes | `scheduled_at` on the post |
| First comment on a post | Yes | Not part of a Story |
| Update a published post | No | `PATCH /v1/posts/{pid}` returns `409 post.state_invalid` for a published post. A `draft`, `scheduled`, or `failed` post can be edited before it publishes. To correct it, delete the post in the Instagram app and publish a new one |
| Delete a published post | Partial | Instagram Login: `DELETE /v1/posts/{pid}` returns HTTP 200 with `results[].outcome: "not_supported"` for the Instagram target, and the post stays live. `POST /v1/posts/{pid}/unpublish` returns `501 resource.not_supported`. Delete the post in the Instagram app. [Facebook Login](#connect-through-facebook-login): `DELETE /v1/posts/{pid}` deletes the post from Instagram, and `POST /v1/posts/{pid}/unpublish` removes it from Instagram and keeps it in SocialAPI |
| List posts | Yes | Posts, Reels, and carousels |
| List active stories | Yes | Only stories that are live now |
| List comments and replies | Yes | Comments are read per post |
| Reply to a comment | Yes | |
| Hide, unhide, delete a comment | Yes | |
| Like a comment | Partial | Instagram Login: `501 resource.not_supported`, and `can_like` is `false` on every comment. [Facebook Login](#connect-through-facebook-login): yes, and `can_like` is `true` |
| Private reply to a comment | Yes | One per comment, within 7 days of the comment |
| DMs: list, read, send | Yes | Inside the 24-hour messaging window. Text, attachments, quick replies, buttons, cards |
| React to a DM | Yes | |
| Unsend or delete a DM | No | Only the Instagram app can |
| Messaging participant profile | Yes | Only for a person who messaged the account or tapped an icebreaker or the persistent menu |
| Mentions | Partial | `GET /v1/accounts/{id}/mentions` returns media the account is tagged in. Caption and comment @mentions arrive as `mention.received` events only |
| Reply to a mention | Yes | |
| Reviews | No | Instagram has no reviews. `GET /v1/inbox/reviews/{account_id}` returns `422 account.platform_unsupported` |
| Automations | Yes | Comment and DM triggers, buttons, multi-step flows, the Follow gate. See [Automations](/guides/automations) |
| Account summary | Yes | Needs the `analytics.read` [permission](/guides/permissions): see [Account summary](#account-summary) |
| Analytics | Yes | See [Analytics](/guides/analytics) |
| Collaboration invites | Yes | List, accept, decline. Invites are sent at publish time only |
| Webhook events | Yes | See [Webhook events](#webhook-events) |

The cross-platform matrix is on [Platforms](/platforms/overview).

## Connect an account

Connect with `POST /v1/accounts/connect` and `"platform": "instagram"`. The shared flow, request fields, and result are in [Connect accounts](/guides/connect-accounts), and the redirect parameters are in [Redirect parameters](/guides/connect-accounts#redirect-parameters).

```bash theme={null}
curl -X POST https://api.social-api.ai/v1/accounts/connect \
  -H "Authorization: Bearer $SOCAPI_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "platform": "instagram",
    "redirect_uri": "https://app.example.com/oauth/callback",
    "state": "session_abc123"
  }'
```

Response (HTTP 202):

```json theme={null}
{
  "auth_url": "https://www.instagram.com/oauth/authorize/?client_id=1234567890&redirect_uri=https%3A%2F%2Fapi.social-api.ai%2Foauth%2Fcallback%2Finstagram&response_type=code&state=4a8f2c1e9b3d7f06a5c2e8b4d1f3a7e2#weblink",
  "state": "4a8f2c1e9b3d7f06a5c2e8b4d1f3a7e2",
  "message": "Open this link to connect your instagram account. Once you've authorized, the account will be connected automatically."
}
```

Instagram-specific rules:

* **Account type.** The person must connect an Instagram Business or Creator account. A personal account cannot be connected.
* **One account per brand.** A brand holds one Instagram account. With [Facebook Login](#connect-through-facebook-login), each further Instagram account the login granted appears as a Page of the brand's Instagram account. Connecting a different Instagram account to the same brand ends with `status=error` and `error=account.already_linked` on your `redirect_uri`.
* **Reconnect.** If a token is no longer valid, calls return `401 platform.instagram.auth` and the account needs reconnecting. See [Reconnect an account](/guides/connect-accounts#reconnect-an-account).
* **Permissions.** Send `permissions` to ask the person for fewer scopes: see [Scopes](#scopes).

## Connect through Facebook Login

Connect through Facebook Login when the Instagram account has a linked Facebook Page and you need to delete published posts, like comments, or set the paid-partnership label. Instagram Login stays the default: send no `connection_type` and nothing changes. The two paths are the same platform, `instagram`, and every call, field, and webhook event is the same unless this section says otherwise.

Select Facebook Login with `metadata.connection_type: "facebook_login"` on `POST /v1/accounts/connect`. Any other value, or none, connects through Instagram Login.

```bash theme={null}
curl -X POST https://api.social-api.ai/v1/accounts/connect \
  -H "Authorization: Bearer $SOCAPI_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "platform": "instagram",
    "redirect_uri": "https://app.example.com/oauth/callback",
    "state": "session_abc123",
    "metadata": {"connection_type": "facebook_login"}
  }'
```

Response (HTTP 202):

```json theme={null}
{
  "auth_url": "https://www.facebook.com/v25.0/dialog/oauth?client_id=1234567890&redirect_uri=https%3A%2F%2Fapi.social-api.ai%2Foauth%2Fcallback%2Finstagram&state=4a8f2c1e9b3d7f06a5c2e8b4d1f3a7e2&response_type=code&auth_type=rerequest&scope=...",
  "state": "4a8f2c1e9b3d7f06a5c2e8b4d1f3a7e2",
  "message": "Open this link to connect your instagram account. Once you've authorized, the account will be connected automatically."
}
```

The person signs in to Facebook, not Instagram, and approves the scopes in [Facebook Login scopes](#facebook-login-scopes). The redirect then carries `status=success` and the brand's Instagram account, as described in [Redirect parameters](/guides/connect-accounts#redirect-parameters).

### More than one Instagram account under one login

A Facebook login can administer more than one Instagram account. The brand's Instagram account holds every Instagram account the login granted that none of your other brands holds, each as a Page. The `platform_page_id` of such a Page is the Instagram account ID. List the Pages with `GET /v1/accounts/{id}/pages`, and publish to one with `page_id` on the post target: see [Delivery](/guides/delivery). A Facebook Page with no linked Instagram account is not listed.

* A login that grants no Instagram account ends with `status=error` and `error=platform.instagram.no_pages` on your `redirect_uri`.
* A login whose every Instagram account belongs to another of your brands, or is already held through Instagram Login, ends with `status=error` and `error=platform.instagram.no_assignable_pages`.
* A brand whose Instagram account is connected through a different Facebook login ends with `status=error` and `error=account.different_login`. Disconnect the brand's Instagram account first.

### Requirements

* The Instagram account is a Business or Creator account linked to a Facebook Page. An account with no linked Page does not appear in the connection: use Instagram Login.
* The person holds the Page task that each capability needs. Meta grants an Instagram scope only for a task the person holds on the Page: create content for publishing, moderate for comments, messaging for DMs, and analyze for insights.
* A DM or private reply on an account with no Facebook Page linked to it returns `409 platform.instagram.no_page`. Reconnect the account.

### One path per Instagram account

Hold each Instagram account through one path. Connecting through Facebook Login does not add an account that you hold through Instagram Login: if no account remains, the connection ends with `status=error` and `error=platform.instagram.no_assignable_pages`. To switch an account to Facebook Login, disconnect it, then connect it again with `connection_type: "facebook_login"`.

### Differences from Instagram Login

| Feature | Instagram Login | Facebook Login |
| - | - | - |
| Linked Facebook Page | Not needed | Required |
| Instagram accounts per connection | One | Every account the login administers, each as a Page of the brand's Instagram account |
| Delete a published post | No | Yes: `DELETE /v1/posts/{pid}` deletes it, and `POST /v1/posts/{pid}/unpublish` removes it from Instagram and keeps it in SocialAPI |
| Like a comment | No | Yes |
| `message_tag: "HUMAN_AGENT"` on a DM | Extends the window to 7 days | Not sent: the DM goes out untagged and the 24-hour window applies |
| `content_type` on a post | Required | Optional. `stories` and `carousel` apply as given. Otherwise, including `feed` and `reel`, the media decides: one video publishes as a Reel, one image as a feed post, 2 or more items as a carousel |
| Paid-partnership label | Either key fails validation | `platform_data.is_paid_partnership` (`true` or `false`) and `platform_data.branded_content_sponsor_ids` (1 or 2 numeric Instagram account IDs) |
| Scope names | `instagram_business_*` | `instagram_*` and `pages_*` |

Every other row of the Capabilities table behaves the same on both paths.

### Facebook Login scopes

SocialAPI's Meta app requests these scopes at connect. You apply for no app review. Each scope belongs to the account [permissions](/guides/permissions) in the last column, and the consent screen asks for the scopes of the permissions you selected. The scopes marked Every account are always requested.

| Scope | Used for | Permissions |
| - | - | - |
| `instagram_basic` | Profile and media | Every account |
| `pages_show_list` | List the Pages the person manages | Every account |
| `pages_read_engagement` | Read engagement on the linked Page | Every account |
| `pages_read_user_content` | Read content on the linked Page | Every account |
| `pages_manage_metadata` | Subscribe the linked Page to webhook events | Every account |
| `business_management` | List Pages owned through a Business Portfolio | Every account |
| `instagram_content_publish` | Publish posts and Reels | `posts.write` |
| `instagram_manage_contents` | Delete a published post | `posts.write` |
| `instagram_manage_comments` | Read, reply to, hide, and delete comments, read mentions, and the first comment | `comments.read`, `comments.write` |
| `instagram_manage_engagement` | Like a comment | `comments.write` |
| `instagram_manage_messages` | Read and send DMs and private replies | `messages.read`, `messages.write` |
| `pages_messaging` | Receive DM events for the linked Page | `messages.read`, `messages.write` |
| `instagram_manage_insights` | Account summary and post insights | `analytics.read` |

The account stays limited to the permissions you selected: an account connected with `comments.read` alone cannot reply to comments.

## Comments

List comments on a post with `GET /v1/inbox/comments/{postId}`, where `postId` is the post's platform ID (`targets[].platform_post_id`). Reply, hide, unhide, and delete work as described in [Comments](/guides/comments). Instagram-specific rules:

* On Instagram Login, a comment's `capabilities.can_like` is always `false`, because Instagram has no like endpoint for comments on that path. On [Facebook Login](#connect-through-facebook-login) it is `true`.

## Private replies

A private reply sends a DM to the person who commented. Send it with `POST /v1/inbox/comments/{postId}/{commentId}/private-reply`.

* Instagram allows one private reply per comment, within 7 days of the comment. A second reply, or a comment older than 7 days, returns `400 platform.instagram.private_reply_ineligible`.
* A private reply does not open the 24-hour messaging window: the person's answer does.
* The request accepts up to 3 `buttons`, sent as a button template.
* An [Automation](/guides/automations) can send the private reply whenever a comment matches its keywords.

## Direct messages and the messaging window

An Instagram account can message a person only inside the 24-hour messaging window that the person's last message opened. Outside it, the send returns `400 platform.instagram.window_closed`. On Instagram Login, send `message_tag: "HUMAN_AGENT"` to reply up to 7 days after the person's last message. Instagram Login accepts no other tag: any other value returns `400 validation.invalid_message_tag`. On [Facebook Login](#connect-through-facebook-login), `message_tag` is not sent: the DM goes out untagged and the 24-hour window applies.

* **Message types.** Text, attachments, quick replies, buttons, and cards. Each attachment in `attachments[]` has a `source_type` (`url`, `media_id`, or `platform_attachment_id`) and a `type`. `type` is required for `platform_attachment_id`, or the request returns `400 validation.attachment_type_required`. Field rules are in [Direct messages](/guides/direct-messages).
* **Size limits.** Instagram sets them and refuses a larger message: text up to 1,000 bytes of UTF-8; images in PNG or JPEG up to 8 MB; video in MP4, OGG, AVI, MOV, or WebM up to 25 MB; audio in AAC, M4A, WAV, or MP4 up to 25 MB; files in PDF up to 25 MB.
* **Unsending.** Instagram does not let apps unsend or delete a sent DM. When the other person unsends a message, you receive a `dm.deleted` event and the message disappears from the conversation.
* **Reactions.** `POST /v1/inbox/conversations/{id}/messages/{messageId}/reaction` reacts to a message with any emoji, and `DELETE` on the same path removes the reaction.
* **Story mentions.** A story that mentions your account arrives as `dm.received` with an attachment of type `story_mention`, not as `mention.received`.

### Participant profile

`GET /v1/platforms/instagram/accounts/{id}/participants/{participantId}/profile` returns the profile of a person in a conversation, including whether they follow the account (`is_user_follow_business`) and whether the account follows them (`is_business_follow_user`). `participantId` is the `participant_id` of the conversation.

```bash theme={null}
curl "https://api.social-api.ai/v1/platforms/instagram/accounts/acc_01HZ9X3Q4R5M6N7P8V2K0W1J/participants/2287522528728101/profile" \
  -H "Authorization: Bearer $SOCAPI_KEY"
```

Response (HTTP 200):

```json theme={null}
{
  "id": "2287522528728101",
  "username": "janedoe",
  "name": "Jane Doe",
  "profile_pic": "https://scontent.cdninstagram.com/v/.../profile.jpg",
  "follower_count": 310,
  "is_user_follow_business": true
}
```

* Read the follow fields at each call, because they change when a person unfollows.
* `profile_pic` links expire: do not store them.
* Instagram discloses a profile only for a person who messaged the account or tapped an icebreaker or the persistent menu. For anyone else the call returns `403 platform.instagram.230`, which means Instagram withholds the data. It does not mean the person does not follow the account.
* A field that Instagram has no value for, such as `name`, is absent.
* `is_verified_user`, `is_user_follow_business`, and `is_business_follow_user` are absent when `false`, and `follower_count` is absent when it is `0`. An absent follow flag means the person does not follow in that direction, or Instagram did not report it: the response does not tell the two apart. When Instagram withholds the relationship because the person has not given consent, the call returns `403 platform.instagram.230` instead.

## Mentions

`GET /v1/accounts/{id}/mentions` returns media in which another account tagged yours. An @mention written in a caption or a comment is not in that list: it arrives as a `mention.received` event, with `metadata.mention_type` set to `comment` or `caption`. Reply to a mention with `POST /v1/accounts/{id}/mentions/reply`. A story mention arrives as a DM: see [Direct messages](#direct-messages-and-the-messaging-window). Details are in [Mentions](/guides/mentions).

## Stories

`GET /v1/platforms/instagram/accounts/{id}/stories` lists the stories that are live now. Instagram removes a story 24 hours after posting, so a call returns nothing older. The request takes `limit` (1 to 100, default 20) and `cursor`, and no `since`.

```bash theme={null}
curl "https://api.social-api.ai/v1/platforms/instagram/accounts/acc_01HZ9X3Q4R5M6N7P8V2K0W1J/stories?limit=10" \
  -H "Authorization: Bearer $SOCAPI_KEY"
```

Response (HTTP 200):

```json theme={null}
{
  "data": [
    {
      "id": "17895695668004550",
      "platform": "instagram",
      "caption": "",
      "media_type": "VIDEO",
      "media_url": "https://scontent.cdninstagram.com/v/t51.../story.jpg",
      "permalink": "https://www.instagram.com/stories/acmecorp/17895695668004550/",
      "timestamp": "2026-10-12T12:00:00Z",
      "like_count": 0,
      "comments_count": 0,
      "shares_count": 0,
      "view_count": 0,
      "account_id": "acc_01HZ9X3Q4R5M6N7P8V2K0W1J",
      "metadata": {
        "is_story": true,
        "expires_at": "2026-10-13T12:00:00Z"
      }
    }
  ],
  "count": 1
}
```

Each item has `id`, `platform`, `caption`, `media_type`, `media_url`, `permalink`, `timestamp`, `like_count`, `comments_count`, `shares_count`, `view_count`, `account_id`, and `metadata`. `like_count`, `comments_count`, `shares_count`, and `view_count` are always `0` on a story. An item also carries `settings` when Instagram reports any: see [Settings on published posts](/platforms/instagram/publishing#settings-on-published-posts). `metadata.is_story` is always `true`, and `metadata.expires_at` is the posting time plus 24 hours. For a video story with no `media_url`, the cover image is returned as `media_url`.

## Collaboration invites

A collaborator is invited when a post is published, with `platform_data.collaborators`: see [Instagram publishing](/platforms/instagram/publishing#platform-data-fields). Instagram has no call that adds a collaborator to a published post. Three calls remain:

| Method | Path | Description |
| - | - | - |
| `GET` | `/v1/platforms/instagram/accounts/{id}/media/{mediaId}/collaborators` | Lists the collaborators of a post and the `status` of each invite. Call it with the account that published the post |
| `POST` | `/v1/platforms/instagram/accounts/{id}/media/{mediaId}/collab/accept` | Accepts a pending invite and publishes the co-authored post on this account's feed. Call it with the invited account. An invite expires 14 days after it is sent |
| `POST` | `/v1/platforms/instagram/accounts/{id}/media/{mediaId}/collab/decline` | Declines a pending invite. The post does not appear on this account's feed. Call it with the invited account |

The list call returns HTTP 200:

```json theme={null}
{
  "data": [
    { "id": "17841405793187218", "username": "janesmith", "status": "pending" }
  ],
  "count": 1
}
```

`status` is `accepted`, `pending`, or `declined`.

Accepting or declining with no pending invite for the account on that media returns an error from Instagram. Accept and decline return `{"success": true}`.

## Account summary

`GET /v1/platforms/instagram/accounts/{id}/summary` returns live profile counts and insight totals for the trailing 30 days.

```bash theme={null}
curl "https://api.social-api.ai/v1/platforms/instagram/accounts/acc_01HZ9X3Q4R5M6N7P8V2K0W1J/summary" \
  -H "Authorization: Bearer $SOCAPI_KEY"
```

Response (HTTP 200):

```json theme={null}
{
  "username": "acmecorp",
  "display_name": "Acme Corp",
  "picture_url": "https://scontent.cdninstagram.com/v/t51.../profile.jpg",
  "follower_count": 12400,
  "following_count": 87,
  "media_count": 340,
  "reach": 22400,
  "views": 90100,
  "interactions": 5500,
  "accounts_engaged": 4000,
  "net_follows": 120,
  "period_start": "2026-09-13T10:00:00Z",
  "period_end": "2026-10-13T10:00:00Z"
}
```

The insight totals need the `analytics.read` [permission](/guides/permissions) on the account. An account without it returns `403 account.permission_missing`. When Instagram withdraws the insights access, the next call can return `403 platform.instagram.insights_scope_missing` instead: reconnect the account. Instagram's insight data can lag by up to 48 hours. Per-post and per-account metrics over a window you choose are in [Analytics](/guides/analytics).

## Webhook events

Instagram accounts emit these events to your webhook endpoints. Payloads are in [Webhook events](/guides/webhook-events).

| Event | When it fires |
| - | - |
| `comment.received` | A person comments on a post |
| `mention.received` | Another account @mentions yours in a caption or a comment |
| `dm.received` | A person sends a DM, including a story mention |
| `dm.sent` | A message left the account, including one sent from the Instagram app |
| `dm.deleted` | A person unsent a message |
| `dm.referral` | A person opened a conversation from an ad or referral link without sending a message |
| `dm.postback` | A person tapped a quick reply or a button |
| `dm.status.sent` | Instagram accepted a DM you sent |
| `dm.status.read` | A person read a DM you sent. Instagram sends no delivery receipts, so there is no `dm.status.delivered` |
| `account.connected` | You finished connecting or reconnecting the account |
| `account.disconnected` | The person revoked access to the account on Instagram, or SocialAPI flagged the account for reconnection (`reconnect_required: true`, see `reason`) |
| `account.updated` | The account lost [permissions](/guides/permissions) you did not remove yourself (`change` is `permissions_reduced`) |
| `post.published`, `post.partial`, `post.failed` | A post to this account finished: see [Delivery](/guides/delivery) |

Every `post.*` event in [Webhook events](/guides/webhook-events#posts) is emitted for this platform.

## Limits

| Limit | Value |
| - | - |
| Caption | 2,200 characters, 30 hashtags, 20 mentions |
| Carousel | 2 to 10 items |
| Posts | 45 per 24 hours and 25 per hour for each account. Instagram's own cap is 50 per rolling 24 hours: see [Posting velocity caps](/guides/rate-limits#posting-velocity-caps) |
| Private reply | 1 per comment, within 7 days |
| Instagram's own rate limit | `429 platform.instagram.rate_limit`. Credit rules: see [when a credit comes back](/guides/plans#when-a-credit-comes-back) |

`GET /v1/accounts/{id}/limits` returns `posts_remaining`, the posts left in Instagram's rolling 24 hours.

## Scopes

SocialAPI's Meta app requests these scopes at connect through Instagram Login. You apply for no app review. The scopes of Facebook Login are in [Facebook Login scopes](#facebook-login-scopes). Each scope belongs to the account [permissions](/guides/permissions) in the last column, and the consent screen asks for the scopes of the permissions you selected. `instagram_business_basic` is always requested.

| Scope | Used for | Permissions |
| - | - | - |
| `instagram_business_basic` | Profile and media | Every account |
| `instagram_business_manage_comments` | Read, reply to, hide, and delete comments, read mentions, and the first comment | `comments.read`, `comments.write` |
| `instagram_business_manage_messages` | Read and send DMs and private replies | `messages.read`, `messages.write` |
| `instagram_business_content_publish` | Publish posts, Reels, carousels, and Stories | `posts.write` |
| `instagram_business_manage_insights` | Account summary and post insights | `analytics.read` |

Instagram asks for comments and for messages as 1 scope each, covering both reading and writing, so the consent screen shows the broader scope. The account stays limited to the permissions you selected: an account connected with `comments.read` alone cannot reply to comments.

## Related

* [Instagram publishing](/platforms/instagram/publishing): fields, media rules, and quirks for publishing
* [Connect accounts](/guides/connect-accounts): the shared connect flow
* [Automations](/guides/automations): comment-to-DM and the Follow gate
* [Platforms](/platforms/overview): the capability matrix
* [Errors](/guides/errors): every error code


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.