RCS API
What is RCS
RCS (Rich Communication Services) is the evolution of traditional SMS. It allows you to send rich messages with images, videos, interactive buttons, cards, and carousels directly in the phone's native messaging app, without requiring the recipient to install additional applications.
Unlike SMS, RCS messages support:
- Multimedia content (images, videos, GIFs)
- Interactive buttons (reply, open URL, call, location, calendar)
- Cards with title, description, and media
- Carousels of scrollable cards
- Read receipts and typing indicators
- Automatic fallback to WhatsApp and/or SMS if the recipient does not support RCS
:::info Automatic fallback If the recipient does not support RCS, the message is automatically sent via WhatsApp and/or SMS (if configured). This ensures the message always reaches the recipient, regardless of their device. :::
Endpoint
POST https://lora-api.agiletelecom.com/api/message-server/rcs/send
Content-Type: application/json
Authentication: API Key (X-Api-Key) or Basic Auth (Authorization: Basic)
Request fields
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
destination | string | Yes | – | Recipient phone number in international format (e.g., +393401234567) |
agentId | integer | Yes | – | ID of the RCS sender agent associated with your account |
body | object | Yes* | – | RCS message content. *Mutually exclusive with templateId |
templateId | integer | Yes* | – | ID of a pre-configured RCS template. *Mutually exclusive with body |
campaignId | string | No | – | Campaign identifier for grouping multiple messages. Maximum 255 characters |
messageId | string | No | (auto) | Custom message identifier. If not provided, it is automatically generated (UUID) |
simulation | boolean | No | false | If true, the message is processed but not physically sent. Useful for testing |
enableNotification | boolean | No | true | If true, enables delivery and read notifications to your callback URL |
maxSmsParts | integer | No | – | Maximum number of SMS parts allowed for the fallback message. If the fallback text exceeds this limit, the message is not sent via SMS |
placeholders | object | No | – | Key-value map to replace placeholders in the text. E.g., {"name": "Mario"} replaces {name} in the message |
scheduledDate | string | No | – | Scheduled send date and time. Format: yyyy-MM-dd HH:mm:ss.SSSZ (e.g., 2025-10-01 09:00:00.000+0000) |
Body types
The body field must contain a type field that specifies the message format and its related sub-fields.
TEXT
Simple text message, optionally with interactive suggestions.
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | Must be "TEXT" |
text | string | Yes | Message text |
suggestions | array | No | List of interactive suggestions (see Suggestions section) |
CARD
:::tip Best practice for Rich Cards
Always include a mediaUrl with a high-quality image and a clear title. Add at least one interactive suggestion (button) to maximize user engagement.
:::
Message with a single visual element containing media, title, description, and suggestions.
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | Must be "CARD" |
title | string | No | Card title |
description | string | No | Card description |
mediaUrl | string | No | Public URL of the image or video to display in the card |
mediaHeight | string | No | Media height: SHORT, MEDIUM, TALL. Default: MEDIUM |
suggestions | array | No | List of interactive suggestions |
CAROUSEL
Message with multiple horizontally scrollable cards. Each card can have its own title, description, media, and suggestions.
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | Must be "CAROUSEL" |
cards | array | Yes | List of cards (minimum 2, maximum 10). Each card has the same fields as the CARD type (title, description, mediaUrl, mediaHeight, suggestions) |
Suggestions (interactive suggestions)
Suggestions are interactive buttons that appear below the message. Each suggestion has a type and specific fields.
reply
Quick reply with predefined text. When the user clicks, the system receives the postbackData.
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | "reply" |
text | string | Yes | Text displayed on the button |
postbackData | string | Yes | Data sent to your callback when the user clicks |
url
Opens a URL in the device's browser.
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | "url" |
text | string | Yes | Text displayed on the button |
url | string | Yes | URL to open |
dial
Initiates a phone call to the specified number.
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | "dial" |
text | string | Yes | Text displayed on the button |
phoneNumber | string | Yes | Phone number to call (international format) |
locationCoordinates
Opens the map with a pin at the specified coordinates.
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | "locationCoordinates" |
text | string | Yes | Text displayed on the button |
latitude | string | Yes | Latitude (e.g., "45.4642") |
longitude | string | Yes | Longitude (e.g., "9.1900") |
label | string | No | Pin label on the map |
locationQuery
Opens the map with a text search for the address.
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | "locationQuery" |
text | string | Yes | Text displayed on the button |
query | string | Yes | Address or place to search for (e.g., "Via Roma 1, Milano") |
calendar
Creates an event in the device's calendar.
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | "calendar" |
text | string | Yes | Text displayed on the button |
title | string | Yes | Event title |
description | string | No | Event description |
startTime | string | Yes | Start date and time in ISO 8601 format (e.g., "2025-10-15T14:00:00Z") |
endTime | string | Yes | End date and time in ISO 8601 format |
Fallback
RCS supports automatic fallback to other channels when the recipient does not support RCS or the message cannot be delivered.
fallbackWhatsApp
If RCS fails, the system attempts to send the message via WhatsApp.
| Field | Type | Required | Description |
|---|---|---|---|
phoneNumberId | integer | Yes | WhatsApp Business sender phone number ID |
templateId | integer | Yes* | WhatsApp template ID. *Mutually exclusive with body |
body | object | Yes* | Inline WhatsApp body. *Mutually exclusive with templateId |
fallbackSms
If RCS (and the optional WhatsApp fallback) fails, the system sends an SMS.
| Field | Type | Required | Description |
|---|---|---|---|
sender | string | Yes | SMS sender (alphanumeric or numeric) |
text | string | Yes | Fallback SMS text |
Rule: If
fallbackWhatsAppis present,fallbackSmsis mandatory.
Response
{
"messageId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"simulation": false,
"results": {
"rcs": {
"accepted": true,
"reasons": []
},
"sms": null
}
}
| Field | Type | Description |
|---|---|---|
messageId | string | Unique message ID |
simulation | boolean | true if the message was in simulation mode |
results.rcs.accepted | boolean | true if the RCS message was accepted |
results.rcs.reasons | array | List of rejection reasons |
results.sms | object/null | SMS fallback result (if configured, otherwise null) |
Important:
accepted: truemeans the message was accepted for sending, not that it was delivered. Delivery confirmation arrives via callback.
Notifications (Callbacks)
Delivery Notification
Message delivery notification:
{
"channel": "RCS",
"eventType": "DELIVERY",
"messageId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"destination": "+393401234567",
"statusCode": 3,
"description": "delivered",
"eventDate": "2025-10-16T10:42:18Z"
}
| statusCode | Meaning |
|---|---|
3 | Message delivered |
6 | Message undeliverable |
Read Notification
Read notification (the recipient has opened the message):
{
"channel": "RCS",
"eventType": "READ",
"messageId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"destination": "+393401234567",
"eventDate": "2025-10-16T10:43:05Z"
}
Inbound Message
Inbound message notification (the recipient has replied or clicked a suggestion):
{
"channel": "RCS",
"eventType": "INBOUND",
"messageId": "rcs-inbound-id-12345",
"source": "+393401234567",
"destination": "+393209998877",
"receivedDate": "2025-10-16T10:45:00Z",
"messageType": "TEXT",
"text": "Messaggio di risposta dell'utente"
}
For messages with media, the mediaKey field contains the key to download the file.
Media file download
When you receive an inbound message with media, you can download the file via:
GET https://lora-api.agiletelecom.com/api/files/{mediaKey}?expireMinutes=180
The response contains a url field with a temporary (pre-signed) URL for direct file download.
Examples
1. TEXT message with suggestions
Sending a text message with quick reply buttons and a URL button:
{
"destination": "+393401234567",
"agentId": 1,
"body": {
"type": "TEXT",
"text": "Ciao Mario! La tua prenotazione per il 15 ottobre è confermata. Vuoi modificarla?",
"suggestions": [
{
"type": "reply",
"text": "Conferma",
"postbackData": "CONFIRM_BOOKING_123"
},
{
"type": "reply",
"text": "Modifica",
"postbackData": "MODIFY_BOOKING_123"
},
{
"type": "url",
"text": "Vedi dettagli",
"url": "https://example.com/booking/123"
},
{
"type": "dial",
"text": "Chiamaci",
"phoneNumber": "+390212345678"
}
]
},
"enableNotification": true
}
2. CARD message with image
Sending a card with image, title, description, and suggestions:
{
"destination": "+393401234567",
"agentId": 1,
"body": {
"type": "CARD",
"title": "Offerta Speciale",
"description": "Sconto del 30% su tutta la collezione primavera-estate. Valido fino al 31 marzo.",
"mediaUrl": "https://example.com/images/promo-spring.jpg",
"mediaHeight": "MEDIUM",
"suggestions": [
{
"type": "url",
"text": "Scopri l'offerta",
"url": "https://example.com/promo"
},
{
"type": "calendar",
"text": "Ricordamelo",
"title": "Fine promozione primavera",
"description": "Ultimo giorno per lo sconto del 30%",
"startTime": "2025-03-31T09:00:00Z",
"endTime": "2025-03-31T23:59:00Z"
}
]
},
"campaignId": "promo-primavera-2025"
}
3. Send with templateId
Sending a message using a pre-configured RCS template with placeholders:
{
"destination": "+393401234567",
"agentId": 1,
"templateId": 42,
"placeholders": {
"nome": "Mario",
"codiceOrdine": "ORD-2025-789",
"dataConsegna": "18 ottobre 2025"
},
"enableNotification": true
}
Error codes
| HTTP Code | Meaning | What to do |
|---|---|---|
200 | Request processed | Check results.rcs.accepted to verify acceptance |
400 | Bad request | Verify required fields (destination, agentId, body or templateId) |
401 | Not authenticated | Verify your API Key or Basic Auth credentials |
403 | Access denied | IP not in whitelist or unauthorized resource |
404 | Not found | Template or agent does not exist |
422 | Unprocessable entity | Data is syntactically correct but semantically invalid |
429 | Too many requests | You have exceeded the rate limit. Retry after the indicated period |
500 | Internal server error | Retry later. If the problem persists, contact support |