Skip to content
SocialMate

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)

GET /v1/accounts/{id}/messages

scope: readPro

List 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 } }
GET /v1/accounts/{id}/polls/{messageId}

scope: readPro

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.

GET /v1/accounts/{id}/ai-context

scope: readPro

The 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.

QueryTypeNotes
chatIdstringRequired. The conversation to build context for.
maxMessages1–500Most-recent N messages to consider. Default 50.
maxTokens100–32000Token budget; the transcript is trimmed to fit. Default 4000.
formatenumboth (default), messages, or transcript.
orderenumoldest (default) or newest.
includeTimestampsboolPrefix transcript lines with a timestamp. Default false.
beforeTsintegerExclude 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

POST /v1/accounts/{id}/messages

scope: sendFree: textPro: media

Unified 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.

POST /v1/accounts/{id}/messages/media

scope: sendPro

Legacy dedicated media route, kept for back-compat — responses carry Deprecation/Sunset headers. Prefer the unified endpoint.

Trigger a backfill sync (Pro)

POST /v1/accounts/{id}/sync

scope: adminPro

Kick off a historical backfill into the local cache. Body: typefull (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" } }
GET /v1/sync/status

scope: read

The 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 } ] }
Free forever · no card Download free