Chats and history
List chats, read a conversation page by page, and ask the phone for older history.
GET/v1/sessions/<CHANNEL_ID>/chats
List chats, up to 100.
GET/v1/sessions/<CHANNEL_ID>/chats/<CHAT_JID>/messages
Read one conversation, newest first.
GET/v1/sessions/<CHANNEL_ID>/history-sync
See whether synced history is stored.
PUT/v1/sessions/<CHANNEL_ID>/history-sync
Turn storing synced history on or off.
POST/v1/sessions/<CHANNEL_ID>/chats/<CHAT_JID>/history-requests
Ask the phone for older messages of one chat.
Chats and messages come from WAgate's own log of this channel. The log starts when the number was linked, unless synced history is on.
List chats
curl "https://api-wagate.socialground.co/v1/sessions/<CHANNEL_ID>/chats" -H "Authorization: Bearer <CHANNEL_TOKEN>"{
"chats": [
{ "chat_jid": "[email protected]", "last_at": "2026-09-17T03:00:00Z", "message_count": 42, "unread": 2 }
]
}Up to 100 chats. unread can be null.
Read a conversation
curl "https://api-wagate.socialground.co/v1/sessions/<CHANNEL_ID>/chats/[email protected]/messages?limit=50" \
-H "Authorization: Bearer <CHANNEL_TOKEN>"{
"messages": [
{
"id": "3EB0C767D26A1D8E2A41",
"chat_jid": "[email protected]",
"sender_jid": "[email protected]",
"direction": "in",
"type": "text",
"text": "hello",
"from_me": false,
"timestamp": "2026-09-17T03:00:00Z",
"source": "live",
"source_chat": "[email protected]"
}
],
"chats": ["[email protected]"],
"merge": "none_known",
"next_before": "AbC123"
}- Messages come newest first, 50 to a page by default.
limitis 1 to 500. - When older messages exist, the response has
next_before. Pass it back asbefore=<value>, exactly as returned. Stop when it is absent. Any otherbeforevalue is a 400. limitandbeforeare the only query parameters this route reads.directionisinorout.from_meis the more reliable field: a message sent from the paired phone is stored asinwithfrom_me: true.sourceislivefor a message captured while the channel was connected, orhistory_syncfor one the phone sent as history.typeincludes text, image, video, document, audio, sticker, contact, contact_list, location, live_location, poll, poll_vote, reaction, protocol, short, group_invite and unknown. New values can be added, so treat one you do not recognize as unknown.- Other fields on a message when they apply:
media_id,push_name,mentions,quoted_id,quoted_author,poll,reaction,revoke,revoked_at,ambiguous,chat_lid,sender_lid,sender_pn_resolved,quoted_author_lid. ambiguous: truemarks a send that answered 504send_unconfirmed. Itsidstarts withambiguous:and is not a WhatsApp message ID. The message may or may not have been delivered. The row records the attempt, not the outcome.revoked_atis set when a message was deleted for everyone. The log keeps the message's content.
A paging loop:
let before;
do {
const url = new URL(`${API}/sessions/<CHANNEL_ID>/chats/${chat}/messages`);
url.searchParams.set('limit', '200');
if (before) url.searchParams.set('before', before);
const res = await fetch(url, { headers: { Authorization: `Bearer ${TOKEN}` } });
const page = await res.json();
handle(page.messages);
before = page.next_before;
} while (before);One person, two addresses
WhatsApp may file a person's messages under their phone number and under a LID. On a channel that holds the lid_lookup grant, both are read and merged into one timeline. merge says what happened:
merged: both addresses were read.none_known: no other address is known for this person.not_granted: your channel does not hold the grant, so only the address you named was read.not_a_person: the chat is a group.
Each message's source_chat says which address it is filed under. In a group, each sender is shown once. sender_jid is their phone number where known, and sender_lid is the LID they were stored under.
Reads are recorded
Each page you read is recorded in your API access records: which token read it, which chats, and how many messages. The content is never recorded there.
History from the phone
Storing history the phone sends is off by default.
curl -X PUT "https://api-wagate.socialground.co/v1/sessions/<CHANNEL_ID>/history-sync" \
-H "Authorization: Bearer <CHANNEL_TOKEN>" -H "Content-Type: application/json" \
-d '{"store_history_sync": true}'
# {"store_history_sync":true}
curl "https://api-wagate.socialground.co/v1/sessions/<CHANNEL_ID>/history-sync" -H "Authorization: Bearer <CHANNEL_TOKEN>"
# {"store_history_sync":true}- The body must be exactly that one field, true or false. Any other body is refused with 400
field_not_allowed. - With it on, history your phone sends is kept with this channel's messages, under the same retention, and returned by the conversation read with
source: history_sync. Turning it off stops storing. What was stored stays until retention removes it. The gateway does not read or use this content. It only stores it for your channel. - A phone sends history when you link it and when you ask. Turn the setting on before linking to receive up to 200 recent messages per chat, from within the message retention period.
Ask for older messages of one chat:
curl -X POST "https://api-wagate.socialground.co/v1/sessions/<CHANNEL_ID>/chats/[email protected]/history-requests" \
-H "Authorization: Bearer <CHANNEL_TOKEN>" -H "Content-Type: application/json" \
-d '{"count": 50}'{
"status": "requested",
"chat_jid": "[email protected]",
"before_message_id": "3EB0C767D26A1D8E2A41",
"before": "2026-09-01T03:00:00Z",
"count": 50
}- The body is optional.
countis 1 to 50 and defaults to 50. The request asks for messages older than the oldest one this channel holds for the chat. - The answer is 202. The phone replies later, in its own time, and the messages then appear in the conversation read with
source: history_sync. Whether the phone answers, and how much, is up to the phone. - If
store_history_syncis off, it answers 409history_sync_off. If the channel holds no message of that chat, it answers 404no_history_anchor. - Limits: one request per channel every 30 seconds, and one per chat every 5 minutes. Over that, 429
history_request_too_soonwith aRetry-Afterheader and the same number asretry_afterin the body. Wait that long. - Each request is recorded in your API access records.
Errors on these routes
403 blocked, 404 not_found, 400 invalid_request or field_not_allowed, 429 history_request_too_soon. See Errors.