> 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.

# Create Test Agent

POST https://api.pinnacle.sh/rcs/test/agents
Content-Type: application/json

Create a new RCS test agent for development and testing.

## Overview

Test agents let you build and test full RCS functionality — rich cards, carousels, buttons,
quick replies, and media messages — without going through the full carrier review process.
Messages from test agents can only be sent to [whitelisted phone numbers](/api-reference/rcs-agents/test/whitelist-number).

## Limits

* **Maximum 5 test agents per account.**

## Image Requirements

| Image | Format    | Max Size |
| ----- | --------- | -------- |
| Logo  | JPEG, PNG | 50 KB    |
| Hero  | JPEG, PNG | 200 KB   |

## After Creation

Once your test agent is created, you'll need to:

1. **Whitelist test phone numbers** using [`POST /rcs/test/agents/{agentId}/whitelist`](/api-reference/rcs-agents/test/whitelist-number).
2. **Accept the tester invite** on each whitelisted device.
3. **Send messages** using [`POST /messages/send/rcs`](/api-reference/messages/send-rcs) with the returned agent ID as the `from` field.

> **2-Minute Cooldown**
>
> After creating a test agent, there is a mandatory 2-minute cooldown before you can whitelist phone numbers.
> This is a requirement imposed by Google's RBM platform.

Reference: https://docs.pinnacle.sh/api-reference/rcs-agents/test/create-agent

## Authentication

- `PINNACLE-API-KEY` header (required) — API Key authentication via header

## Request

### Body (application/json)

This endpoint expects a CreateTestAgentRequest.

- `displayName` (string, required) — Display name of the agent shown to users in RCS conversations. Must be between 1 and 40 characters.
- `description` (string, required) — Short description of what the agent does. Shown to users in the agent's profile. Must be between 1 and 100 characters.
- `logoUrl` (string, required) — URL to the agent's logo image. Displayed as the agent's avatar in conversations. **Requirements:** - Format: JPEG or PNG - Max file size: 50 KB - Recommended: Square aspect ratio
- `heroUrl` (string, required) — URL to the agent's hero banner image. Displayed at the top of the agent's profile. **Requirements:** - Format: JPEG or PNG - Max file size: 200 KB - Recommended: Landscape aspect ratio
- `phoneNumbers` (list of AgentPhoneEntry, required) — Contact phone numbers displayed on the agent's profile. At least 1 and up to 3 entries.
- `emails` (list of AgentEmailEntry, required) — Contact email addresses displayed on the agent's profile. At least 1 and up to 3 entries.
- `websites` (list of AgentWebsiteEntry, required) — Website links displayed on the agent's profile. At least 1 and up to 3 entries.
- `privacyUrl` (string, required) — URL to the agent's privacy policy.
- `termsUrl` (string, required) — URL to the agent's terms and conditions.
- `color` (string, required) — The agent's brand color as a hex color code. Used for UI accents in the RCS conversation. Must have sufficient contrast with white for accessibility.
- `isConversational` (boolean, required) — Whether the agent supports two-way conversations. Set to `true` if the agent will respond to user messages. Set to `false` for send-only agents (e.g., notifications).
- `agentUseCase` (enum, optional) — The primary use case for the RCS agent. This helps carriers understand the purpose of the agent during review. - `TRANSACTIONAL` — Order confirmations, shipping updates, appointment reminders, and similar transactional notifications. - `PROMOTIONAL` — Marketing messages, offers, discounts, and promotional content. - `OTP` — One-time passwords and verification codes. - `MULTI_USE` — A combination of transactional, promotional, and/or OTP messaging.
  - Allowed values: `TRANSACTIONAL`, `PROMOTIONAL`, `OTP`, `MULTI_USE`

## Response

### 200

The test agent was created successfully. Use the returned `id` as the `from` field when sending RCS messages, and when whitelisting phone numbers.

- `id` (string, required) — The unique agent ID. Use this ID when sending messages, whitelisting numbers, and performing other agent operations. Always prefixed with `agent_`.
- `type` (enum, required) — The type of the agent. Test agents always have type `TEST`.
  - Allowed values: `TEST`
- `serviceId` (string, required) — The RCS service ID assigned to this agent by the carrier network. Used internally for routing messages. You can use this to construct RCS deep links manually.
- `details` (RcsAgentDetails, required) — The configuration details of an RCS agent, as returned by the GET endpoint.

