> This page is for version v1.
> For other versions, use one of these documentation indexes:
> - v2 (default): https://docs.pinnacle.sh/v-2/llms.txt
> - v1: https://docs.pinnacle.sh/v1/llms.txt

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.pinnacle.sh/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.pinnacle.sh/_mcp/server.

# RCS Message

POST https://www.trypinnacle.dev/api/send/rcs
Content-Type: application/json

Send an interactive RCS message with text, media, or cards. Each message can only contain either text, media, or card(s).

Quick replies can also be added to the message.

Reference: https://docs.pinnacle.sh/v1/api-reference/send-a-message/rcs

## Authentication

- `PINNACLE-API-Key` header (required) — Pinnacle API Key

## Request

### Body (application/json)

This endpoint expects a RCS.

- `from` (string, required) — The id of the RCS agent sending the message. Use 'test' if you want to send from the Pinnacle test agent. The test agent can only send to whitelisted test numbers. See https://dashboard.trypinnacle.app/settings/test-numbers to whitelist a number.
- `to` (string, required) — The recipient's RCS-enabled phone number in E.164 format (e.g., +12345678901).
- `text` (string, optional) — Text content of the message. Make sure you have either 'text', 'mediaUrl', or 'cards'. An error will be thrown if multiple (i.e. both 'text' and 'mediaUrl') is provided.
- `mediaUrl` (string, optional) — Media URL to be included in the message. Make sure you have either 'text', 'mediaUrl', or 'cards'. An error will be thrown if multiple (i.e. both 'text' and 'mediaUrl') is provided.
- `cards` (list of Card, optional) — List of rich cards. Maximum of 10 cards. Make sure you have either 'text', 'mediaUrl', or 'cards'. An error will be thrown if multiple (i.e. both 'text' and 'mediaUrl') is provided.
- `quickReplies` (list of Action, optional) — Optional list of quick reply actions (max 10).
- `fallback` (RcsFallback, optional)
- `statusCallback` (string, optional) — Optional URL to receive a POST request when the message status changes. Read more about status callbacks [here](/v1/receive-msg-statuses).

## Response

### 200

RCS/Fallback message sent successfully

- `messageId` (string, required) — The unique ID of the sent message.
- `message` (string, required) — A message indicating the status of the sent message.

## Errors

### 400 Bad Request Error

Invalid input parameters

- `errors` (list of string, optional)

### 401 Unauthorized Error

Unauthorized access due to invalid or missing API key

- `errors` (list of string, optional)

### 402 Payment Required Error

Insufficient balance to send RCS

- `errors` (list of string, optional)

### 403 Forbidden Error

Unauthorized use of an agent not owned by the user

- `errors` (list of string, optional)

### 500 Internal Server Error

Internal server error

- `errors` (list of string, optional)

## Types

### Card

- `title` (string, required) — The title of the card.
- `subtitle` (string, optional) — Optional subtitle for the card.
- `mediaUrl` (string, optional) — Optional media URL displayed with the card.
- `buttons` (list of Action, optional) — Optional list of buttons on the card (max 4).

### Action

- `title` (string, optional) — Title of the action (must be less than 25 characters).
- `type` (enum, optional) — Type of action for the button. 'openUrl' opens a URL, 'call' dials a phone number, 'trigger' sends the predefined payload to the webhook when pressed, 'requestUserLocation' requests the user's location, 'scheduleEvent' creates a calendar event, 'sendLocation' sends a location.
  - Allowed values: `openUrl`, `call`, `trigger`, `requestUserLocation`, `scheduleEvent`, `sendLocation`
- `payload` (string, optional) — Optional payload associated with the action. This payload encodes the respective fields for the action type and is required. For 'openUrl', the payload is the URL to open. For 'call', the payload is the phone number to dial. For 'trigger', the payload is the predefined payload to send to the webhook.
- `metadata` (string, optional) — Optional metadata. Only used for type 'trigger' ignored for other action types. When the user presses the action, the metadata is sent to the webhook alongside the payload.
- `eventStartTime` (string, optional) — Start time for events in ISO 8601 format. For example, '2022-01-01T12:00:00Z'. Required for 'scheduleEvent'.
- `eventEndTime` (string, optional) — End time for events in ISO 8601 format. For example, '2022-01-01T12:00:00Z'. Required for 'scheduleEvent'.
- `eventTitle` (string, optional) — Event title. Required for 'scheduleEvent'.
- `eventDescription` (string, optional) — Optional event description.
- `latLong` (ActionLatLong, optional) — Latitude and longitude coordinates. Required for 'sendLocation'.

### RcsFallback

- `from` (string, optional) — The sender's phone number in E.164 format. Must be owned by the user.
- `text` (string, optional) — The fallback message content (max 1600 characters). One of 'text' or 'mediaUrls' must be provided.
- `mediaUrls` (list of string, optional) — The URLs of media to include. One of 'text' or 'mediaUrls' must be provided. `jpeg`, `jpg`, `gif`, and `png` file types are fully supported and have a size limit of 5 MB. 500 KB limit for other types. Up to 10 media URLs can be included.

### ActionLatLong

Latitude and longitude coordinates. Required for 'sendLocation'.

