SocialMate Local API
Messages reference
Send and read messages: parameters, validation limits, and every response code.
The messages resource covers reading history and sending. Sending (text, with media on Pro) is fully covered in Sending messages; this page is the compact reference plus the read & sync endpoints.
Read history (Pro)
/v1/accounts/{id}/messagesList or search stored messages. Requires Pro (localMessageCache) — Free returns
402. Query params: chatId, search, limit
(max 500, default 100), offset, and afterTs — a Unix-ms timestamp
(exclusive) that returns only messages arriving after it. afterTs is the poll
cursor: it is how an agent that cannot receive a webhook (an MCP client, for instance)
fetches what is new since it last checked. Returns the paginated envelope. A message with media
carries a media block — id, kind, mimeType,
caption, apiPath (fetch the bytes), and, once your AI has described it,
the cached context + needsContext flag (see
Agent Memory).
curl "http://localhost:3456/v1/accounts/ACCOUNT_ID/[email protected]&limit=50" \
-H "x-api-key: YOUR_KEY"
Every message also carries a reactions array (empty when nobody reacted), and a
type: "poll" message carries a poll block with the aggregate tally. To see
who voted for what, call
GET /v1/accounts/{id}/polls/{messageId}.
{ "data": [
{ "id": "msg_1", "body": "Hi", "type": "text", "hasMedia": false, "media": null,
"reactions": [ { "emoji": "👍", "senderId": "15559876543", "senderName": "Jane", "fromMe": false, "ts": 1750000100000 } ] },
{ "id": "msg_2", "type": "image", "hasMedia": true, "reactions": [],
"media": { "id": "med_1", "kind": "image", "mimeType": "image/jpeg",
"apiPath": "/v1/accounts/ACCOUNT_ID/media/med_1/file",
"context": "A signed invoice #A-1001, total $420.", "needsContext": false } },
{ "id": "msg_3", "type": "poll", "body": "Which day?", "reactions": [],
"poll": { "tally": { "Monday": 3, "Tuesday": 1 }, "totalVoters": 4 } }
], "pagination": { "limit": 50, "offset": 0, "total": 318 } }
/v1/accounts/{id}/polls/{messageId}Read back a poll's results by its message id — the pull-side counterpart of the
poll.vote webhook, for a workflow that sent a poll and wants to know whether it was
answered. Requires Pro (localMessageCache); Free returns 402 and should
consume results live from the poll.vote webhook instead.
Re-voting replaces a person's previous choice (WhatsApp's own semantics), so the
tally is derived from the current selections and can never double-count. An option nobody picked is
still listed, with a count of 0.
curl "http://localhost:3456/v1/accounts/ACCOUNT_ID/polls/msg_3" \
-H "x-api-key: YOUR_KEY"
{ "data": {
"messageId": "msg_3", "chatId": "[email protected]", "name": "Which day?",
"options": [ "Monday", "Tuesday", "Wednesday" ], "selectableCount": 1,
"tally": { "Monday": 3, "Tuesday": 1, "Wednesday": 0 },
"totalVoters": 4,
"voters": [ { "voterId": "15559876543", "voterName": "Jane", "options": [ "Monday" ], "ts": 1750000300000 } ]
} }
Votes are readable for any poll SocialMate saw created — one you sent through the API, and one the contact created while your account was connected. A poll from before the account was linked returns its question and options with an empty tally.
/v1/accounts/{id}/ai-contextThe integration's "memory" primitive — built for AI agents. Drop it between a Trigger and
an AI node: it role-maps one conversation (the contact becomes user, your account
assistant), windows it to a token budget, and returns both a
ready-to-paste transcript and a structured messages[] array — no WhatsApp
round-trips. Requires Pro (localMessageCache); Free returns 402.
| Query | Type | Notes |
|---|---|---|
chatId | string | Required. The conversation to build context for. |
maxMessages | 1–500 | Most-recent N messages to consider. Default 50. |
maxTokens | 100–32000 | Token budget; the transcript is trimmed to fit. Default 4000. |
format | enum | both (default), messages, or transcript. |
order | enum | oldest (default) or newest. |
includeTimestamps | bool | Prefix transcript lines with a timestamp. Default false. |
beforeTs | integer | Exclude messages at/after this Unix-ms time (windowing). |
curl "http://localhost:3456/v1/accounts/ACCOUNT_ID/[email protected]&maxMessages=50&format=both" \
-H "x-api-key: YOUR_KEY"
Reactions and poll results are rendered into the turns (and mirrored on
messages[]), so the agent reads how people responded — not just what was said — and both
are priced into the token budget.
{ "data": {
"account": { "id": "a1b2c3", "name": "Sales", "phone": "15551234567" },
"chat": { "id": "[email protected]", "name": "Jane" },
"messages": [
{ "role": "user", "name": "Jane", "content": "Hi [reactions: 👍 you]", "ts": 1750000000000, "type": "text",
"reactions": [ { "emoji": "👍", "from": "Sales", "fromMe": true } ] },
{ "role": "assistant", "name": "Sales", "type": "poll",
"content": "[poll: Which day? — Monday: 3, Tuesday: 1 (4 voters)]",
"poll": { "tally": { "Monday": 3, "Tuesday": 1 }, "totalVoters": 4 } }
],
"transcript": "Jane: Hi [reactions: 👍 you]\nSales: [poll: Which day? — Monday: 3, Tuesday: 1 (4 voters)]",
"meta": { "totalMessages": 2, "returnedMessages": 2, "truncated": false, "oldestReturnedTs": 1750000000000, "newestReturnedTs": 1750000200000, "tokenEstimate": 34, "window": { "maxMessages": 50, "maxTokens": 4000 } }
} }
Send
/v1/accounts/{id}/messagesUnified send — text or a media object. Returns 200
(sent), 202 (auto-queued, Pro), or 429 (blocked, Free). Full body,
limits, and the anti-ban paths are in
Sending messages.
/v1/accounts/{id}/messages/mediaLegacy dedicated media route, kept for back-compat — responses carry
Deprecation/Sunset headers. Prefer the unified endpoint.
Trigger a backfill sync (Pro)
/v1/accounts/{id}/syncKick off a historical backfill into the local cache. Body: type ∈
full (default), contacts, messages, chats.
Requires Pro (localMessageCache). Runs in the background — track it via the
sync.* webhooks or the status endpoint.
curl -X POST http://localhost:3456/v1/accounts/ACCOUNT_ID/sync \
-H "x-api-key: YOUR_KEY" -H "content-type: application/json" \
-d '{ "type": "full" }'
{ "data": { "success": true, "accountId": "a1b2c3", "type": "full", "status": "started" } }
/v1/sync/statusThe most recent sync jobs with status, progress,
itemsDone/itemsTotal, and timing.
curl http://localhost:3456/v1/sync/status \
-H "x-api-key: YOUR_KEY"
{ "data": [ { "id": "sync_1", "accountId": "a1b2c3", "type": "full", "status": "completed", "progress": 100, "itemsDone": 4200, "itemsTotal": 4200 } ] }