## Errors

### 400 Bad Request Error

Validation failed. The payload has missing required fields and/or invalid types.&#x20; See [https://zod.dev/error-formatting](https://zod.dev/error-formatting) for more information.

- `description` (string, required) — Human-readable summary of validation failures.
- `errors` (ZodErrorErrors, required) — Structured dictionary of issues containing two main sections: - `errors`: Array of global validation errors not tied to specific fields - `properties`: Object mapping field names to their specific validation errors, where each field contains an `errors` array

### 401 Unauthorized Error

The request lacks valid authentication credentials or the provided credentials are invalid.&#x20; Ensure you're including a valid API key in the request headers and that your account has the necessary permissions to access this endpoint.

- `error` (string, required) — Human-readable description of the error that occurred, corresponding to the HTTP status code.

### 403 Forbidden Error

Your subscription does not include access to this feature.&#x20; This occurs when attempting to use functionality that requires a higher subscription tier. Please upgrade your subscription to access this feature.

- `error` (string, required) — Human-readable description of the error that occurred, corresponding to the HTTP status code.

### 500 Internal Server Error

An internal error occurred. Common causes: - **Agent limit reached:** You can create a maximum of 5 test agents per account. - **Invalid image:** Logo exceeds 50 KB, hero exceeds 200 KB, or image is not JPEG/PNG. - **Invalid color:** The hex color does not have sufficient contrast with white.

- `error` (string, required) — Human-readable description of the error that occurred, corresponding to the HTTP status code.

## Types

### AgentPhoneEntry

A phone number contact entry for the RCS agent's contact information.

- `number` (string, required) — Phone number in E.164 format (e.g., `+14155550123`).
- `label` (string, required) — Display label for the phone number (e.g., "Support", "Sales").

### AgentEmailEntry

An email contact entry for the RCS agent's contact information.

- `address` (string, required) — A valid email address.
- `label` (string, required) — Display label for the email (e.g., "Support", "Sales").

### AgentWebsiteEntry

A website contact entry for the RCS agent's contact information.

- `url` (string, required) — A valid URL for the website.
- `label` (string, required) — Display label for the website (e.g., "Website", "Help Center").

### RcsAgentDetails

The configuration details of an RCS agent, as returned by the GET endpoint.

- `name` (string, optional) — Display name of the agent.
- `description` (string, optional) — Description of the agent.
- `iconUrl` (string, optional, nullable) — URL to the agent's logo image.
- `heroUrl` (string, optional, nullable) — URL to the agent's hero banner image.
- `color` (string, optional) — The agent's brand color hex code.
- `phones` (list of RcsAgentDetailsPhonesItems, optional) — Contact phone numbers for the agent.
- `emails` (list of RcsAgentDetailsEmailsItems, optional) — Contact email addresses for the agent.
- `websites` (list of RcsAgentDetailsWebsitesItems, optional) — Website links for the agent.
- `privacyUrl` (string, optional, nullable) — URL to the agent's privacy policy.
- `termsUrl` (string, optional, nullable) — URL to the agent's terms and conditions.
- `isConversational` (boolean, optional, nullable) — Whether the agent supports two-way conversations. `true` for agents that respond to user messages, `false` for send-only agents (e.g., notifications).
- `agentUseCase` (enum, optional, nullable) — The primary use case for the RCS agent. - `TRANSACTIONAL` — Order confirmations, shipping updates, appointment reminders. - `PROMOTIONAL` — Marketing messages, offers, discounts. - `OTP` — One-time passwords and verification codes. - `MULTI_USE` — A combination of transactional, promotional, and/or OTP messaging.
  - Allowed values: `TRANSACTIONAL`, `PROMOTIONAL`, `OTP`, `MULTI_USE`

### ZodErrorErrors

Structured dictionary of issues containing two main sections: - `errors`: Array of global validation errors not tied to specific fields - `properties`: Object mapping field names to their specific validation errors, where each field contains an `errors` array

### RcsAgentDetailsPhonesItems

- `phone` (string, optional) — Phone number in E.164 format.
- `label` (string, optional) — Display label for the phone number.

### RcsAgentDetailsEmailsItems

