Skip to main content

RCS Templates

Learn how to create and structure RCS templates (TEXT, CARD, CAROUSEL) using the POST /api/message-server/rcs/templates endpoint. This guide covers JSON structure, field requirements, and real-world examples in multiple programming languages.

Base payload structure

Every RCS template includes a name, description, type, and body. The body structure varies by template type.

{
"name": "Human-readable name",
"description": "Brief template description",
"type": "TEXT | CARD | CAROUSEL",
"body": { /* template content */ }
}
FieldTypeRequiredNotes
namestringYesDisplay name for your template
descriptionstringYesClear description of the template's purpose
typestringYesOne of: TEXT, CARD, CAROUSEL
bodyobjectYesTemplate structure (varies by type)

Common fields (in body)

SMS Fallback (optional)

Provide an SMS alternative that sends automatically if RCS isn't available on the recipient's device. Both sender and text are required if you define fallbackSms.

"fallbackSms": {
"sender": "SMS-SENDER",
"text": "SMS message text"
}
SMS Fallback Requirements
  • sender: Your authorized SMS sender ID (typically 4-11 alphanumeric characters)
  • text: Fallback message content (must match template language and tone)

Suggestions (optional)

Add interactive buttons and actions that recipients can tap. Each suggestion defines the action type and required fields:

  • type: action type (url, dial, reply, coordinates, location, calendar)
  • text: button label (displays to the user)
"suggestions": [
{
"type": "url",
"text": "Visit website",
"url": { "url": "https://example.com" }
},
{
"type": "dial",
"text": "Call us",
"dial": { "phoneNumber": "+39037224525" }
}
]

Best practices for suggestions:

  • Keep button text concise (under 25 characters)
  • Use action-oriented labels ("Call us", "Learn more", "Shop now")
  • Include 1-4 suggestions per template for optimal UX
  • Ensure phone numbers include country code

TEXT Template

Send rich text messages with optional interactive suggestions and SMS fallback. Perfect for confirmations, alerts, and personalized messages.

Structure

{
"type": "TEXT",
"body": {
"text": "Message text",
"suggestions": [ ... ],
"fallbackSms": { ... }
}
}
FieldRequiredNotes
textYesNon-empty message content (supports placeholders like \{name\})
suggestionsNoArray of interactive buttons and actions
fallbackSmsNoSMS alternative if RCS unavailable

Create a TEXT template

This example creates a welcome message with a website link, call button, and SMS fallback.

curl -X POST https://lora-api.agiletelecom.com/api/message-server/rcs/templates \
-H "X-Api-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Welcome Message",
"description": "Personalized welcome with SMS fallback",
"type": "TEXT",
"body": {
"text": "Hi {name}, welcome to our service!",
"suggestions": [
{
"type": "url",
"text": "Visit our site",
"url": { "url": "https://agiletelecom.com" }
},
{
"type": "dial",
"text": "Call us",
"dial": { "phoneNumber": "+39037224525" }
}
],
"fallbackSms": {
"sender": "AGILE",
"text": "Hi {name}, welcome to our service!"
}
}
}'

CARD Template

Display a single rich card with media, title, description, and interactive actions. Perfect for promotional offers, product showcases, and event announcements.

Structure

{
"type": "CARD",
"body": {
"cardOrientation": "VERTICAL | HORIZONTAL | UNSPECIFIED",
"thumbnailAlignment": "LEFT | RIGHT | UNSPECIFIED",
"card": {
"title": "Title",
"description": "Description",
"media": {
"height": "SHORT | MEDIUM | TALL | UNSPECIFIED",
"fileUrl": "https://..."
},
"suggestions": [ ... ]
},
"suggestions": [ ... ],
"fallbackSms": { ... }
}
}
FieldRequiredNotes
cardOrientationYesLayout: VERTICAL (recommended) or HORIZONTAL
cardYesCard container with title, description, media
card.media.heightIf media presentHeight: SHORT, MEDIUM, TALL
card.media.fileUrlIf media presentPublic URL to image or video (kept online during send)
suggestionsNoCard-level and global-level action buttons

