Skip to main content
Version: 1.0

Setting Up the Instagram Channel

The Instagram integration uses the Instagram Messaging API (Meta) via OAuth. The process connects an Instagram Business account to your Application. You can authorize the connection either through Instagram directly or through a linked Facebook account.

Prerequisites​

  • An Instagram Business or Creator account (personal accounts are not supported)
  • A Facebook Page linked to the Instagram account
  • Administrator access to the Facebook Page (required for the Facebook flow)
  • Hub Chatt2.me account with administrator permission on the Application

Connection process​

1. Start authorization​

In the Hub Chatt2.me dashboard:

  1. Go to Channels → Activate/Configure → Instagram
  2. Choose your preferred authorization method:
    • Connect with Instagram — authorizes directly via Instagram OAuth
    • Connect with Facebook — authorizes via the Facebook account linked to the Instagram Page

2a. Instagram OAuth flow​

If you chose Connect with Instagram:

  1. Log in with your Instagram Business or Creator account
  2. Authorize the requested permissions (access to message inbox)
  3. The channel is created automatically

2b. Facebook OAuth flow​

If you chose Connect with Facebook:

  1. Log in with the account that manages the Facebook Page linked to Instagram
  2. Authorize the requested permissions (access to Instagram message inbox)
  3. Select the corresponding Facebook Page
  4. Select the Instagram account linked to that Page

3. Channel ready​

After authorization, the channel is created and the UUID becomes available in the channel details.

Comment automations​

Comment automations watch direct, top-level text comments and send one literal Instagram Direct reply. A rule can apply globally or to one media.id, and it can also post an optional public confirmation beneath the source comment.

Use the API-key application channel with these operations:

  • GET and POST /v1/communication/channel/instagram/{applicationChannelId}/comment-automations
  • GET, PATCH, and DELETE /v1/communication/channel/instagram/{applicationChannelId}/comment-automations/{automationId}
  • GET /v1/communication/channel/instagram/{applicationChannelId}/comment-automations/media
  • GET /v1/communication/channel/instagram/{applicationChannelId}/comment-automations/media/{mediaId}

The API key must belong to the application that owns the exact channel. You may create multiple global rules and multiple rules for the same post. For a post rule, select recent media or provide its exact media.id; the Hub checks ownership with Meta before saving.

Triggers accept at most 100 characters. Exact mode respects case and accents; flexible mode ignores them. Both match a whole word or contiguous phrase anywhere, so pão matches quero um pão but not pãozinho. Public replies accept 500 characters and private replies accept 1,000 UTF-8 bytes. If several rules match, a post-specific rule wins, then the longest trigger, then the oldest rule.

Subscribe the channel webhook to comment_automation to receive the automated outbound after Meta accepts and the Hub persists it. The event includes a real sessionId and message.is_automated: true; it is not duplicated as a messages event. The automated outbound is not charged. The first inbound starts the normal expiration window and is not charged; normal charging begins with the first later non-automated outbound.

Only Feed posts and Reels are supported by this flow. Replies to comments, the connected account's own comments, Stories, Live, and ads are ignored. Comment private replies are a separate provider operation, not permission for ordinary send-message calls. Their eligibility (including time since the comment and any prior private reply) is evaluated by Meta. Provider policies and inbox placement can change; this guide does not guarantee delivery or a seven-day ordinary messaging window.

Create a global rule​

curl -X POST 'https://app.chatt2.me/v1/communication/channel/instagram/YOUR_APPLICATION_CHANNEL_ID/comment-automations' \
-H 'x-api-key: YOUR_APPLICATION_API_KEY' \
-H 'content-type: application/json' \
--data '{"scope":"global","trigger":"catalog","matchMode":"flexible","privateReply":"Here is our catalog: https://example.com/catalog","publicReply":"Please check your inbox.","active":true}'

Keep the returned rule id as automationId. A global rule omits mediaId. Reply strings are literal text; this endpoint does not interpolate template variables.

Discover media and create a post rule​

curl 'https://app.chatt2.me/v1/communication/channel/instagram/YOUR_APPLICATION_CHANNEL_ID/comment-automations/media' \
-H 'x-api-key: YOUR_APPLICATION_API_KEY'

Use a returned data[].id; for another media page, pass the returned after cursor as ?after=.... When after is absent there is no next page. If you already know a media ID, fetch GET /v1/communication/channel/instagram/{applicationChannelId}/comment-automations/media/{mediaId} to confirm ownership/availability. An owned eligible post can then have its own rule:

curl -X POST 'https://app.chatt2.me/v1/communication/channel/instagram/YOUR_APPLICATION_CHANNEL_ID/comment-automations' \
-H 'x-api-key: YOUR_APPLICATION_API_KEY' \
-H 'content-type: application/json' \
--data '{"scope":"media","mediaId":"YOUR_OWNED_MEDIA_ID","trigger":"price","matchMode":"exact","privateReply":"See the price at https://example.com/product","active":true}'

List, read, replace, and delete​

List rules with GET /v1/communication/channel/instagram/{applicationChannelId}/comment-automations?page=1&pageSize=10. page starts at 1; pageSize defaults to 10 and accepts 1–100. Optional search, scope (global/media), and active (true/false) filter the results. Read the stored configuration with GET /v1/communication/channel/instagram/{applicationChannelId}/comment-automations/{automationId}.