- `email` (string, optional) — Email address.
- `label` (string, optional) — Display label for the email.

### RcsAgentDetailsWebsitesItems

- `url` (string, optional) — Website URL.
- `label` (string, optional) — Display label for the website.

## Examples

### Created Test Agent

**Response**

```json
{
  "id": "agent_abc123def456",
  "type": "TEST",
  "serviceId": "acme-support_agent",
  "details": {
    "name": "Acme Support",
    "description": "Get help with your Acme orders and account",
    "iconUrl": "https://example.com/logo.png",
    "heroUrl": "https://example.com/hero.png",
    "color": "#FF6B00",
    "phones": [
      {
        "phone": "+14155550123",
        "label": "Support"
      }
    ],
    "emails": [
      {
        "email": "support@example.com",
        "label": "Support"
      }
    ],
    "websites": [
      {
        "url": "https://example.com",
        "label": "Website"
      }
    ],
    "privacyUrl": "https://example.com/privacy",
    "termsUrl": "https://example.com/terms",
    "isConversational": true,
    "agentUseCase": "MULTI_USE"
  }
}
```

**SDK Code**

```python Created Test Agent
import requests

url = "https://api.pinnacle.sh/rcs/test/agents"

headers = {"PINNACLE-API-KEY": "<apiKey>"}

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

print(response.json())
```

```javascript Created Test Agent
const url = 'https://api.pinnacle.sh/rcs/test/agents';
const options = {method: 'POST', headers: {'PINNACLE-API-KEY': '<apiKey>'}};

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

```go Created Test Agent
package main

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

func main() {

	url := "https://api.pinnacle.sh/rcs/test/agents"

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

	req.Header.Add("PINNACLE-API-KEY", "<apiKey>")

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

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

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

}
```

```ruby Created Test Agent
require 'uri'
require 'net/http'

url = URI("https://api.pinnacle.sh/rcs/test/agents")

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

request = Net::HTTP::Post.new(url)
request["PINNACLE-API-KEY"] = '<apiKey>'

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

```java Created Test Agent
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.pinnacle.sh/rcs/test/agents")
  .header("PINNACLE-API-KEY", "<apiKey>")
  .asString();
```

```php Created Test Agent
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.pinnacle.sh/rcs/test/agents', [
  'headers' => [
    'PINNACLE-API-KEY' => '<apiKey>',
  ],
]);

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

```csharp Created Test Agent
using RestSharp;

var client = new RestClient("https://api.pinnacle.sh/rcs/test/agents");
var request = new RestRequest(Method.POST);
request.AddHeader("PINNACLE-API-KEY", "<apiKey>");
IRestResponse response = client.Execute(request);
```

```swift Created Test Agent
import Foundation

let headers = ["PINNACLE-API-KEY": "<apiKey>"]

