curl --request GET \
--url https://api.vambe.me/api/public/contact/v3/{aiContactId}/messages \
--header 'x-api-key: <x-api-key>'const options = {method: 'GET', headers: {'x-api-key': '<x-api-key>'}};
fetch('https://api.vambe.me/api/public/contact/v3/{aiContactId}/messages', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.vambe.me/api/public/contact/v3/{aiContactId}/messages"
headers = {"x-api-key": "<x-api-key>"}
response = requests.get(url, headers=headers)
print(response.text){
"data": [
{
"id": "df980fc8-b6db-4820-bf22-2969482d106d",
"created_at": "2024-09-30T10:00:00.000Z",
"body": "Hola, necesito ayuda",
"direction": "inbound",
"type": "text",
"content": "<unknown>",
"provider_message_id": "wamid.HBgLNTY5MTIzNDU2NzgVAgARGBI5QTND",
"attribution_id": "<string>",
"user": {
"first_name": "Jane",
"last_name": "Doe"
},
"assistant": {
"id": "123e4567-e89b-12d3-a456-426614174000",
"name": "Vambe"
},
"campaign": {
"title": "Reactivación agosto"
},
"ticket_id": "7c3e4f21-9b8a-4d5e-8f60-1a2b3c4d5e6f"
}
],
"page": 1,
"page_size": 15,
"pages": 3,
"total": 45,
"has_next_page": true
}Retrieve messages by AI contact with pagination
Paginated message history, newest first. Prefer this over v2: page is 1-based and echoed back unchanged, page_size is configurable, and total/pages describe exactly what data contains — data.length never exceeds page_size, and summing data across all pages equals total. Unlike v2, the response contains only real messages: the synthetic “stage” and “interactive_note” entries that v2 injects are not messages and are not returned here. Also unlike v2, this endpoint is side-effect free: reading messages does NOT mark the conversation as read. Requesting a page beyond the last one returns an empty data with has_next_page: false.
curl --request GET \
--url https://api.vambe.me/api/public/contact/v3/{aiContactId}/messages \
--header 'x-api-key: <x-api-key>'const options = {method: 'GET', headers: {'x-api-key': '<x-api-key>'}};
fetch('https://api.vambe.me/api/public/contact/v3/{aiContactId}/messages', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.vambe.me/api/public/contact/v3/{aiContactId}/messages"
headers = {"x-api-key": "<x-api-key>"}
response = requests.get(url, headers=headers)
print(response.text){
"data": [
{
"id": "df980fc8-b6db-4820-bf22-2969482d106d",
"created_at": "2024-09-30T10:00:00.000Z",
"body": "Hola, necesito ayuda",
"direction": "inbound",
"type": "text",
"content": "<unknown>",
"provider_message_id": "wamid.HBgLNTY5MTIzNDU2NzgVAgARGBI5QTND",
"attribution_id": "<string>",
"user": {
"first_name": "Jane",
"last_name": "Doe"
},
"assistant": {
"id": "123e4567-e89b-12d3-a456-426614174000",
"name": "Vambe"
},
"campaign": {
"title": "Reactivación agosto"
},
"ticket_id": "7c3e4f21-9b8a-4d5e-8f60-1a2b3c4d5e6f"
}
],
"page": 1,
"page_size": 15,
"pages": 3,
"total": 45,
"has_next_page": true
}Overview
Retrieve a contact’s messages with pagination, newest first. This is the recommended endpoint for reading message history. Use this instead of v2:page is 1-based and echoed back unchanged, page_size is configurable, and the counters describe exactly what you receive.
Authentication
Include your API key in the request header:x-api-key: your_api_key_here
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
aiContactId | string (UUID) | Yes | Unique identifier of the contact |
Query Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
page | number | No | 1 | Page number, 1-based. Page 1 = newest messages |
page_size | number | No | 15 | Messages per page, between 1 and 100 |
page below 1, page_size outside 1–100, and fractional values are rejected with 400.
Response Structure
| Field | Type | Description |
|---|---|---|
data | array | Messages for this page, ordered newest first |
page | number | The page you requested, echoed back |
page_size | number | The page size in effect |
pages | number | Total number of pages. Valid values for page are 1..pages |
total | number | Total messages for this contact across all pages |
has_next_page | boolean | Whether a page after this one exists |
data never holds more than page_size
items, and summing data across all pages equals total.Message Object
This list is exhaustive and identical on every channel — the response carries these fields and nothing else:| Field | Type | Description |
|---|---|---|
id | string | Message identifier, always a string (some channels store it as an integer internally) |
created_at | string (ISO) | Message timestamp |
body | string | Message text |
direction | string | inbound, outbound, internal_note, ai_note or task |
type | string | Channel message type, e.g. text, image, audio, document |
content | object | array | null | Structured payload for non-text messages, as delivered by the channel. Channel-defined shape — WhatsApp template messages carry an array of components. Do not assume a fixed shape |
provider_message_id | string | null | Channel provider’s own message id |
attribution_id | string | null | Attribution identifier, when set |
user | object | null | Human sender (first_name, last_name) when sent by an agent |
assistant | object | null | AI sender (id, name) when sent by an assistant |
campaign | object | null | { title } when the message came from a campaign |
ticket_id | string | null | Ticket this message belongs to, when there is one |
whatsapp_message on top of the flattened
fields, plus the ticket, summary and activity graph. If you depend on a field
that only exists there, tell us and we will consider adding it to v3 rather
than exposing the internal row.stage
and interactive_note entries that v2 mixes into its list are not messages
and are not returned here.Example Request
curl --request GET \
'https://api.vambe.me/api/public/contact/v3/df980fc8-b6db-4820-bf22-2969482d106d/messages?page=1&page_size=15' \
--header 'x-api-key: your_api_key_here'
Example Response
{
"data": [
{
"id": "9f1c2b3a-5d6e-4f70-8a91-2b3c4d5e6f70",
"created_at": "2024-09-30T10:01:30.000Z",
"body": "¡Por supuesto! ¿Cuál es tu número de pedido?",
"direction": "outbound",
"type": "text",
"content": null,
"provider_message_id": "wamid.HBgLNTY5MTIzNDU2NzgVAgARGBI5QTND",
"attribution_id": null,
"user": null,
"assistant": {
"id": "123e4567-e89b-12d3-a456-426614174000",
"name": "Vambe"
},
"campaign": null,
"ticket_id": "7c3e4f21-9b8a-4d5e-8f60-1a2b3c4d5e6f"
},
{
"id": "6b0d8e1f-2a34-4c56-9d78-0e1f2a3b4c56",
"created_at": "2024-09-30T10:00:00.000Z",
"body": "Hola, necesito ayuda con mi pedido",
"direction": "inbound",
"type": "text",
"content": null,
"provider_message_id": "wamid.HBgLNTY5ODc2NTQzMjEVAgASGBQzQjJE",
"attribution_id": null,
"user": null,
"assistant": null,
"campaign": null,
"ticket_id": "7c3e4f21-9b8a-4d5e-8f60-1a2b3c4d5e6f"
}
],
"page": 1,
"page_size": 15,
"pages": 9,
"total": 127,
"has_next_page": true
}
Fetching the Full History
const getAllMessages = async (contactId, apiKey) => {
const all = [];
let page = 1;
while (true) {
const response = await fetch(
`https://api.vambe.me/api/public/contact/v3/${contactId}/messages?page=${page}&page_size=100`,
{ headers: { 'x-api-key': apiKey } },
);
const result = await response.json();
all.push(...result.data);
if (!result.has_next_page) {
return all; // all.length === result.total
}
page += 1;
}
};
data with has_next_page: false.
Error Responses
| Status Code | Description |
|---|---|
| 400 | Invalid page or page_size |
| 401 | Unauthorized — invalid or missing API key |
| 404 | Contact not found for this API key’s account |
| 500 | Internal Server Error |
Important Notes
- Order is newest first. Page 1 holds the most recent messages.
- Reading is side-effect free. Unlike v2, fetching messages here does not mark the conversation as read, so polling this endpoint never changes what your agents see as unread.
- Deleted Instagram messages are excluded from
data,totalandpages. - Cross-channel: works for every channel a contact may use.
Related Endpoints
- GET /api/public/contact/v2//messages — legacy paginated history
- GET /api/public/contact//conversations — messages grouped into conversations
- GET /api/public/contact//info — contact info
Headers
API key required to authorize the request
Path Parameters
ID of the AI contact
Query Parameters
Page number, 1-based. Page 1 returns the newest messages. Defaults to 1.
1 <= x <= 90071992547409911
Messages per page, between 1 and 100. Defaults to 15.
1 <= x <= 10015
Response
Messages retrieved successfully.
Messages for this page, newest first. The shape below is exhaustive and identical across channels: no channel-specific or internal fields are returned.
Show child attributes
Show child attributes
The requested page, echoed back.
1
15
Total number of pages. Valid values for page are 1..pages.
3
Total messages for this contact, across all pages.
45
true
Was this page helpful?