Create a CARD template

This example creates a promotional card with an image, offer details, and action buttons.

curl -X POST https://lora-api.agiletelecom.com/api/message-server/rcs/templates \
-H "X-Api-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Fall Promotion Card",
"description": "Vertical card with seasonal offer",
"type": "CARD",
"body": {
"cardOrientation": "VERTICAL",
"card": {
"title": "Fall promotion",
"description": "20% off selected products",
"media": {
"height": "TALL",
"fileUrl": "https://cdn.example.com/img/offer.jpg"
},
"suggestions": [
{
"type": "url",
"text": "Discover offer",
"url": { "url": "https://shop.example.com/offer" }
}
]
},
"suggestions": [
{
"type": "dial",
"text": "Call us",
"dial": { "phoneNumber": "+39037224525" }
}
],
"fallbackSms": {
"sender": "AGILE",
"text": "Promo -20% on shop.example.com"
}
}
}'

Display a scrollable horizontal list of 2-10 cards. Each card has its own media, content, and actions. Ideal for product catalogs, portfolios, and menus.

Structure

{
"type": "CAROUSEL",
"body": {
"cardWidth": "SMALL | MEDIUM | UNSPECIFIED",
"cards": [
{
"title": "Title",
"description": "Description",
"media": {
"height": "SHORT | MEDIUM | TALL | UNSPECIFIED",
"fileUrl": "https://..."
},
"suggestions": [ ... ]
}
],
"suggestions": [ ... ],
"fallbackSms": { ... }
}
}
FieldRequiredNotes
cardWidthYesCard size: SMALL or MEDIUM
cardsYesArray of 2-10 card objects
cards[].media.heightIf media presentHeight: SHORT, MEDIUM, TALL
cards[].suggestionsNoCard-specific action buttons
suggestionsNoGlobal actions shown below carousel

This example creates a restaurant menu carousel with multiple dishes, photos, and booking actions.

curl -X POST https://lora-api.agiletelecom.com/api/message-server/rcs/templates \
-H "X-Api-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Restaurant Menu Carousel",
"description": "Scrollable menu with dishes and booking",
"type": "CAROUSEL",
"body": {
"cardWidth": "MEDIUM",
"cards": [
{
"title": "Appetizers",
"description": "A burst of flavors.",
"media": {
"height": "SHORT",
"fileUrl": "https://cdn.example.com/appetizers.jpg"
},
"suggestions": [
{
"type": "dial",
"text": "Call now",
"dial": { "phoneNumber": "+39037224525" }
}
]
},
{
"title": "Mains",
"description": "Fresh pasta made locally.",
"media": {
"height": "SHORT",
"fileUrl": "https://cdn.example.com/mains.jpg"
},
"suggestions": [
{
"type": "url",
"text": "View online",
"url": { "url": "https://restaurant.example.com/menu" }
}
]
}
],
"suggestions": [
{
"type": "calendar",
"text": "Book a table",
"calendar": {
"title": "Dinner reservation",
"description": "Reserve your table",
"startTime": "2026-06-15T19:00:00Z",
"endTime": "2026-06-15T21:00:00Z"
}
}
],
"fallbackSms": {
"sender": "AGILE",
"text": "Discover our menu at restaurant.example.com"
}
}
}'

Suggestion types and required fields

TypeDescriptionRequired FieldsExample
replyText reply button-\{ "type": "reply", "text": "Yes", "reply": \{\} \}
urlOpen a web linkurl.url\{ "type": "url", "text": "Learn more", "url": \{"url": "https://example.com"\} \}
dialInitiate a phone calldial.phoneNumber\{ "type": "dial", "text": "Call us", "dial": \{"phoneNumber": "+39037224525"\} \}
coordinatesNavigate to a locationlatitude, longitude\{ "type": "coordinates", "text": "Find us", "locationCoordinates": \{"label": "Store", "latitude": 45.464, "longitude": 9.188\} \}
locationSearch for nearby placeslocationQuery.query\{ "type": "location", "text": "Nearby", "locationQuery": \{"query": "restaurants"\} \}
calendarAdd event to calendarstartTime, endTime\{ "type": "calendar", "text": "Save date", "calendar": \{"title": "Webinar", "startTime": "2026-06-15T14:00:00Z", "endTime": "2026-06-15T15:00:00Z"\} \}
Dates and times