let request = NSMutableURLRequest(url: NSURL(string: "https://api.pinnacle.sh/rcs/test/agents")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers

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()
```

### Create Test Agent

**Request**

```json
{
  "displayName": "Acme Support",
  "description": "Get help with your Acme orders and account",
  "logoUrl": "https://example.com/logo.png",
  "heroUrl": "https://example.com/hero.png",
  "phoneNumbers": [
    {
      "number": "+14155550123",
      "label": "Support"
    }
  ],
  "emails": [
    {
      "address": "support@example.com",
      "label": "Support"
    }
  ],
  "websites": [
    {
      "url": "https://example.com",
      "label": "Website"
    }
  ],
  "privacyUrl": "https://example.com/privacy",
  "termsUrl": "https://example.com/terms",
  "color": "#FF6B00",
  "isConversational": true,
  "agentUseCase": "MULTI_USE"
}
```

**Response**

```json
{
  "id": "agent_abc123def456",
  "type": "TEST",
  "serviceId": "acme-support_agent",
  "details": {
    "name": "Acme Support",
    "description": "Get help with your Acme orders and account",
    "iconUrl": "https://example.com/logo.png",
    "heroUrl": "https://example.com/hero.png",
    "color": "#FF6B00",
    "phones": [
      {
        "phone": "+14155550123",
        "label": "Support"
      }
    ],
    "emails": [
      {
        "email": "support@example.com",
        "label": "Support"
      }
    ],
    "websites": [
      {
        "url": "https://example.com",
        "label": "Website"
      }
    ],
    "privacyUrl": "https://example.com/privacy",
    "termsUrl": "https://example.com/terms",
    "isConversational": true,
    "agentUseCase": "MULTI_USE"
  }
}
```

**SDK Code**

```python Create Test Agent
import requests

url = "https://api.pinnacle.sh/rcs/test/agents"

payload = {
    "displayName": "Acme Support",
    "description": "Get help with your Acme orders and account",
    "logoUrl": "https://example.com/logo.png",
    "heroUrl": "https://example.com/hero.png",
    "phoneNumbers": [
        {
            "number": "+14155550123",
            "label": "Support"
        }
    ],
    "emails": [
        {
            "address": "support@example.com",
            "label": "Support"
        }
    ],
    "websites": [
        {
            "url": "https://example.com",
            "label": "Website"
        }
    ],
    "privacyUrl": "https://example.com/privacy",
    "termsUrl": "https://example.com/terms",
    "color": "#FF6B00",
    "isConversational": True,
    "agentUseCase": "MULTI_USE"
}
headers = {
    "PINNACLE-API-KEY": "<apiKey>",
    "Content-Type": "application/json"
}

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

print(response.json())
```

```javascript Create Test Agent
const url = 'https://api.pinnacle.sh/rcs/test/agents';
const options = {
  method: 'POST',
  headers: {'PINNACLE-API-KEY': '<apiKey>', 'Content-Type': 'application/json'},
  body: '{"displayName":"Acme Support","description":"Get help with your Acme orders and account","logoUrl":"https://example.com/logo.png","heroUrl":"https://example.com/hero.png","phoneNumbers":[{"number":"+14155550123","label":"Support"}],"emails":[{"address":"support@example.com","label":"Support"}],"websites":[{"url":"https://example.com","label":"Website"}],"privacyUrl":"https://example.com/privacy","termsUrl":"https://example.com/terms","color":"#FF6B00","isConversational":true,"agentUseCase":"MULTI_USE"}'
};

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

```go Create Test Agent
package main

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

func main() {

	url := "https://api.pinnacle.sh/rcs/test/agents"

	payload := strings.NewReader("{\n  \"displayName\": \"Acme Support\",\n  \"description\": \"Get help with your Acme orders and account\",\n  \"logoUrl\": \"https://example.com/logo.png\",\n  \"heroUrl\": \"https://example.com/hero.png\",\n  \"phoneNumbers\": [\n    {\n      \"number\": \"+14155550123\",\n      \"label\": \"Support\"\n    }\n  ],\n  \"emails\": [\n    {\n      \"address\": \"support@example.com\",\n      \"label\": \"Support\"\n    }\n  ],\n  \"websites\": [\n    {\n      \"url\": \"https://example.com\",\n      \"label\": \"Website\"\n    }\n  ],\n  \"privacyUrl\": \"https://example.com/privacy\",\n  \"termsUrl\": \"https://example.com/terms\",\n  \"color\": \"#FF6B00\",\n  \"isConversational\": true,\n  \"agentUseCase\": \"MULTI_USE\"\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 Create Test Agent
require 'uri'
require 'net/http'

url = URI("https://api.pinnacle.sh/rcs/test/agents")

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  \"displayName\": \"Acme Support\",\n  \"description\": \"Get help with your Acme orders and account\",\n  \"logoUrl\": \"https://example.com/logo.png\",\n  \"heroUrl\": \"https://example.com/hero.png\",\n  \"phoneNumbers\": [\n    {\n      \"number\": \"+14155550123\",\n      \"label\": \"Support\"\n    }\n  ],\n  \"emails\": [\n    {\n      \"address\": \"support@example.com\",\n      \"label\": \"Support\"\n    }\n  ],\n  \"websites\": [\n    {\n      \"url\": \"https://example.com\",\n      \"label\": \"Website\"\n    }\n  ],\n  \"privacyUrl\": \"https://example.com/privacy\",\n  \"termsUrl\": \"https://example.com/terms\",\n  \"color\": \"#FF6B00\",\n  \"isConversational\": true,\n  \"agentUseCase\": \"MULTI_USE\"\n}"

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

```java Create Test Agent
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.pinnacle.sh/rcs/test/agents")
  .header("PINNACLE-API-KEY", "<apiKey>")
  .header("Content-Type", "application/json")
  .body("{\n  \"displayName\": \"Acme Support\",\n  \"description\": \"Get help with your Acme orders and account\",\n  \"logoUrl\": \"https://example.com/logo.png\",\n  \"heroUrl\": \"https://example.com/hero.png\",\n  \"phoneNumbers\": [\n    {\n      \"number\": \"+14155550123\",\n      \"label\": \"Support\"\n    }\n  ],\n  \"emails\": [\n    {\n      \"address\": \"support@example.com\",\n      \"label\": \"Support\"\n    }\n  ],\n  \"websites\": [\n    {\n      \"url\": \"https://example.com\",\n      \"label\": \"Website\"\n    }\n  ],\n  \"privacyUrl\": \"https://example.com/privacy\",\n  \"termsUrl\": \"https://example.com/terms\",\n  \"color\": \"#FF6B00\",\n  \"isConversational\": true,\n  \"agentUseCase\": \"MULTI_USE\"\n}")
  .asString();
```

```php Create Test Agent
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.pinnacle.sh/rcs/test/agents', [
  'body' => '{
  "displayName": "Acme Support",
  "description": "Get help with your Acme orders and account",
  "logoUrl": "https://example.com/logo.png",
  "heroUrl": "https://example.com/hero.png",
  "phoneNumbers": [
    {
      "number": "+14155550123",
      "label": "Support"
    }
  ],
  "emails": [
    {
      "address": "support@example.com",
      "label": "Support"
    }
  ],
  "websites": [
    {
      "url": "https://example.com",
      "label": "Website"
    }
  ],
  "privacyUrl": "https://example.com/privacy",
  "termsUrl": "https://example.com/terms",
  "color": "#FF6B00",
  "isConversational": true,
  "agentUseCase": "MULTI_USE"
}',
  'headers' => [
    'Content-Type' => 'application/json',
    'PINNACLE-API-KEY' => '<apiKey>',
  ],
]);

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

