# Get messages

Get the newest messages in your community, optionally from one channel or one trader, as plain text with the sender and channel.

- Endpoint: `GET https://api.returning.ai/v1/messages`
- Section: Community / Messaging
- Authentication: `Authorization: Bearer <API_KEY>` (Community API key)
- Permission: `getMessages` (Shown in the dashboard as "Get Messages")
- Retries: Read-only; exact retries are safe
- Guide: hand-written
- Verified: live, 2026-09-27
- Last updated: 26 Sep 2026
- Web page: https://docs.returning.ai/api-reference/messaging/get-messages

## When to use this

- You watch a channel from your own system and want the latest messages.
- You want to see what one trader has posted recently.
- You need a message ID so you can reply to it or react to it.

**Instead:** Use [List integration channels](https://docs.returning.ai/api-reference/channels/list-integration-channels.md) instead to find a channel ID first.

## Authentication

- Header: `Authorization: Bearer <API_KEY>`
- Permission: `getMessages`

Use a Community API key with `getMessages`, and keep it on your server. The key decides the community, so you only read that community's messages and never send a community ID.

## Behaviour

Messages come newest first. Without `channel_id` you get the newest messages from every channel in your community. Direct messages aren't included.

`data.messages.message` is plain text: formatting is removed and mentions read `@Display Name`. A message with a file reads `Attached File`, and a GIF reads `GIF Message`. There is no cursor or page parameter, so to catch up after a gap, read with a higher `count` and skip IDs you have already seen.

## Request

### Query parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `channel_id` | `string` | No | Only messages from this channel, from List integration channels. Omit it for messages from every channel. (Channel ID in your community) |
| `count` | `integer` | No | How many of the newest messages to return. (1-100, default 50) |
| `user_id` | `string` | No | Only messages posted by this trader, by platform user ID. Send this or `email`, not both. |
| `email` | `string` | No | Only messages posted by the trader with this email. Send this or `user_id`, not both. |

### Headers

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `Authorization` | `string` | Yes | Community API key with `getMessages`. (`Bearer <API_KEY>`) |

### Example request

```bash
curl --request GET \
  --url 'https://api.returning.ai/v1/messages?channel_id=66f000000000000000000a11&count=20' \
  --header 'Authorization: Bearer <API_KEY>'
```

## Response

A `200` returns up to `count` messages in `data.messages`. `data.total` counts the messages in this response only. A channel with no messages returns an empty list.

### Response fields

| Field | Type | Presence | Description |
| --- | --- | --- | --- |
| `status` | `string` | always | Result of the request. (`success`) |
| `message` | `string` | always | Human-readable summary. Do not branch on it. |
| `data` | `object` | always | The messages. |
| `data.total` | `integer` | always | Number of messages in this response, not the total in the channel. |
| `data.messages` | `object[]` | always | Up to `count` messages, newest first. |
| `data.messages.id` | `string` | always | The message ID. Use it as `messageId` to reply or react. |
| `data.messages.message` | `string` | always | The message as plain text. Attachments read `Attached File` and GIFs read `GIF Message`. |
| `data.messages.user` | `object` | always | Who posted the message. |
| `data.messages.user.user_id` | `string` | always | The sender's platform user ID, as a string. |
| `data.messages.user.email` | `string` | always | The sender's email. |
| `data.messages.channel` | `object` | always | Where the message was posted. |
| `data.messages.channel.channel_id` | `string` | always | The channel ID. |
| `data.messages.channel.name` | `string` | always | The channel's name. |
| `data.messages.timestamp` | `string` | always | When the message was posted. |

### Example response (200)

```json
{
  "status": "success",
  "message": "messages fetched successfully",
  "data": {
    "total": 1,
    "messages": [
      {
        "id": "66f000000000000000000a21",
        "message": "Is the gold webinar still on for Friday?",
        "user": {
          "user_id": "3247779",
          "email": "trader@example.com"
        },
        "channel": {
          "channel_id": "66f000000000000000000a11",
          "name": "general"
        },
        "timestamp": "2026-09-26T08:30:00.000Z"
      }
    ]
  }
}
```

## Errors

Validation errors put the reason in `detail`, and `detail.fields` names the bad parameter. Other errors carry only `message`, or `message` and `detail`. None has a machine-readable code, so branch on the HTTP status.

### Fix the request

| Status | Code | What to do |
| --- | --- | --- |
| 400 | - | A query value is invalid: `count` outside 1-100 or not a whole number, a malformed `channel_id`, both `user_id` and `email`, or a parameter this endpoint doesn't accept. `detail.fields` names it. A `detail` of `Channel not found` means `channel_id` isn't a channel in your community. Any other `detail` text is an unexpected failure; retry it once with backoff. |
| 401 | - | The key is missing (`Invalid token`), unknown (`Invalid API key`) or expired, or it lacks `getMessages` (`Your api key does not have permission to access this action`). Personal user API keys can't read messages. Add the permission in Settings > Integration > API Keys. |
| 403 | - | The trader in `user_id` or `email` can't see the channel in `channel_id`. Drop one of the two filters, or pick a channel the trader can see. |

### Fix the data

| Status | Code | What to do |
| --- | --- | --- |
| 404 | - | `user_id` or `email` doesn't match a member of your community. Check the value with Get User Data. |

### Retry with backoff

| Status | Code | What to do |
| --- | --- | --- |
| 500 | - | The key could not be checked (`Authentication failed`). Retry with backoff. |

**Retries:** This endpoint is read-only, so retrying the exact same request is safe after a network error or a `500`. Use bounded exponential backoff. Over the [rate limit](https://docs.returning.ai/how-it-works.md#rate-limits), requests return `429`; wait for the window to reset, then retry.

## Next step

- [Reply message](https://docs.returning.ai/api-reference/messaging/reply-message.md): `POST /v1/messages/reply`. Answer a message you just read, using its `id` as `messageId`.
- [Add a reaction with React Message](https://docs.returning.ai/api-reference/messaging/react-message.md): `POST /v1/messages/react`.
