Skip to main content

Carousel Messages

Carousel messages display multiple cards that recipients can scroll through horizontally. Each card can include a title, subtitle, image, and action buttons. They are ideal for showcasing products, plans, or options.

Required Scopes​

ScopePurpose
messages:createSend carousel messages

Channel Support​

ChannelSupportImplementationRequest fields
WhatsAppYesApproved carousel templatetemplate_name, language, cards
MessengerYesGeneric templateelements
InstagramYesGeneric templateelements
RCSNoNot through this endpoint; see RCS
TelegramNoNot supported
SMSNoNot supported
EmailNoNot supported
POST /api/v1/messages/send/carousel

Request Body​

FieldTypeRequiredDescription
channel_idstringYesThe channel to send through
contact_idstringYesThe recipient contact
elementsarrayMessenger, InstagramCarousel cards (1-10)
template_namestringWhatsAppName of the approved carousel template
languagestringNoWhatsApp template language (default en)
cardsarrayWhatsAppPer-card values for the template (max 10)
metaobjectNoYour own metadata, stored on the message

Send either elements (Messenger, Instagram) or template_name + cards (WhatsApp), never both.

Element object (Messenger and Instagram):

FieldTypeRequiredDescription
titlestringYesCard title, max 80 characters
subtitlestringNoCard description, max 80 characters
image_urlstringNoAbsolute http(s) URL of the card image
default_actionobjectNoWhat happens when the card itself is tapped: {"type": "web_url", "url": "https://..."}
buttonsarrayNoUp to 3 buttons per card

Button object:

FieldTypeRequiredDescription
typestringYesweb_url (opens a link), postback (sends payload back to you) or phone_number (Messenger only)
titlestringYesButton label, max 20 characters
urlstringweb_urlAbsolute http(s) URL
payloadstringpostbackYour value, max 1000 characters. It comes back when the contact taps the button

curl​

curl -X POST "https://api.sendseven.com/api/v1/messages/send/carousel" \
-H "Authorization: Bearer s7_api_a1b2c3d4e5f6789012345678abcdef00" \
-H "Content-Type: application/json" \
-d '{
"channel_id": "channel_insta_001",
"contact_id": "contact_xyz789",
"elements": [
{
"title": "Wireless Headphones",
"subtitle": "Premium noise-cancelling, EUR 149",
"image_url": "https://shop.example.com/images/headphones.jpg",
"default_action": {"type": "web_url", "url": "https://shop.example.com/headphones"},
"buttons": [
{"type": "web_url", "title": "View Product", "url": "https://shop.example.com/headphones"},
{"type": "postback", "title": "Add to Cart", "payload": "add_headphones"}
]
},
{
"title": "Bluetooth Speaker",
"subtitle": "Portable and waterproof, EUR 79",
"image_url": "https://shop.example.com/images/speaker.jpg",
"buttons": [
{"type": "web_url", "title": "View Product", "url": "https://shop.example.com/speaker"},
{"type": "postback", "title": "Add to Cart", "payload": "add_speaker"}
]
}
]
}'

Python​

import requests

BASE_URL = "https://api.sendseven.com/api/v1"
HEADERS = {
"Authorization": "Bearer s7_api_a1b2c3d4e5f6789012345678abcdef00",
"Content-Type": "application/json",
}

response = requests.post(
f"{BASE_URL}/messages/send/carousel",
headers=HEADERS,
json={
"channel_id": "channel_msngr_001",
"contact_id": "contact_xyz789",
"elements": [
{
"title": "Basic Plan",
"subtitle": "Perfect for small teams",
"image_url": "https://example.com/images/basic.jpg",
"buttons": [
{"type": "web_url", "title": "Learn More", "url": "https://example.com/basic"},
{"type": "postback", "title": "Choose Basic", "payload": "SELECT_BASIC"},
],
},
{
"title": "Scale Plan",
"subtitle": "For growing businesses",
"image_url": "https://example.com/images/scale.jpg",
"buttons": [
{"type": "web_url", "title": "Learn More", "url": "https://example.com/scale"},
{"type": "postback", "title": "Choose Scale", "payload": "SELECT_SCALE"},
],
},
],
},
)
print(response.json())

WhatsApp request​

WhatsApp carousels fill an approved carousel template. Each entry in cards matches one template card, in order:

{
"channel_id": "channel_wa_001",
"contact_id": "contact_xyz789",
"template_name": "product_catalog",
"language": "en",
"cards": [
{
"header": {"type": "image", "url": "https://shop.example.com/images/headphones.jpg"},
"body_parameters": [{"type": "text", "text": "Wireless Headphones"}],
"buttons": [{"type": "url", "index": 0, "parameters": [{"type": "text", "text": "headphones"}]}]
}
]
}