- `lat` (double, optional) — Latitude value.
- `lng` (double, optional) — Longitude value.

## Examples

### RCS message sent

**Request**

```json
{
  "from": "string",
  "to": "string"
}
```

**Response**

```json
{
  "messageId": "1",
  "message": "RCS message sent successfully"
}
```

**SDK Code**

```python RCS message sent
import requests

url = "https://www.trypinnacle.dev/api/send/rcs"

payload = {
    "from": "string",
    "to": "string"
}
headers = {
    "PINNACLE-API-Key": "<apiKey>",
    "Content-Type": "application/json"
}

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

print(response.json())
```

```javascript RCS message sent
const url = 'https://www.trypinnacle.dev/api/send/rcs';
const options = {
  method: 'POST',
  headers: {'PINNACLE-API-Key': '<apiKey>', 'Content-Type': 'application/json'},
  body: '{"from":"string","to":"string"}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go RCS message sent
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://www.trypinnacle.dev/api/send/rcs"

	payload := strings.NewReader("{\n  \"from\": \"string\",\n  \"to\": \"string\"\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("PINNACLE-API-Key", "<apiKey>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby RCS message sent
require 'uri'
require 'net/http'

url = URI("https://www.trypinnacle.dev/api/send/rcs")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["PINNACLE-API-Key"] = '<apiKey>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"from\": \"string\",\n  \"to\": \"string\"\n}"

response = http.request(request)
puts response.read_body
```

```java RCS message sent
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://www.trypinnacle.dev/api/send/rcs")
  .header("PINNACLE-API-Key", "<apiKey>")
  .header("Content-Type", "application/json")
  .body("{\n  \"from\": \"string\",\n  \"to\": \"string\"\n}")
  .asString();
```

```php RCS message sent
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://www.trypinnacle.dev/api/send/rcs', [
  'body' => '{
  "from": "string",
  "to": "string"
}',
  'headers' => [
    'Content-Type' => 'application/json',
    'PINNACLE-API-Key' => '<apiKey>',
  ],
]);

echo $response->getBody();
```

```csharp RCS message sent
using RestSharp;

var client = new RestClient("https://www.trypinnacle.dev/api/send/rcs");
var request = new RestRequest(Method.POST);
request.AddHeader("PINNACLE-API-Key", "<apiKey>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"from\": \"string\",\n  \"to\": \"string\"\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift RCS message sent
import Foundation

let headers = [
  "PINNACLE-API-Key": "<apiKey>",
  "Content-Type": "application/json"
]
let parameters = [
  "from": "string",
  "to": "string"
] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://www.trypinnacle.dev/api/send/rcs")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

### Fallback message sent

**Request**

```json
{
  "from": "string",
  "to": "string"
}
```

**Response**

```json
{
  "messageId": "1",
  "message": "Fallback message sent successfully"
}
```

**SDK Code**

```python Fallback message sent
import requests

url = "https://www.trypinnacle.dev/api/send/rcs"

payload = {
    "from": "string",
    "to": "string"
}
headers = {
    "PINNACLE-API-Key": "<apiKey>",
    "Content-Type": "application/json"
}

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

print(response.json())
```

```javascript Fallback message sent
const url = 'https://www.trypinnacle.dev/api/send/rcs';
const options = {
  method: 'POST',
  headers: {'PINNACLE-API-Key': '<apiKey>', 'Content-Type': 'application/json'},
  body: '{"from":"string","to":"string"}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go Fallback message sent
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://www.trypinnacle.dev/api/send/rcs"

	payload := strings.NewReader("{\n  \"from\": \"string\",\n  \"to\": \"string\"\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("PINNACLE-API-Key", "<apiKey>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby Fallback message sent
require 'uri'
require 'net/http'

url = URI("https://www.trypinnacle.dev/api/send/rcs")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["PINNACLE-API-Key"] = '<apiKey>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"from\": \"string\",\n  \"to\": \"string\"\n}"

response = http.request(request)
puts response.read_body
```

```java Fallback message sent
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://www.trypinnacle.dev/api/send/rcs")
  .header("PINNACLE-API-Key", "<apiKey>")
  .header("Content-Type", "application/json")
  .body("{\n  \"from\": \"string\",\n  \"to\": \"string\"\n}")
  .asString();
```

```php Fallback message sent
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://www.trypinnacle.dev/api/send/rcs', [
  'body' => '{
  "from": "string",
  "to": "string"
}',
  'headers' => [
    'Content-Type' => 'application/json',
    'PINNACLE-API-Key' => '<apiKey>',
  ],
]);

echo $response->getBody();
```

```csharp Fallback message sent
using RestSharp;

var client = new RestClient("https://www.trypinnacle.dev/api/send/rcs");
var request = new RestRequest(Method.POST);
request.AddHeader("PINNACLE-API-Key", "<apiKey>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"from\": \"string\",\n  \"to\": \"string\"\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift Fallback message sent
import Foundation

let headers = [
  "PINNACLE-API-Key": "<apiKey>",
  "Content-Type": "application/json"
]
let parameters = [
  "from": "string",
  "to": "string"
] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://www.trypinnacle.dev/api/send/rcs")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```