> This page is for version v2 (default).
> 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.

# List Conversation Messages

POST https://api.pinnacle.sh/conversations/{id}/messages

Retrieve a paginated and filtered list of messages for a specific conversation.

Reference: https://docs.pinnacle.sh/api-reference/conversations/list-messages

## Authentication

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

## Request

### Path parameters

- `id` (string, required) — Unique identifier of the conversation. This identifier is a string that always begins with the prefix `conv_`, for example: `conv_1234567890`.

### Query parameters

- `pageIndex` (integer, optional, default: 0) — Zero-based index for pagination.
- `pageSize` (integer, optional, default: 10) — Number of messages to return per page.
- `sortOrder` (enum, optional, default: desc) — Sort order for messages.&#x20; * `asc`: Oldest messages first * `desc`: Newest messages first (default)
  - Allowed values: `asc`, `desc`
- `direction` (enum, optional) — Filter messages by direction.&#x20; * `INBOUND`: Messages received from contacts * `OUTBOUND`: Messages sent to contacts
  - Allowed values: `INBOUND`, `OUTBOUND`
- `status` (enum, optional) — Filter messages by delivery status.
  - Allowed values: `PENDING`, `SENT`, `SEND_FAILED`, `DELIVERED`, `DELIVERY_FAILED`, `FALLBACK_SENT`, `RECEIVED`, `READ`
- `type` (enum, optional) — Filter messages by protocol type.
  - Allowed values: `SMS`, `MMS`, `RCS`
- `dateFrom` (string, optional) — Filter messages sent on or after this date (ISO 8601 format).
- `dateTo` (string, optional) — Filter messages sent on or before this date (ISO 8601 format).

## Response

### 200

Returns a paginated list of messages in the conversation.

- `messages` (list of MessageWithReactions, required) — Array of messages in the conversation.
- `hasMore` (boolean, required) — Indicates if more messages are available beyond the current page.
- `count` (integer, required) — Total number of messages in the conversation.

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

### 404 Not Found Error

Conversation not found

- `error` (string, optional)

### 500 Internal Server Error

An unexpected error occurred on Pinnacle's servers while processing your request.&#x20; If this error persists, please contact support with the request details.

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

## Types

### MessageWithReactions

Message with additional conversation-specific fields including direction and reactions.

- `content` (MessageContentType, required) — Content type of the message.
- `cost` (double, required, nullable) — Total cost charged for sending the message.&#x20; Null means the message incurred no cost or has not been charged yet.
- `deliveredAt` (string, required, nullable) — Timestamp indicating when the message was successfully delivered to the recipient.&#x20; Null indicates the message has not yet been delivered.
- `error` (string, required, nullable) — Detailed explanation of any errors that occurred while delivering the message.&#x20; Null indicates no errors.
- `id` (string, required) — Unique identifier of the message. This identifier is a string that always begins with the prefix `msg_`, for example: `msg_1234567890`.
- `method` (enum, required) — Method used to send the message.
  - Allowed values: `API`, `SDK`, `OTHER`
- `numSegments` (integer, required) — Number of segments the message was split into for delivery.
- `receiver` (string, required) — Phone number that received the message in E.164 format.
- `sender` (string, required) — Phone number or agent that sent the message.
- `sentAt` (string, required, nullable) — Timestamp indicating when the message was submitted for delivery.&#x20; Null indicates the message is still in the queue.
- `status` (enum, required) — Current status of the message.
  - Allowed values: `QUEUED`, `PENDING`, `SENT`, `SEND_FAILED`, `DELIVERED`, `DELIVERY_FAILED`, `RECEIVED`, `READ`, `FALLBACK_SENT`
- `type` (enum, required) — Delivery protocol used for sending this message.
  - Allowed values: `SMS`, `MMS`, `RCS`
- `direction` (enum, required) — Direction of the message flow.
  - Allowed values: `INBOUND`, `OUTBOUND`
- `reactions` (list of string, required) — Array of unicode emoji reactions attached to this message.&#x20; Empty array indicates no reactions have been added.

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

### MessageContentType

Content type of the message.

- SMS Message: SMSContent
- MMS Message: MMSContent
- RCS Message: RCSContent
- Button Clicked: ButtonClicked

### SMSContent

SMS message containing plain text only.

- `text` (string, required) — Message content.

### MMSContent

Message with text and/or media files from a phone number.