```csharp Create Test Agent
using RestSharp;

var client = new RestClient("https://api.pinnacle.sh/rcs/test/agents");
var request = new RestRequest(Method.POST);
request.AddHeader("PINNACLE-API-KEY", "<apiKey>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"displayName\": \"Acme Support\",\n  \"description\": \"Get help with your Acme orders and account\",\n  \"logoUrl\": \"https://example.com/logo.png\",\n  \"heroUrl\": \"https://example.com/hero.png\",\n  \"phoneNumbers\": [\n    {\n      \"number\": \"+14155550123\",\n      \"label\": \"Support\"\n    }\n  ],\n  \"emails\": [\n    {\n      \"address\": \"support@example.com\",\n      \"label\": \"Support\"\n    }\n  ],\n  \"websites\": [\n    {\n      \"url\": \"https://example.com\",\n      \"label\": \"Website\"\n    }\n  ],\n  \"privacyUrl\": \"https://example.com/privacy\",\n  \"termsUrl\": \"https://example.com/terms\",\n  \"color\": \"#FF6B00\",\n  \"isConversational\": true,\n  \"agentUseCase\": \"MULTI_USE\"\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift Create Test Agent
import Foundation

let headers = [
  "PINNACLE-API-KEY": "<apiKey>",
  "Content-Type": "application/json"
]
let parameters = [
  "displayName": "Acme Support",
  "description": "Get help with your Acme orders and account",
  "logoUrl": "https://example.com/logo.png",
  "heroUrl": "https://example.com/hero.png",
  "phoneNumbers": [
    [
      "number": "+14155550123",
      "label": "Support"
    ]
  ],
  "emails": [
    [
      "address": "support@example.com",
      "label": "Support"
    ]
  ],
  "websites": [
    [
      "url": "https://example.com",
      "label": "Website"
    ]
  ],
  "privacyUrl": "https://example.com/privacy",
  "termsUrl": "https://example.com/terms",
  "color": "#FF6B00",
  "isConversational": true,
  "agentUseCase": "MULTI_USE"
] as [String : Any]

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

let request = NSMutableURLRequest(url: NSURL(string: "https://api.pinnacle.sh/rcs/test/agents")! 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()
```