---
title: "Send an RCS message"
method: POST
path: "/v1/rcs/messages"
tags: ["RCS"]
---

# Send an RCS message

`POST /v1/rcs/messages`

Sends from one of your agents. Use `text` for a plain message or `content` for rich
content (card, carousel, media, suggestion chips). Before launch an agent only reaches
test phones that accepted the invite. With the agent's `smsFallbackFrom` set, phones
without RCS get `fallbackText` (default: the message's readable text) as SMS.

Replies and status arrive as webhooks with `platform: "rcs"`: `message.received`
(a tapped chip carries its postback in `metadata.postbackPayload`), `message.delivered`,
`message.read` and `message.failed`. Send an `Idempotency-Key` header to make retries safe.

## Headers

- `Idempotency-Key` string

## Request body

- object — Send exactly one of text or content.
  - `agentId` string, required
  - `to` string, required — Recipient number (E.164; formatting is normalized).
  - `text` string
  - `content` union — Message content. `suggestions` (max 11) render as chips under the message.
    - object
      - `type` 'text', required
      - `text` string, required
      - `suggestions` RcsSuggestion[]
        - union — A tappable chip. Labels are max 25 characters. postbackData (max 2048) comes back unchanged in message.received metadata as postbackPayload when tapped; defaults to the label. Any string works, JSON included: values outside A-Z a-z 0-9 - _ . are encoded on the wire and decoded for you.
          - object
            - `type` 'reply', required
            - `text` string, required
            - `postbackData` string
          - object
            - `type` 'dial', required
            - `text` string, required
            - `phoneNumber` string, required — E.164
            - `postbackData` string
          - object
            - `type` 'openUrl', required
            - `text` string, required
            - `url` string, uri, required
            - `application` 'BROWSER' | 'WEBVIEW'
            - `webviewViewMode` 'FULL' | 'HALF' | 'TALL'
            - `postbackData` string
          - object — Needs latitude + longitude, or a query.
            - `type` 'viewLocation', required
            - `text` string, required
            - `latitude` number
            - `longitude` number
            - `query` string
            - `label` string
            - `postbackData` string
          - object
            - `type` 'shareLocation', required
            - `text` string, required
            - `postbackData` string
          - object
            - `type` 'calendarEvent', required
            - `text` string, required
            - `startTime` string, date-time, required
            - `endTime` string, date-time, required
            - `title` string, required
            - `description` string
            - `postbackData` string
    - object
      - `type` 'media', required
      - `media` RcsMedia, required
        - `url` string, uri, required — Public image or video URL.
        - `thumbnailUrl` string, uri — Max 100 KB.
        - `height` 'SHORT' | 'MEDIUM' | 'TALL'
      - `suggestions` RcsSuggestion[]
        - union — A tappable chip. Labels are max 25 characters. postbackData (max 2048) comes back unchanged in message.received metadata as postbackPayload when tapped; defaults to the label. Any string works, JSON included: values outside A-Z a-z 0-9 - _ . are encoded on the wire and decoded for you.
          - object
            - `type` 'reply', required
            - `text` string, required
            - `postbackData` string
          - object
            - `type` 'dial', required
            - `text` string, required
            - `phoneNumber` string, required — E.164
            - `postbackData` string
          - object
            - `type` 'openUrl', required
            - `text` string, required
            - `url` string, uri, required
            - `application` 'BROWSER' | 'WEBVIEW'
            - `webviewViewMode` 'FULL' | 'HALF' | 'TALL'
            - `postbackData` string
          - object — Needs latitude + longitude, or a query.
            - `type` 'viewLocation', required
            - `text` string, required
            - `latitude` number
            - `longitude` number
            - `query` string
            - `label` string
            - `postbackData` string
          - object
            - `type` 'shareLocation', required
            - `text` string, required
            - `postbackData` string
          - object
            - `type` 'calendarEvent', required
            - `text` string, required
            - `startTime` string, date-time, required
            - `endTime` string, date-time, required
            - `title` string, required
            - `description` string
            - `postbackData` string
    - object
      - `type` 'card', required
      - `card` RcsCard, required — Needs a title, description or media.
        - `title` string
        - `description` string
        - `media` RcsMedia
          - `url` string, uri, required — Public image or video URL.
          - `thumbnailUrl` string, uri — Max 100 KB.
          - `height` 'SHORT' | 'MEDIUM' | 'TALL'
        - `suggestions` RcsSuggestion[]
          - union — A tappable chip. Labels are max 25 characters. postbackData (max 2048) comes back unchanged in message.received metadata as postbackPayload when tapped; defaults to the label. Any string works, JSON included: values outside A-Z a-z 0-9 - _ . are encoded on the wire and decoded for you.
            - object
              - …
            - object
              - …
            - object
              - …
            - object — Needs latitude + longitude, or a query.
              - …
            - object
              - …
            - object
              - …
      - `orientation` 'VERTICAL' | 'HORIZONTAL'
      - `thumbnailAlignment` 'LEFT' | 'RIGHT'
      - `suggestions` RcsSuggestion[]
        - union — A tappable chip. Labels are max 25 characters. postbackData (max 2048) comes back unchanged in message.received metadata as postbackPayload when tapped; defaults to the label. Any string works, JSON included: values outside A-Z a-z 0-9 - _ . are encoded on the wire and decoded for you.
          - object
            - `type` 'reply', required
            - `text` string, required
            - `postbackData` string
          - object
            - `type` 'dial', required
            - `text` string, required
            - `phoneNumber` string, required — E.164
            - `postbackData` string
          - object
            - `type` 'openUrl', required
            - `text` string, required
            - `url` string, uri, required
            - `application` 'BROWSER' | 'WEBVIEW'
            - `webviewViewMode` 'FULL' | 'HALF' | 'TALL'
            - `postbackData` string
          - object — Needs latitude + longitude, or a query.
            - `type` 'viewLocation', required
            - `text` string, required
            - `latitude` number
            - `longitude` number
            - `query` string
            - `label` string
            - `postbackData` string
          - object
            - `type` 'shareLocation', required
            - `text` string, required
            - `postbackData` string
          - object
            - `type` 'calendarEvent', required
            - `text` string, required
            - `startTime` string, date-time, required
            - `endTime` string, date-time, required
            - `title` string, required
            - `description` string
            - `postbackData` string
    - object
      - `type` 'carousel', required
      - `cards` RcsCard[], required
        - `title` string
        - `description` string
        - `media` RcsMedia
          - `url` string, uri, required — Public image or video URL.
          - `thumbnailUrl` string, uri — Max 100 KB.
          - `height` 'SHORT' | 'MEDIUM' | 'TALL'
        - `suggestions` RcsSuggestion[]
          - union — A tappable chip. Labels are max 25 characters. postbackData (max 2048) comes back unchanged in message.received metadata as postbackPayload when tapped; defaults to the label. Any string works, JSON included: values outside A-Z a-z 0-9 - _ . are encoded on the wire and decoded for you.
            - object
              - …
            - object
              - …
            - object
              - …
            - object — Needs latitude + longitude, or a query.
              - …
            - object
              - …
            - object
              - …
      - `cardWidth` 'SMALL' | 'MEDIUM'
      - `suggestions` RcsSuggestion[]
        - union — A tappable chip. Labels are max 25 characters. postbackData (max 2048) comes back unchanged in message.received metadata as postbackPayload when tapped; defaults to the label. Any string works, JSON included: values outside A-Z a-z 0-9 - _ . are encoded on the wire and decoded for you.
          - object
            - `type` 'reply', required
            - `text` string, required
            - `postbackData` string
          - object
            - `type` 'dial', required
            - `text` string, required
            - `phoneNumber` string, required — E.164
            - `postbackData` string
          - object
            - `type` 'openUrl', required
            - `text` string, required
            - `url` string, uri, required
            - `application` 'BROWSER' | 'WEBVIEW'
            - `webviewViewMode` 'FULL' | 'HALF' | 'TALL'
            - `postbackData` string
          - object — Needs latitude + longitude, or a query.
            - `type` 'viewLocation', required
            - `text` string, required
            - `latitude` number
            - `longitude` number
            - `query` string
            - `label` string
            - `postbackData` string
          - object
            - `type` 'shareLocation', required
            - `text` string, required
            - `postbackData` string
          - object
            - `type` 'calendarEvent', required
            - `text` string, required
            - `startTime` string, date-time, required
            - `endTime` string, date-time, required
            - `title` string, required
            - `description` string
            - `postbackData` string
  - `fallbackText` string
  - `ttlSeconds` integer — Seconds before an undelivered message expires.

## Response `200`

Message accepted.

- object
  - `id` string — Message ID
  - `conversationId` string
  - `status` 'sent'

## Other responses

- `400` — Invalid request
- `401` — Missing or invalid API key. `code` is `missing_credentials` when no Authorization header was sent and `invalid_credentials` when the key is unknown, revoked or expired.
- `403` — The plan does not include the inbox, the recipient is not an accepted test phone before launch, or usage billing is not enabled
- `404` — Agent not found
- `409` — The agent cannot send yet, the recipient opted out (replied STOP), or the Idempotency-Key is still in flight
- `422` — Idempotency-Key reused with a different request
- `502` — Carrier-side send failed

## Changes

- **2026-10-02** `d556591af3f6` — 8 info
  - added the optional property `code` to the response with the `401` status
  - added the optional property `details` to the response with the `401` status
  - added the optional property `docUrl` to the response with the `400` status
  - added the optional property `docUrl` to the response with the `401` status
  - …4 more
- **2026-09-30** `16a7b9d5373e` — 1 info
  - removed the `platform` enum value from the `details/budgetScope` response property for the response status `400`
- **2026-09-29** `698a0d89ab62` — 1 info
  - endpoint added

[Change history](https://skmtc.dev/zernio/apis/zernio-api/changes/v1/rcs/messages/post.md)

---

[API](https://skmtc.dev/zernio/apis/zernio-api.md) · [All operations](https://skmtc.dev/zernio/apis/zernio-api/llms.txt) · [OpenAPI document](https://skmtc.dev/zernio/apis/zernio-api/revisions/f8dd1581bb14?raw)