- `mediaUrls` (list of string, required) — URLs of media files in this message.&#x20; See [supported media types](https://app.pinnacle.sh/supported-file-types?type=MMS).
- `text` (string, optional) — Text content that accompanies the media files.

### RCSContent

Message with richer content (longer text, media files, cards, and buttons) from interacting with an RCS agent.

- Rich Text: RcsTextContent
- Rich Media: RcsMediaContent
- Rich Cards: RcsCardsContent

### ButtonClicked

- Button Clicked Data: ButtonClickedData
- Location Shared: LocationShareAction

### RcsTextContent

Message containing longer text content with optional quick reply buttons.

- `text` (string, required) — Text content of the RCS message.
- `quickReplies` (list of RichButton, optional) — List of interactive quick reply buttons in the message.&#x20; **Limit:** 10 max

### RcsMediaContent

Message containing a media file and/or text with optional quick reply buttons.&#x20; See (supported file types)\[[https://app.pinnacle.sh/supported-file-types?type=RCS-MEDIA](https://app.pinnacle.sh/supported-file-types?type=RCS-MEDIA)].

- `media` (RcsMediaDetailsContent, required) — Metadata about the media file in the message.
- `quickReplies` (list of RichButton, optional) — List of interactive quick reply buttons in the message.&#x20; **Limit:** 10 max

### RcsCardsContent

Message containing cards, each with its own title, subtitle, and/or buttons. Quick replies can also be added.&#x20; See (supported file types)\[[https://app.pinnacle.sh/supported-file-types?type=RCS-CARD](https://app.pinnacle.sh/supported-file-types?type=RCS-CARD)].

- `cards` (list of RcsCardsContentCardsItems, required) — Collection of cards attached to the message.&#x20; **Limit:** 1 to 10
- `quickReplies` (list of RichButton, optional) — List of interactive quick reply buttons in the message.&#x20; **Limit:** 10 max

### ButtonClickedData

Unified data structure for button click events.

- `button` (ButtonClickedDataButton, required) — Information about the button that was clicked.
- `messageId` (string, required, nullable) — ID of the message this button was sent in, or null if not available. To get the message details, use the [GET /messages/\{id}](/api-reference/messages/get) endpoint.

### LocationShareAction

- `data` (LocationShareActionData, required) — Location data shared by the user.

### RichButton

- `type`: `openUrl` (openUrl)
  - `payload` (string, required) — The URL to open when the button is tapped. Must be a valid HTTP or HTTPS URL.
  - `title` (string, required) — Display text for the button.
  - `metadata` (string, optional) — Optional additional data to attach to this button.
  - `webviewMode` (enum, optional) — Controls how the URL is displayed when the button is tapped. **Default behavior:** If not specified, the URL opens in the device's default browser. If you're sending deeplinks, you should use this mode as it will open the deeplink in the native app if it is installed. **Available modes in order of size:** - `HALF` — Half-screen webview overlay - `TALL` — Tall webview overlay - `FULL` — Full-screen webview
    - Allowed values: `HALF`, `TALL`, `FULL`
- `type`: `call` (call)
  - `payload` (string, required) — Phone number to call in E.164 format
  - `title` (string, required) — Display text for the button.
  - `metadata` (string, optional) — Optional additional data to attach to this button.
- `type`: `trigger` (trigger)
  - `payload` (string, required) — Custom data sent to your webhook when the button is tapped. Use this to identify the user's choice.
  - `title` (string, required) — Display text for the button.
  - `metadata` (string, optional) — Optional additional data to attach to this button.
- `type`: `requestUserLocation` (requestUserLocation)
  - `title` (string, required) — Display text for the button.
  - `metadata` (string, optional) — Optional additional data to attach to this button.
- `type`: `scheduleEvent` (scheduleEvent)
  - `eventEndTime` (string, required) — End time in ISO 8601 format.
  - `eventStartTime` (string, required) — Starting time in ISO 8601 format.
  - `eventTitle` (string, required) — Title of the event.
  - `title` (string, required) — Display text for the button.
  - `eventDescription` (string, optional) — Detailed description for the calendar event.
  - `metadata` (string, optional) — Optional additional data to attach to this button.
- `type`: `sendLocation` (sendLocation)
  - `latLong` (RichButtonDiscriminatorMappingSendLocationLatLong, required) — Geographic coordinates of the location to share.
  - `title` (string, required) — Display text for the button.
  - `metadata` (string, optional) — Optional additional data to attach to this button.
  - `name` (string, optional) — Optional name or label for the location that will be displayed in the map app (e.g., "Central Park", "Home Office"). If not provided, the button title will be used as the location name.