PATCH replaces the whole rule, rather than merging individual fields. Send scope, trigger, matchMode, privateReply, and active every time; send mediaId for media scope and publicReply when you want to preserve it. Omitting publicReply clears it. Switching to global scope clears the media association. To deactivate the media rule while preserving its other values:

curl -X PATCH 'https://app.chatt2.me/v1/communication/channel/instagram/YOUR_APPLICATION_CHANNEL_ID/comment-automations/YOUR_AUTOMATION_ID' \
-H 'x-api-key: YOUR_APPLICATION_API_KEY' \
-H 'content-type: application/json' \
--data '{"scope":"media","mediaId":"YOUR_OWNED_MEDIA_ID","trigger":"price","matchMode":"exact","privateReply":"See the price at https://example.com/product","active":false}'

This example intentionally has no public reply. To remove the rule, use DELETE /v1/communication/channel/instagram/{applicationChannelId}/comment-automations/{automationId}; a successful deletion returns HTTP 200 with {"success": true}. See the automation API reference.

Errors and delivery recovery​

All seven management operations, including list/get/delete, require a usable Instagram connection and can return HTTP 400 INSTAGRAM_RECONNECT_REQUIRED. Reconnect in Hub with comment permissions, then retry the management request. Missing or out-of-application channels return HTTP 404 APPLICATION_CHANNEL_NOT_FOUND; get/update/delete of a missing rule return HTTP 404 COMMENT_AUTOMATION_NOT_FOUND. Invalid bodies return HTTP 400; media ownership/eligibility or provider access can also fail, so confirm the selected media instead of repeatedly creating rules.

The optional public reply is attempted only after the private reply succeeds. Its failure does not undo the accepted private message. The Hub deduplicates by channel and comment ID before submission: a repeated provider event does not retry a failed private/public attempt, and editing the rule does not replay that comment. Resolve the connection/content problem for future comments; do not expect webhook replay to resubmit a private reply. The comment_automation message event confirms an accepted, persisted private reply, not success of the later public confirmation.

Identifying the recipient (to)​

The to field on Instagram uses the IGSID — the unique ID of the user in Instagram Messaging. You obtain this ID from the webhook payload when the user sends you a message first.

Inbound participant fragment:

{
"sender": {
"id": "847495124317323"
}
}
warning

Ordinary send-message calls cannot initiate conversations with users who have never sent you a message. Meta's private reply to an eligible comment is the limited exception used by comment automations; follow-up messaging requires the recipient to answer.

Required permissions​

Meta PermissionPurpose
instagram_business_basic / instagram_basicAccess basic account information for Instagram Login / Facebook Login
instagram_business_manage_messages / instagram_manage_messagesSend and receive messages
instagram_business_manage_comments / instagram_manage_commentsRead comments and send public/private comment replies
pages_read_engagementRead Instagram media through the linked Page flow
pages_manage_metadataManage Page metadata
pages_messagingAccess message inbox via API

Accounts connected before comment automations must be reconnected to grant the comment permission. Live accounts outside Meta application roles may also require Advanced Access, App Review, and Business Verification.

Data deletion (LGPD / GDPR)​

Meta requires that apps integrating Instagram implement a data deletion endpoint. When a user requests data deletion from Meta, the Hub receives a notification and processes the deletion automatically.

Limitations​

  • Ordinary messages cannot be sent to users who have never started a conversation; eligible comment automation private replies are the limited exception
  • Ordinary sends use the ordinary provider messaging path and require an eligible existing conversation; do not assume seven days of general messaging permission
  • The Hub uses a 24-hour technical session for Instagram. Session existence/expiration and provider send eligibility are separate; Meta can reject a request even when the Hub has a session
  • The private reply triggered by a comment is separate from ordinary follow-up messaging; the recipient must answer before treating it as an ordinary conversation

Media formats and limits​

TypeFormats currently accepted by the HubOutbound limitInbound mirror limit
ImageJPEG, PNG, GIF, WebP8 MBProvider maximum not published; Hub safety ceiling 2 GiB
AudioAAC, M4A/MP4 and WAV directly; OGG, Opus, MP3/MPEG and WebM input are converted to M4A25 MBProvider maximum not published; Hub safety ceiling 2 GiB
VideoMP4; MOV/QuickTime, AVI, MKV and WebM input is converted to H.264/AAC MP425 MBProvider maximum not published; Hub safety ceiling 2 GiB
StickerInstagram platform identifier such as like_heart; HTTP URLs are rejectedPlatform valuePlatform value
DocumentNot supported—Attachments received from users are preserved when Meta supplies them

The Hub applies only the audio and video conversions listed above. The 25 MB audio/video ceiling is the Hub's conservative attachment contract because Meta's current public documentation does not provide a stable exhaustive MIME-and-size matrix for every Instagram Messaging attachment. Send an ordinary visual through imageUrl; an HTTP(S) value in stickerUrl returns CHANNEL_MEDIA_NOT_SUPPORTED. The inbound 2 GiB value is an operational download protection, not a Meta limit.

Instagram does not support content.text captions with imageUrl, videoUrl, or audioUrl; companion text is discarded. Outbound documentUrl is not supported at all. Send the media and its description in separate requests. See the caption support matrix. Location/contact inputs become text fallbacks; see Content Types.

Identifying the sender (from)​

In POST /v1/communication/instagram/message, set from to the application channel UUID or the Instagram username for that channel (with or without a leading @). The UUID always works as a fallback. See Sending messages overview.

Next steps​