WASync · Developers
API ReferenceMessages

Mark inbound messages as read (blue ticks)

Sends a WhatsApp **read receipt** so the customer sees the blue ticks on the messages they sent you. Call this the moment one of your operators opens the conversation in your own UI. If your agents read WhatsApp inside your CRM, nobody ever opens the chat in WhatsApp — the customer's messages stay on double grey ticks and the conversation feels ignored. **Scope is `whatsapp.send`, not `whatsapp.read`:** marking read TRANSMITS a receipt from your number to the customer's device, so it is an outbound action. Any client that can already send can mark read — no new scope, no re-consent. Supply `connectionId` plus at least one of `phone` / `messageId`. `messageId` is WASync's stable id (a cuid) of an INCOMING message — not `waMessageId`. When both are given, `messageId` wins. Idempotent by nature: re-marking an already-read conversation is a no-op, so no `idempotencyKey` is accepted and no rate limit applies. Retry freely. Connection differences: WAPP/QR connections mark the whole chat; WABA (official API) connections can only mark one specific message, so a `phone`-only request resolves your most recent inbound message from that number automatically.

POST
/messages/read

Sends a WhatsApp read receipt so the customer sees the blue ticks on the messages they sent you.

Call this the moment one of your operators opens the conversation in your own UI. If your agents read WhatsApp inside your CRM, nobody ever opens the chat in WhatsApp — the customer's messages stay on double grey ticks and the conversation feels ignored.

Scope is whatsapp.send, not whatsapp.read: marking read TRANSMITS a receipt from your number to the customer's device, so it is an outbound action. Any client that can already send can mark read — no new scope, no re-consent.

Supply connectionId plus at least one of phone / messageId. messageId is WASync's stable id (a cuid) of an INCOMING message — not waMessageId. When both are given, messageId wins.

Idempotent by nature: re-marking an already-read conversation is a no-op, so no idempotencyKey is accepted and no rate limit applies. Retry freely.

Connection differences: WAPP/QR connections mark the whole chat; WABA (official API) connections can only mark one specific message, so a phone-only request resolves your most recent inbound message from that number automatically.

AuthorizationBearer <token>

The default way to authenticate. Create a key at https://developers.wasync.app/keys and send it as Authorization: Bearer wsk_live_….

The key is shown once at creation and stored only as a hash — lose it and you revoke it and create another. Each key carries its own scopes (whatsapp.read, whatsapp.send, whatsapp.events, whatsapp.manage) and an optional IP allowlist.

Errors: an unknown or revoked key returns 401 invalid_key; a key whose IP allowlist does not cover the calling address returns 403 ip_not_allowed (a distinct code on purpose — the key is fine, the address is not). Both carry a WWW-Authenticate: Bearer challenge. Scopes and the connection list are resolved live on every request, so revoking a key or narrowing it takes effect on the next call.

In: header

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Identifies the conversation to blue-tick. connectionId is always required; supply at least one of phone / messageId (if both are present, messageId wins).

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

application/json

application/json

curl -X POST "https://example.com/messages/read" \  -H "Content-Type: application/json" \  -d '{    "connectionId": "conn_8f3a21",    "phone": "40700000000"  }'
{  "ok": true,  "marked": 3}