Someone comments “LINK” on an Instagram post. Your application sends a private reply asking whether they want the guide. They tap “Send the guide,” and your webhook receives a stable action ID instead of a sentence you have to interpret.
That is the useful part of Instagram buttons: not decoration, but a deliberate transition from a comment into a conversation. The distinction matters because sending the private reply does not, by itself, give you permission to send another message.
Outstand supports quick replies, postback buttons and URL buttons on Instagram messages, including the initial comment-to-DM request. They do different jobs. Here is how to choose between them, handle the resulting webhook and avoid building a flow that depends on every Instagram client displaying the same interface.
Three controls, two different outcomes
A quick reply is a suggested answer. Tapping it sends the title as the contact's message and dismisses the choices. Meta documents a maximum of 13 quick replies, titles of up to 20 characters before truncation, and no desktop support in its quick replies reference.
A postback button is an action attached to a button-template message. Tapping it sends a payload back to your application. In Outstand, that becomes an inbound message with interaction.type: "button". Unlike quick replies, the buttons stay attached, so the person can tap again later.
A URL button opens a web page. It does not send a reply to your application and does not open the messaging window. If your only objective is delivering a destination, that might be exactly what you want. If you need a reply before continuing, it is the wrong control.
Meta's button-template documentation describes the two template actions as postback and web_url. Outstand calls the latter url in its request schema and translates it for Meta.
Control | Outstand field | What comes back | Opens the standard reply window? |
|---|---|---|---|
Quick reply |
|
| Yes, when the inbound tap arrives |
Postback |
|
| Yes, when the inbound tap arrives |
URL |
| No messaging reply from the click | No |
These are Instagram options in Outstand, not portable decorations for every network. Facebook Page private replies are plain text; attaching an instagram object to a Facebook conversation is rejected.
First, keep the private-reply rules intact
For ordinary post and Reel comments, Meta allows one private reply per comment, within seven days. Further messages require the recipient to respond and must fit the standard 24-hour response window. Instagram Live has a different restriction: private replies are limited to the live broadcast. This guide concerns post and Reel comment flows, not Live automation.
Those constraints come from Meta's private-replies documentation. Adding a button does not remove them. On a new conversation, Outstand keeps lastInboundAt null until the contact answers and rejects ordinary follow-up sends before then.
For account setup, use a Business or Creator account, enable message access and request the messaging permissions described in the Outstand comment-to-DM guide. Subscribe your endpoint to both comment.received and message.received. For BYOK, subscribe your Meta app to comments, messages and messaging_postbacks on its verified callback. Both app-level and account-level subscriptions are required; Outstand configures the account-level fields when you connect with the appropriate granted permissions. messaging_postbacks is necessary for template-button replies, not just messages.
If you need the basic comment filtering and account connection flow first, start with Instagram comment-to-DM automation.
Send a private reply with a quick reply
Take accountId, commentId and authorId from the verified comment.received event. Use those as social_account_id, instagram.comment_id and instagram.author_id in POST https://api.outstand.so/v1/conversations.
This is a complete example request body; replace the illustrative IDs with the webhook's values:
1{
2 "social_account_id": "x8Kp2",
3 "content": "Want the guide? Tap below, or reply GUIDE if you cannot see the option.",
4 "instagram": {
5 "comment_id": "17865799348089039",
6 "author_id": "17841400000000000",
7 "quick_replies": [
8 { "title": "Send the guide", "id": "GUIDE_SEND_V1" }
9 ]
10 }
11}Authenticate server-side with Authorization: Bearer YOUR_API_KEY and send JSON with Content-Type: application/json. Store the returned conversation ID with your campaign state. It is the ID you will use for the next message, not the Instagram comment ID.
Choose quick replies when the choices belong to one prompt: selecting a size, requesting a guide or declining an offer. Although 13 are supported, a single clear answer is often enough for comment-to-DM. More choices mean more branches to maintain and more opportunities to confuse the request.
Use a postback when the action should remain available
For a persistent action, replace quick_replies with buttons:
1{
2 "social_account_id": "x8Kp2",
3 "content": "Tap to request the guide, or reply GUIDE.",
4 "instagram": {
5 "comment_id": "17865799348089039",
6 "author_id": "17841400000000000",
7 "buttons": [
8 { "type": "postback", "title": "Send the guide", "id": "GUIDE_SEND_V1" }
9 ]
10 }
11}Outstand permits one to three template buttons, titles up to 20 characters and postback IDs up to 1,000 characters, unique within the message. Template content must be no longer than 640 characters. You cannot combine buttons with quick replies or media_urls.
Quick replies also require text content, cannot accompany media_urls, and have IDs up to 1,000 characters, unique within the message. Outstand rejects overlong titles rather than relying on Instagram to truncate them. The message lifecycle reference covers both schemas.
To open a destination instead, use a button such as { "type": "url", "title": "Read the guide", "url": "https://example.com/guide" }. Do not wait for message.received after that click. Website analytics can measure a visit, but a visit is not a messaging reply.
Route the tap by interaction.id
Outstand normalizes quick-reply payloads and postbacks into the same message.received surface. This abridged event shows a postback:
1{
2 "event": "message.received",
3 "data": {
4 "conversationId": "9dyJS",
5 "messageId": "5vWxY",
6 "network": "instagram",
7 "content": "Send the guide",
8 "interaction": { "type": "button", "id": "GUIDE_SEND_V1" }
9 }
10}Match the ID and expected interaction type, then load your campaign record for that conversation. Do not use the visible title as your only routing key: copy changes, translations and typed messages can all produce the same text without representing the same button action.
After this inbound interaction, send the guide through POST https://api.outstand.so/v1/conversations/9dyJS/messages, with a body such as { "content": "Here is your guide: https://example.com/guide" }. The inbound message opens the standard 24-hour window. Process promptly; a queue delay or future scheduled send can put delivery outside it.
For the typed fallback, handle an explicit GUIDE reply separately and only within an active campaign. The message still opens the window, but it has no button interaction.id. Treating every occurrence of “guide” in every conversation as a campaign request creates surprises.
Design for clients, requests and repeated taps
Quick replies are unavailable on Instagram desktop. Your plain-text prompt must therefore explain how to continue without them. Do not claim template buttons are a universal desktop workaround: verify their behavior on the clients your audience uses.
Meta also says private replies go to the inbox for followers and the Requests folder for non-followers. Test with a genuinely new contact, not only an established thread. A message reaching Requests is not evidence that its controls will render or behave identically to an accepted conversation. A successful API response is not a guarantee of a particular Meta interface.
Before launch, test a follower, a non-follower in Requests, an accepted conversation and desktop. Confirm the actual inbound webhook, not just a screenshot of an outbound message.
Verify webhook signatures, acknowledge quickly and process through a durable queue. Deduplicate deliveries by event identity and account scope. Also prevent duplicate business actions: two separate taps on a persistent postback are two real messages, not necessarily a webhook retry. Record whether this campaign has already delivered the guide.
Use short, opaque action IDs and resolve sensitive context server-side. They are routing data, not authorization. Check the conversation's organization, campaign and expected state before fulfilling a request.
The simplest reliable design is one prompt, one explicit inbound action and one useful response. Explore the comment-to-DM solution for the overall architecture, then implement against the API guide. Buttons make answering easier; the webhook and the messaging window decide what happens next.