Always use ISO-8601 format: 2026-06-15T14:00:00Z (UTC) or 2026-06-15T14:00:00+02:00 (with timezone offset).

Media in cards

Add images or videos to cards with the media object:

FieldTypeNotes
heightenumRequired if media is present. Options: SHORT (50px), MEDIUM (100px), TALL (200px), UNSPECIFIED
fileUrlstringPublic HTTPS URL to image or video file
Media hosting requirements
  • fileUrl must be publicly accessible (no authentication)
  • Keep files online during the entire campaign send
  • Missing or unreachable media causes send errors
  • Use CDN or stable hosting for reliability

Enumerations reference

Template and card types:

  • type: TEXT | CARD | CAROUSEL
  • cardOrientation: VERTICAL (recommended) | HORIZONTAL | UNSPECIFIED
  • thumbnailAlignment: LEFT | RIGHT | UNSPECIFIED

Media dimensions:

  • height: SHORT | MEDIUM | TALL | UNSPECIFIED
  • cardWidth: SMALL | MEDIUM | UNSPECIFIED

Placeholders for personalization

Personalize templates with dynamic values using placeholders. Wrap variable names in curly braces (e.g., \{firstName\}, \{orderId\}) and provide values during send.

How placeholders work

  1. Define placeholders in your template text
  2. Send a message referencing the template
  3. Provide placeholder values in the placeholders object
  4. Substitution happens automatically

Placeholder example

Template definition:

{
"name": "Order Status",
"type": "TEXT",
"body": {
"text": "Hi {firstName}, your order #{orderId} is being prepared. Estimated delivery: {deliveryDate}."
}
}

Send with values:

{
"templateId": "tpl_123",
"destination": "+391234567890",
"agentId": "agent_abc",
"messageId": "msg-001",
"placeholders": {
"firstName": "Marco",
"orderId": "12345",
"deliveryDate": "June 15"
}
}

Recipient sees:

Hi Marco, your order #12345 is being prepared. Estimated delivery: June 15.
Missing placeholder values

If a placeholder is defined in the template but not provided during send, the unreplaced placeholder (e.g., \{firstName\}) will appear in the message. Always provide all placeholder values.

Common template errors and how to fix them

Template TypeErrorSolution
TEXTMissing body.textEnsure text field is populated and non-empty
CARDMissing body.card or media heightAdd card object and set media.height if including media
CAROUSELMissing cardWidth or empty cardsSet cardWidth and include 2-10 cards in array
MediafileUrl not publicly accessibleUse HTTPS URLs; verify no authentication required
SuggestionsType-field mismatchMatch suggestion type with required fields (e.g., dial needs phoneNumber)
PlaceholdersValues not provided at send timeAlways supply placeholder values to avoid \{placeholder\} appearing in message

Best practices checklist

  • Placeholders: Provide all placeholder values during send to avoid unreplaced text
  • Media URLs: Use stable, public HTTPS URLs; keep them online throughout the campaign
  • Media height: Always specify SHORT, MEDIUM, or TALL for consistent rendering
  • Suggestions: Use consistent, concise button labels (under 25 characters)
  • SMS fallback: If enabled, ensure sender ID is authorized and matches template language
  • Testing: Test with real placeholder values before sending campaigns
  • Card orientation: Default to VERTICAL for optimal mobile display

Next steps

Once you create templates, use the RCS Send API to deliver messages:

  1. Send from template: Reference template ID with placeholder values
  2. Send inline: Create ad-hoc messages without storing templates
  3. Track webhooks: Monitor delivery status and user interactions

See RCS API documentation for send endpoints, authentication, and webhook setup.

To test templates interactively, download the Postman Collection from your dashboard.