---
title: "Send an agent LiveChat text or media reply as RCS"
description: "Used by the LiveChat composer to send an agent's text or single image/prepared video RCS-first. Twilio delivers RCS where the device supports it and otherwise falls back to SMS/MMS from the contact's own board number (FallbackFrom), so the conversation stays on one number. A contact not yet confirmed RCS-capable is only attempted when that board number resolves. Gated by RCS_MESSAGING + workspace_rcs_config. Returns sent:false (HTTP 200) with a fallback-safe outcome only when no RCS send was attempted or definitively rejected by the configuration allowlist. Invalid, raw or unverifiable media returns rejected and must never fall back. Media is workspace-owned public storage, at most 5,000,000 bytes including UTF-8 text; videos must be prepared MP4 files at most 600,000 bytes. MMS-only image formats and multiple attachments use the existing MMS path after validation. Requires an authenticated workspace agent (Bearer).\n"
---

> Documentation Index
> Fetch the complete documentation index at: https://developer.channelautomations.com/llms.txt
> Use this file to discover all available pages before exploring further.

Path: Channel Automation API › RCS

`POST /api/rcs/workspaces/{workspaceId}/agent-send`

Used by the LiveChat composer to send an agent's text or single image/prepared video RCS-first. Twilio delivers RCS where the device supports it and otherwise falls back to SMS/MMS from the contact's own board number (FallbackFrom), so the conversation stays on one number. A contact not yet confirmed RCS-capable is only attempted when that board number resolves. Gated by RCS_MESSAGING + workspace_rcs_config. Returns sent:false (HTTP 200) with a fallback-safe outcome only when no RCS send was attempted or definitively rejected by the configuration allowlist. Invalid, raw or unverifiable media returns rejected and must never fall back. Media is workspace-owned public storage, at most 5,000,000 bytes including UTF-8 text; videos must be prepared MP4 files at most 600,000 bytes. MMS-only image formats and multiple attachments use the existing MMS path after validation. Requires an authenticated workspace agent (Bearer).

## Authentication

- `BearerAuth`, http, header `Authorization`, format `JWT`

## Path parameters

- `workspaceId` (`post/api/rcs/workspaces/workspaceId/agent-send.path.workspaceId`; string, required)

## Request body

_Required._

- `contactId` (`post/api/rcs/workspaces/workspaceId/agent-send.contactId`; string, required)
- `body` (`post/api/rcs/workspaces/workspaceId/agent-send.body`; string, optional) — Reply text (max 1600 chars), optional when mediaUrls is present.
- `mediaUrls` (`post/api/rcs/workspaces/workspaceId/agent-send.mediaUrls`; array<string>, optional) — Public workspace-owned image or prepared MP4 URL. One attachment uses RCS.
- `mediaPaths` (`post/api/rcs/workspaces/workspaceId/agent-send.mediaPaths`; array<string>, optional) — Matching storage object paths, in the same order as mediaUrls.
- `userName` (`post/api/rcs/workspaces/workspaceId/agent-send.userName`; string, optional) — Agent display name stored on the message.
- `userAvatar` (`post/api/rcs/workspaces/workspaceId/agent-send.userAvatar`; string, optional) — Agent avatar URL stored on the message.

## Example request

```json
{
  "contactId": "string",
  "body": "string",
  "mediaUrls": [
    "string"
  ],
  "mediaPaths": [
    "string"
  ],
  "userName": "string",
  "userAvatar": "string"
}
```

## Code samples

### cURL

```bash
curl --request POST \
  --url 'https://api.channelautomation.com/api/rcs/workspaces/<workspaceId>/agent-send' \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '
{
  "contactId": "string",
  "body": "string",
  "mediaUrls": [
    "string"
  ],
  "mediaPaths": [
    "string"
  ],
  "userName": "string",
  "userAvatar": "string"
}
'
```

### TypeScript

```typescript
const url = 'https://api.channelautomation.com/api/rcs/workspaces/<workspaceId>/agent-send';
const options = {
  method: 'POST',
  headers: {'Content-Type': 'application/json', Authorization: 'Bearer <token>'},
  body: JSON.stringify({
    contactId: 'string',
    body: 'string',
    mediaUrls: ['string'],
    mediaPaths: ['string'],
    userName: 'string',
    userAvatar: 'string'
  })
};

fetch(url, options)
  .then(res => res.json())
  .then(json => console.log(json))
  .catch(err => console.error(err));
```

### Python

```python
import requests

url = "https://api.channelautomation.com/api/rcs/workspaces/<workspaceId>/agent-send"

payload = {
    "contactId": "string",
    "body": "string",
    "mediaUrls": ["string"],
    "mediaPaths": ["string"],
    "userName": "string",
    "userAvatar": "string"
}
headers = {
    "Content-Type": "application/json",
    "Authorization": "Bearer <token>"
}

response = requests.post(url, json=payload, headers=headers)

print(response.text)
```

## Responses

### 200

Always 200 on a well-formed request. `sent:true` with a messageSid when handed to Twilio RCS-first. Otherwise `sent:false` with an `outcome`: `not_attempted` or `rejected_fallback_ok` → the UI sends plain SMS; `rejected` → Twilio refused it (e.g. unsubscribed) and nothing may be re-sent; `unknown` → Twilio may have accepted it, so nothing may be re-sent.

### 400

Missing contactId, or no text and no media.

### 401

Authentication required

#### Example

```json
{
  "error": "Authentication required",
  "success": false
}
```

- `error` (`post/api/rcs/workspaces/workspaceId/agent-send.response.401.error`; string, optional)
  - example `"Authentication required"`
- `success` (`post/api/rcs/workspaces/workspaceId/agent-send.response.401.success`; boolean, optional)
  - example `false`

### 403

Membership in the path workspace is required.

### 503

Identity or workspace access verification is temporarily unavailable.


Source: https://developer.channelautomations.com/api/post-api-rcs-workspaces-workspace-id-agent-send/index.md
