> This page is for Platform.

> Fetch clean Markdown by appending `.md` to any page URL under https://signalwire.com/docs or requesting it with the HTTP header `Accept: text/markdown`. The root index at https://signalwire.com/docs/llms.txt lists the available documentation indexes.

# Send RCS messages

> Send plain-text and rich RCS messages, including media, locations, suggestions, cards, and carousels, through the SignalWire Messaging API.

RCS messages are sent through the same endpoint as SMS, MMS, and WhatsApp,
[`POST /api/messaging/messages`](/docs/apis/rest/messages/create-message). Setting `from` to the ID
of your [RCS agent](/docs/platform/messaging/rcs/onboarding) routes the message over RCS. The Agent ID
is shown on the agent's page in the Dashboard.

For the full request schema and authentication, see the
[Send a message](/docs/apis/rest/messages/create-message) API reference. To send SMS and MMS from the
same endpoint, see [Send and receive messages](/docs/platform/messaging/send-and-receive-messages).

The Relay SDK sends RCS the same way: pass your agent's ID as the sender, and the rules and errors
on this page apply. To answer an inbound RCS message from a SWML script, see
[Reply with SWML](/docs/platform/messaging/rcs/receive-messages#reply-with-swml).

## Messaging rules

* `to` must be a US phone number. Numbers in any other country, including Canada and US territories
  such as Puerto Rico, are rejected with `rcs_recipient_country_not_supported`. The examples below
  use `+1555` placeholders, so replace them with a real US number.
* The agent must be `in_review`, `launching`, or `launched`.
* Send either `body` for plain text or `content` for rich content, never both.
* `media` and `message_type` are not supported. Send media with a `content` of type `media` instead.
* `status_callback` and `custom_variables` work the same way as for SMS, as described in
  [Track delivery via REST](/docs/platform/messaging/send-and-receive-messages#track-delivery-via-rest).

Until the agent is launched, it can reach only the test device numbers registered on it. This isn't
checked when you send: a message to any other number is accepted with `status: queued` and isn't
delivered, so watch its [delivery status](/docs/platform/messaging/rcs/receive-messages#track-delivery)
rather than expecting a `422`.

## Content types

Set `content.type` to one of the following. Each value determines the other fields of `content`.

### Schema (`Message.RcsContent`)

```yaml
components:
  schemas:
    MessageRcsMediaContentType:
      type: string
      enum:
        - media
      title: MessageRcsMediaContentType
    MessageRcsLocationContentType:
      type: string
      enum:
        - location
      title: MessageRcsLocationContentType
    MessageRcsSuggestionsContentType:
      type: string
      enum:
        - suggestions
      title: MessageRcsSuggestionsContentType
    MessageRcsReplyActionType:
      type: string
      enum:
        - reply
      title: MessageRcsReplyActionType
    MessageRcsUrlActionType:
      type: string
      enum:
        - url
      title: MessageRcsUrlActionType
    MessageRcsUrlActionWebview:
      type: string
      enum:
        - browser
        - full
        - half
        - tall
      description: >-
        How the URL opens: in the device's browser, or in a webview inside the
        messaging app at full, half, or tall height.
      title: MessageRcsUrlActionWebview
    MessageRcsCallActionType:
      type: string
      enum:
        - call
      title: MessageRcsCallActionType
    MessageRcsLocationActionType:
      type: string
      enum:
        - location
      title: MessageRcsLocationActionType
    MessageRcsCalendarActionType:
      type: string
      enum:
        - calendar
      title: MessageRcsCalendarActionType
    MessageRcsRequestLocationActionType:
      type: string
      enum:
        - request_location
      title: MessageRcsRequestLocationActionType
    Message.RcsAction:
      oneOf:
        - type: object
          properties:
            type:
              $ref: '#/components/schemas/MessageRcsReplyActionType'
            title:
              type: string
              description: Text shown on the suggestion.
          required:
            - type
            - title
          description: >-
            A suggested reply. Tapping it sends a reply to your agent as an
            inbound message.
        - type: object
          properties:
            type:
              $ref: '#/components/schemas/MessageRcsUrlActionType'
            title:
              type: string
              description: Text shown on the suggestion.
            url:
              type: string
              format: uri
              description: The HTTP or HTTPS URL to open.
            webview:
              $ref: '#/components/schemas/MessageRcsUrlActionWebview'
              description: >-
                How the URL opens: in the device's browser, or in a webview
                inside the messaging app at full, half, or tall height.
          required:
            - type
            - title
            - url
          description: Opens a URL on the recipient's device.
        - type: object
          properties:
            type:
              $ref: '#/components/schemas/MessageRcsCallActionType'
            title:
              type: string
              description: Text shown on the suggestion.
            phone:
              type: string
              description: The phone number to call.
          required:
            - type
            - title
            - phone
          description: Starts a phone call from the recipient's device.
        - type: object
          properties:
            type:
              $ref: '#/components/schemas/MessageRcsLocationActionType'
            title:
              type: string
              description: Text shown on the suggestion.
            latitude:
              type: number
              format: double
              minimum: -90
              maximum: 90
              description: Latitude, between -90 and 90.
            longitude:
              type: number
              format: double
              minimum: -180
              maximum: 180
              description: Longitude, between -180 and 180.
            label:
              type: string
              description: Optional label for the pin on the map.
          required:
            - type
            - title
            - latitude
            - longitude
          description: Shows a location on a map on the recipient's device.
        - type: object
          properties:
            type:
              $ref: '#/components/schemas/MessageRcsCalendarActionType'
            title:
              type: string
              description: Text shown on the suggestion.
            event_title:
              type: string
              description: Title of the calendar event.
            start:
              type: string
              description: Start time of the event.
            end:
              type: string
              description: End time of the event.
            description:
              type: string
              description: Optional description of the calendar event.
            fallback_url:
              type: string
              format: uri
              description: >-
                An HTTP or HTTPS URL to open when the device can't create the
                calendar event.
          required:
            - type
            - title
            - event_title
            - start
            - end
            - fallback_url
          description: Adds an event to the recipient's calendar.
        - type: object
          properties:
            type:
              $ref: '#/components/schemas/MessageRcsRequestLocationActionType'
            title:
              type: string
              description: Text shown on the suggestion.
            fallback_url:
              type: string
              format: uri
              description: >-
                An HTTP or HTTPS URL to open when the device can't share its
                location.
          required:
            - type
            - title
            - fallback_url
          description: >-
            Asks the recipient to share their location. The location the
            recipient shares isn't delivered to your application.
      discriminator:
        propertyName: type
      description: >-
        A suggestion shown with a message. The `type` field determines the other
        fields.
      title: Message.RcsAction
    Message.RcsCard:
      type: object
      properties:
        title:
          type: string
          maxLength: 200
          description: Card title. Maximum 200 characters.
        subtitle:
          type: string
          maxLength: 2000
          description: Card subtitle. Maximum 2000 characters.
        media:
          type: string
          format: uri
          description: An HTTP or HTTPS URL to a media file shown on the card.
        actions:
          type: array
          items:
            $ref: '#/components/schemas/Message.RcsAction'
          description: Suggestions shown on the card.
      required:
        - title
      description: 'A rich card: a title with optional subtitle, image, and suggestions.'
      title: Message.RcsCard
    Message.RcsContent:
      oneOf:
        - type: object
          properties:
            type:
              $ref: '#/components/schemas/MessageRcsMediaContentType'
            url:
              type: string
              format: uri
              description: An HTTP or HTTPS URL to the file.
          required:
            - type
            - url
          description: Sends a media file.
        - type: object
          properties:
            type:
              $ref: '#/components/schemas/MessageRcsLocationContentType'
            title:
              type: string
              description: Name of the location.
            latitude:
              type: number
              format: double
              minimum: -90
              maximum: 90
              description: Latitude, between -90 and 90.
            longitude:
              type: number
              format: double
              minimum: -180
              maximum: 180
              description: Longitude, between -180 and 180.
            label:
              type: string
              description: Optional label for the pin on the map.
          required:
            - type
            - title
            - latitude
            - longitude
          description: Sends a location pin.
        - type: object
          properties:
            type:
              $ref: '#/components/schemas/MessageRcsSuggestionsContentType'
            text:
              type: string
              maxLength: 3072
              description: Message text. Maximum 3072 characters.
            actions:
              type: array
              items:
                $ref: '#/components/schemas/Message.RcsAction'
              description: Suggestions shown under the text. At least one.
          required:
            - type
            - text
            - actions
          description: Sends text with suggestions the recipient can tap.
        - type: object
          properties:
            type:
              type: string
              enum:
                - card
              description: 'Discriminator value: card'
            title:
              type: string
              maxLength: 200
              description: Card title. Maximum 200 characters.
            subtitle:
              type: string
              maxLength: 2000
              description: Card subtitle. Maximum 2000 characters.
            media:
              type: string
              format: uri
              description: An HTTP or HTTPS URL to a media file shown on the card.
            actions:
              type: array
              items:
                $ref: '#/components/schemas/Message.RcsAction'
              description: Suggestions shown on the card.
          required:
            - type
            - title
          description: Sends a single rich card.
        - type: object
          properties:
            type:
              type: string
              enum:
                - carousel
              description: 'Discriminator value: carousel'
            cards:
              type: array
              items:
                $ref: '#/components/schemas/Message.RcsCard'
              description: The cards in the carousel. At least 1 and at most 10 cards.
            actions:
              type: array
              items:
                $ref: '#/components/schemas/Message.RcsAction'
              description: Suggestions shown under the carousel. Maximum 3.
          required:
            - type
            - cards
          description: Sends a horizontally scrolling set of rich cards.
      discriminator:
        propertyName: type
      title: Message.RcsContent
```

Suggestions in `actions` take one of these types:

### Schema (`Message.RcsAction`)

```yaml
components:
  schemas:
    MessageRcsReplyActionType:
      type: string
      enum:
        - reply
      title: MessageRcsReplyActionType
    MessageRcsUrlActionType:
      type: string
      enum:
        - url
      title: MessageRcsUrlActionType
    MessageRcsUrlActionWebview:
      type: string
      enum:
        - browser
        - full
        - half
        - tall
      description: >-
        How the URL opens: in the device's browser, or in a webview inside the
        messaging app at full, half, or tall height.
      title: MessageRcsUrlActionWebview
    MessageRcsCallActionType:
      type: string
      enum:
        - call
      title: MessageRcsCallActionType
    MessageRcsLocationActionType:
      type: string
      enum:
        - location
      title: MessageRcsLocationActionType
    MessageRcsCalendarActionType:
      type: string
      enum:
        - calendar
      title: MessageRcsCalendarActionType
    MessageRcsRequestLocationActionType:
      type: string
      enum:
        - request_location
      title: MessageRcsRequestLocationActionType
    Message.RcsAction:
      oneOf:
        - type: object
          properties:
            type:
              $ref: '#/components/schemas/MessageRcsReplyActionType'
            title:
              type: string
              description: Text shown on the suggestion.
          required:
            - type
            - title
          description: >-
            A suggested reply. Tapping it sends a reply to your agent as an
            inbound message.
        - type: object
          properties:
            type:
              $ref: '#/components/schemas/MessageRcsUrlActionType'
            title:
              type: string
              description: Text shown on the suggestion.
            url:
              type: string
              format: uri
              description: The HTTP or HTTPS URL to open.
            webview:
              $ref: '#/components/schemas/MessageRcsUrlActionWebview'
              description: >-
                How the URL opens: in the device's browser, or in a webview
                inside the messaging app at full, half, or tall height.
          required:
            - type
            - title
            - url
          description: Opens a URL on the recipient's device.
        - type: object
          properties:
            type:
              $ref: '#/components/schemas/MessageRcsCallActionType'
            title:
              type: string
              description: Text shown on the suggestion.
            phone:
              type: string
              description: The phone number to call.
          required:
            - type
            - title
            - phone
          description: Starts a phone call from the recipient's device.
        - type: object
          properties:
            type:
              $ref: '#/components/schemas/MessageRcsLocationActionType'
            title:
              type: string
              description: Text shown on the suggestion.
            latitude:
              type: number
              format: double
              minimum: -90
              maximum: 90
              description: Latitude, between -90 and 90.
            longitude:
              type: number
              format: double
              minimum: -180
              maximum: 180
              description: Longitude, between -180 and 180.
            label:
              type: string
              description: Optional label for the pin on the map.
          required:
            - type
            - title
            - latitude
            - longitude
          description: Shows a location on a map on the recipient's device.
        - type: object
          properties:
            type:
              $ref: '#/components/schemas/MessageRcsCalendarActionType'
            title:
              type: string
              description: Text shown on the suggestion.
            event_title:
              type: string
              description: Title of the calendar event.
            start:
              type: string
              description: Start time of the event.
            end:
              type: string
              description: End time of the event.
            description:
              type: string
              description: Optional description of the calendar event.
            fallback_url:
              type: string
              format: uri
              description: >-
                An HTTP or HTTPS URL to open when the device can't create the
                calendar event.
          required:
            - type
            - title
            - event_title
            - start
            - end
            - fallback_url
          description: Adds an event to the recipient's calendar.
        - type: object
          properties:
            type:
              $ref: '#/components/schemas/MessageRcsRequestLocationActionType'
            title:
              type: string
              description: Text shown on the suggestion.
            fallback_url:
              type: string
              format: uri
              description: >-
                An HTTP or HTTPS URL to open when the device can't share its
                location.
          required:
            - type
            - title
            - fallback_url
          description: >-
            Asks the recipient to share their location. The location the
            recipient shares isn't delivered to your application.
      discriminator:
        propertyName: type
      title: Message.RcsAction
```

## Examples

### Plain text

```json
{
  "to": "+15551234567",
  "from": "<YOUR_AGENT_ID>",
  "body": "Your appointment is confirmed for tomorrow at 2pm."
}
```

### Text with suggested replies

```json
{
  "to": "+15551234567",
  "from": "<YOUR_AGENT_ID>",
  "content": {
    "type": "suggestions",
    "text": "Can you make your appointment tomorrow at 2pm?",
    "actions": [
      { "type": "reply", "title": "Yes, confirm" },
      { "type": "reply", "title": "Reschedule" },
      { "type": "call", "title": "Call us", "phone": "+15557654321" }
    ]
  }
}
```

### Rich card

A card has a title and, optionally, a subtitle, a media URL, and suggestions.

```json
{
  "to": "+15551234567",
  "from": "<YOUR_AGENT_ID>",
  "content": {
    "type": "card",
    "title": "Your order has shipped",
    "subtitle": "Order #12345 arrives Thursday.",
    "media": "https://example.com/images/package.png",
    "actions": [
      { "type": "url", "title": "Track your order", "url": "https://example.com/orders/12345" }
    ]
  }
}
```

### Carousel

A carousel holds up to 10 cards and up to 3 suggestions under them.

```json
{
  "to": "+15551234567",
  "from": "<YOUR_AGENT_ID>",
  "content": {
    "type": "carousel",
    "cards": [
      {
        "title": "Classic sneaker",
        "subtitle": "$89",
        "media": "https://example.com/images/classic.png",
        "actions": [{ "type": "url", "title": "Buy", "url": "https://example.com/products/classic" }]
      },
      {
        "title": "Trail runner",
        "subtitle": "$119",
        "media": "https://example.com/images/trail.png",
        "actions": [{ "type": "url", "title": "Buy", "url": "https://example.com/products/trail" }]
      }
    ],
    "actions": [
      { "type": "reply", "title": "Show me more" }
    ]
  }
}
```

## Verify the send

A successful request returns the message with `kind: rcs` and `status: queued`. For a rich message,
`body` in the response holds your `content` serialized as a JSON string. Set `status_callback` to
follow the message as its status changes, as described in
[Receive RCS messages](/docs/platform/messaging/rcs/receive-messages#track-delivery).

When the request is rejected with a `422`, the `code` says why. The RCS-specific codes, and the
general messaging codes an RCS send most often hits, are:

| Code                                                     | Cause                                                                                                       |
| -------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
| `invalid_from_number`                                    | `from` isn't the ID of an RCS agent in this Project. Check for a typo, or an agent ID from another Project. |
| `rcs_agent_not_sendable`                                 | The agent isn't `in_review`, `launching`, or `launched`.                                                    |
| `rcs_agent_not_configured`                               | The agent hasn't been set up for sending messages yet.                                                      |
| `rcs_messaging_not_enabled`                              | RCS isn't enabled for this Space.                                                                           |
| `rcs_recipient_country_not_supported`                    | `to` isn't a US phone number.                                                                               |
| `body_not_allowed_with_rcs_content`                      | The request has both `body` and `content`.                                                                  |
| `rcs_media_not_supported`                                | The request has `media`. Use a `content` of type `media` instead.                                           |
| `rcs_message_type_not_supported`                         | The request has `message_type`. Use `content` instead.                                                      |
| `rcs_content_missing_field`                              | A required field in `content` is missing. The error names its path.                                         |
| `rcs_content_invalid_value`                              | A `type` or `webview` value isn't allowed. The error lists the allowed values.                              |
| `rcs_content_invalid_url`                                | A URL in `content` isn't a valid HTTP or HTTPS URL.                                                         |
| `rcs_content_invalid_coordinate`                         | A latitude or longitude is out of range or not a number.                                                    |
| `rcs_content_too_long`                                   | A text field is longer than its maximum.                                                                    |
| `rcs_content_too_many_items`                             | A carousel has more than 10 cards or more than 3 suggestions.                                               |
| `rcs_content_not_an_object` / `rcs_content_not_an_array` | A field in `content` has the wrong JSON type.                                                               |
| `rcs_content_not_supported`                              | `content` was sent from a phone number instead of an RCS agent.                                             |
| `body_or_media_required`                                 | The request has neither `body` nor `content`.                                                               |
| `character_limit_exceeded`                               | `body` is longer than the character limit. The error states the limit.                                      |
| `sending_restricted_to_verified`                         | Your account can send only to verified numbers, and `to` isn't one of them.                                 |
| `not_routeable`                                          | SignalWire can't route a message to `to`.                                                                   |
| `insufficient_balance`                                   | Your account balance doesn't cover the message.                                                             |

For every other code, see [Error codes](/docs/apis/error-codes).

## Next steps

#### [Send a message (API reference)](/docs/apis/rest/messages/create-message)

The full request schema for every content type.

#### [Receive RCS messages](/docs/platform/messaging/rcs/receive-messages)

Handle inbound messages and track delivery status.