/v1/conversations/{conversation_id}/messagesbetaList messages of a conversation
- Needs
- Read your data
(mcp:read) - Plan
- Any plan with API access
- Limits
- 300 a minute per key
- Undo
- Nothing to undo: this only reads.
Returns the messages of one conversation, newest first (or oldest first with order=oldest_first). Each message has its type, direction (inbound from the customer, outbound from your team, a bot or the API, system for notes like assignments), delivery status and its text or caption. Media files and their links are never included. Reading does not mark anything as read.
Pages hold 1–100 messages (limit, default 25). Pass next_cursor as cursor to get the next page; it is null on the last page. With the types, direction or status filters a page may hold fewer than limit messages while next_cursor is still set: keep paging until it is null.
Try it
Query (9)
`newest_first` (default) or `oldest_first`.
Only messages containing this text.
`inbound` = from the customer; `outbound` = from your team, a bot or the API; `system` = assignment and close notes.
Only messages with this delivery status.
Only messages that failed to deliver.
Cut each message text after this many characters (50–4000, default 1000); `text_truncated` tells.
How many messages per page (1–100, default 25).
The `next_cursor` from the previous page. Cursors expire after 24 hours.
This only reads. It uses your real data and changes nothing.
Code and response
curl -X GET 'https://mcp.wa-api.cloud/v1/conversations/77410/messages?limit=2' \ -H "Authorization: Bearer $API_KEY"
The code reads your key from $API_KEY.
Parameters
| Field | Type | What it is |
|---|---|---|
| conversation_idrequired | string · path | The conversation id.pattern ^\d{1,19}$Signed in? Pick one from your data with “My data”. |
| order | string · query | newest_first (default) or oldest_first.one of: newest_first, oldest_first · default "newest_first" |
| search | string · query | Only messages containing this text.1–200 characters |
| types | array of string · query | Only these message types. Repeat the parameter for several.1–∞ items |
| direction | string · query | inbound = from the customer; outbound = from your team, a bot or the API; system = assignment and close notes.one of: inbound, outbound, system |
| status | string · query | Only messages with this delivery status.one of: received, pending, sent, delivered, read, failed |
| failed_only | boolean · query | Only messages that failed to deliver. |
| max_text_chars | integer · query | Cut each message text after this many characters (50–4000, default 1000); text_truncated tells.50–4000 · default 1000 |
| limit | integer · query | How many messages per page (1–100, default 25).1–100 · default 25 |
| cursor | string · query | The next_cursor from the previous page. Cursors expire after 24 hours.1–2048 characters |
Headers
| Field | Type | What it is |
|---|---|---|
| Authorizationrequired | header | Bearer $API_KEY — your API key. |
| Api-Version | header | The API version to use, e.g. 2026-10-01. Default: the version your key is pinned to.one of: 2026-10-01 · pattern ^\d{4}-\d{2}-\d{2}$ |
Response 200
A page of messages.
| Field | Type | What it is |
|---|---|---|
| datarequired | array of object | |
| idrequired | string | |
| conversation_idrequired | string or null | |
| typerequired | string | TEXT, IMAGE, VIDEO, AUDIO, DOCUMENT, STICKER, LOCATION, TEMPLATE, INTERACTIVE, ORDER, CONTACTS, SYSTEM |
| directionrequired | string | one of: inbound, outbound, system |
| statusrequired | string | received (inbound) | pending | sent | delivered | read | failed | system |
| textrequired | string or null | Message text, or the caption for media. Media files/URLs are never included. |
| text_truncatedrequired | boolean | |
| has_mediarequired | boolean | |
| fromrequired | object or null | Who sent an outbound message (staff or bot); null for inbound. |
| staff_idrequired | string or null | |
| staff_namerequired | string or null | |
| botrequired | boolean | |
| reply_to_idrequired | string or null | |
| errorrequired | string or null | |
| created_atrequired | string or null | |
| next_cursorrequired | string or null | Pass as "cursor" to get the next page; null when there are no more results. |
Errors
Errors are application/problem+json. Branch on code.
| Status | Code | When |
|---|---|---|
| 400 | invalid_input | A field is missing or has the wrong format. |
| 401 | unauthenticated | The Authorization header is missing, the key is unknown, expired or revoked. |
| 403 | entitlement_required | The workspace's plan does not include API access ( |
| 403 | insufficient_scope | The key does not have the permission this operation needs. |
| 404 | not_found | No conversation with this id, or your key cannot see it. |
| 429 | rate_limited | The key or workspace went over its rate limit. Wait for |
| 503 | upstream_unavailable | A service behind the API is briefly unavailable. Safe to retry with backoff. |
Examples
The latest messages
Response 200
{
"data": [
{
"id": "5501235",
"conversation_id": "77410",
"type": "TEXT",
"direction": "outbound",
"status": "delivered",
"text": "Yes! It ships today.",
"text_truncated": false,
"has_media": false,
"from": {
"staff_id": "1203",
"staff_name": "Priya Nair",
"bot": false
},
"reply_to_id": "5501234",
"error": null,
"created_at": "2026-09-24T09:14:00Z"
},
{
"id": "5501234",
"conversation_id": "77410",
"type": "TEXT",
"direction": "inbound",
"status": "received",
"text": "Hi, is the blue one in stock?",
"text_truncated": false,
"has_media": false,
"from": null,
"reply_to_id": null,
"error": null,
"created_at": "2026-09-24T09:12:00Z"
}
],
"next_cursor": "eyJ2IjoxLCJwIjp7ImMiOiJNZyJ9fQ.q1f0bm9ZS2dLQnVQ"
}Operation path
The same operation is also at POST /v1/ops/inbox_list_messages, with every field in the JSON body.