A card header takes either url or media_id; each card has at most 2 buttons.

Response​

201 Created:

{
"id": "msg_car_001",
"conversation_id": "conv_def456",
"external_id": "aWdfZAG1faXRlbToxOklHTWVzc2FnZAUlE",
"status": "sent",
"platform": "instagram",
"cards_count": 2,
"error": null
}

Instagram​

Instagram shows a carousel as a horizontally scrollable row of cards in the Direct inbox. SendSeven checks Instagram's rules before sending, so a carousel Instagram would reject never leaves your account:

RuleLimit
Cards per carousel1 to 10
Card titleRequired, max 80 characters
Card subtitleMax 80 characters
Card contentEach card needs a subtitle, image_url, default_action or button besides its title
Buttons per cardMax 3
Button typesweb_url and postback only
Button labelMax 20 characters
Postback payloadMax 1000 characters
Card tap (default_action)web_url with a url only
ImagesAbsolute http(s) URL; use PNG or JPEG up to 8 MB

Good to know:

  • Carousels show in the Instagram mobile app. Instagram doesn't display them on desktop.
  • Like any Instagram message, a carousel can only be sent within 24 hours of the contact's last message.
  • Messenger-only options are rejected on Instagram rather than dropped silently: phone_number buttons and default_action.webview_height_ratio.

When a rule is broken the request returns 400 with a code in detail, before anything is sent:

{
"detail": {
"error": "CAROUSEL_BUTTON_UNSUPPORTED",
"message": "elements[0].buttons[1].type 'phone_number' is not supported on Instagram; use web_url or postback.",
"field": "elements[0].buttons[1].type",
"channel_type": "instagram"
}
}
detail.errorMeaning
CAROUSEL_LIMIT_EXCEEDEDToo many cards or buttons, or a text is too long
CAROUSEL_ELEMENT_INCOMPLETEA required value is missing, or a card has only a title
CAROUSEL_BUTTON_UNSUPPORTEDA button type Instagram can't show
CAROUSEL_FIELD_UNSUPPORTEDA field Instagram can't show (for example webview_height_ratio)
CAROUSEL_INVALID_URLimage_url, default_action.url or a button url is not an absolute http(s) URL

field points at the value to fix.

Button taps​

A tap on a postback button (Messenger or Instagram) arrives like any other button reply: an inbound message.received event whose text is the button label, with the button's payload in meta.button_id, a {"type": "button_reply", "button_id": "...", "button_title": "..."} attachment and the structured meta.button object (see Webhook events). Flows and bots can branch on it. web_url buttons open the link and send nothing back.

Error Responses​

Most errors return detail as a message string. See Error Handling for the response shapes.

StatusdetailDescription
400"Carousel messages are only supported on WhatsApp, Messenger and Instagram. ..."The channel does not support carousels
400"WhatsApp carousels require 'template_name' and 'cards' fields", "Messenger carousels require 'elements' field", "Instagram carousels require 'elements' field"Required fields for the channel are missing
400"elements[0].image_url is not a valid http(s) URL: ..."A Messenger element URL is not an absolute http(s) URL
400{"error": "CAROUSEL_...", "message": "...", "field": "..."}The carousel breaks an Instagram rule (see Instagram)
400"Contact does not have a WhatsApp ID or phone number", "Contact does not have a Messenger PSID", "Contact does not have an Instagram ID for this channel"The contact can't be reached on this channel
400{"message": "...", "message_id": "...", "error_code": ...}The platform rejected the carousel. The message is stored as failed and the message.failed webhook fires once; error_code is the platform's code when there is one
401"Invalid or expired API token"Token is invalid or expired
403"Missing required permission(s): messages:create"Token lacks the scope
404"Channel not found", "Contact not found"Unknown ID, or it belongs to another workspace
409{"error": "CHANNEL_DISCONNECTED", ...}The channel is disconnected
409{"error": "CONTACT_BLOCKED", ...}The contact is blocked
422list of field errorsInvalid request body (for example more than 10 cards, more than 3 buttons, or a title over 80 characters)
warning

WhatsApp carousels need an approved carousel template, so they can be sent outside the 24-hour window. Messenger and Instagram carousels need no template, but Meta accepts them only inside the platform's messaging window. SendSeven does not block them up front: Meta decides, and a rejected carousel ends as failed.

Next Steps​