### RcsMediaDetailsContent

Metadata about the media file in the message.

- `mimeType` (string, required) — Detected MIME type of the media file.
- `url` (string, required) — Direct URL to the media file.
- `fullPath` (string, optional) — Path to the file in Pinnacle's storage.

### RcsCardsContentCardsItems

Individual card containing title, optional media, and action buttons.

- `title` (string, required) — Title displayed on the card.
- `buttons` (list of RichButton, optional) — While buttons resemble quick replies, they remain on screen after being clicked and are card-specific.&#x20; **Limit:** 4 max
- `media` (RcsMediaDetailsContent, optional) — Metadata about the media file in the message.
- `subtitle` (string, optional) — Secondary text displayed below the title for additional context.

### ButtonClickedDataButton

Information about the button that was clicked.

- `raw` (ButtonClickedDataButtonRaw, required) — Raw button data. Contains the entire button that was clicked by the user. In rare cases where we cannot determine the exact button, this will return only the button title.
- `clicks` (integer, required) — Number of times the button has been clicked.
- `type` (enum, optional, nullable) — Type of button clicked. - `CARD` for card buttons, - `QUICK_REPLY` for quick replies. - `null` if we cannot determine the button type. This is a rare edge case and is mainly here for backward compatibility.
  - Allowed values: `CARD`, `QUICK_REPLY`
- `payload` (string, optional, nullable) — Extracted payload from the button's `payload` field, if provided. Provides quick access to any payload that was attached to the button.
- `metadata` (string, optional, nullable) — Additional metadata attached to the button's `metadata` field, if provided.

### LocationShareActionData

Location data shared by the user.

- `address` (string, required) — Address corresponding to the shared location.
- `latitude` (double, required) — Latitude of the shared location.
- `longitude` (double, required) — Longitude of the shared location.
- `text` (string, optional) — Text message sent with the location.

### RichButtonDiscriminatorMappingSendLocationLatLong

Geographic coordinates of the location to share.

- `lat` (double, required) — Latitude coordinate in decimal degrees.
- `lng` (double, required) — Longitude coordinate in decimal degrees.

### ButtonClickedDataButtonRaw

Raw button data. Contains the entire button that was clicked by the user. In rare cases where we cannot determine the exact button, this will return only the button title.

- RichButton: RichButton
- string

## Examples

**Response**

```json
{
  "messages": [
    {
      "content": {
        "text": "Hello, how can I help you today?"
      },
      "cost": 0.0075,
      "deliveredAt": "2024-09-11T00:05:30.123Z",
      "error": null,
      "id": "msg_1234567890",
      "method": "API",
      "numSegments": 1,
      "receiver": "+16509231662",
      "sender": "+18445551234",
      "sentAt": "2024-09-11T00:05:29.434Z",
      "status": "DELIVERED",
      "type": "SMS",
      "direction": "OUTBOUND",
      "reactions": []
    },
    {
      "content": {
        "text": "I need help with my order"
      },
      "cost": null,
      "deliveredAt": "2024-09-11T00:10:16.123Z",
      "error": null,
      "id": "msg_0987654321",
      "method": "API",
      "numSegments": 1,
      "receiver": "+18445551234",
      "sender": "+16509231662",
      "sentAt": "2024-09-11T00:10:15.234Z",
      "status": "DELIVERED",
      "type": "SMS",
      "direction": "INBOUND",
      "reactions": [
        "👍"
      ]
    }
  ],
  "hasMore": true,
  "count": 42
}
```

**SDK Code**

```python Conversation Messages
import requests

url = "https://api.pinnacle.sh/conversations/id/messages"

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

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

print(response.json())
```

```javascript Conversation Messages
const url = 'https://api.pinnacle.sh/conversations/id/messages';
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 Conversation Messages
package main

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

func main() {

	url := "https://api.pinnacle.sh/conversations/id/messages"

	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 Conversation Messages
require 'uri'
require 'net/http'

url = URI("https://api.pinnacle.sh/conversations/id/messages")

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 Conversation Messages
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

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

```php Conversation Messages
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

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

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

```csharp Conversation Messages
using RestSharp;

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

```swift Conversation Messages
import Foundation

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

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