Marcar como lida
Marcar mensagens como lidas sinaliza ao WhatsApp que sua aplicação leu o histórico de um chat, e mostra o “check azul” para quem enviou as mensagens.
Marcação automática
O Turbo Notify já marca automaticamente o histórico de mensagens não lidas de um chat (ou grupo) como lido antes de enviar, responder, reagir, editar ou excluir uma mensagem nesse mesmo chat, e também quando você começa a digitar (parar de digitar não lê nada). Isso reproduz o comportamento de um cliente WhatsApp real: o número aparece online, as mensagens são lidas e só então a ação acontece.
O número volta a ficar offline sozinho, alguns minutos depois da última interação (é a presença exibida no WhatsApp: a conexão e o status do número não mudam). Abrir a conversa dessa forma é automático, não consome cota própria (o envio, a resposta ou a reação contam como antes) e não gera evento de webhook.
Use o endpoint abaixo apenas quando quiser marcar um chat como lido sem realizar nenhuma outra ação no WhatsApp (o número também aparece online antes de ler), por exemplo para manter a caixa de entrada da sua própria aplicação sincronizada com o WhatsApp.
Um agente de IA conectado pelo Servidor MCP faz o mesmo com a ferramenta mark_as_read (escopo messages:send, mesma exigência de plano), útil para triagem ou para passar a conversa a uma pessoa sem responder.
Marcar um chat como lido
curl -X POST \ https://api.turbonotify.com/v1/messages/read \ -H "Authorization: Bearer SUA_CHAVE" \ -H "Content-Type: application/json" \ -d '{ "to": {"number": "+5511988887777"} }'const response = await fetch('https://api.turbonotify.com/v1/messages/read', { method: 'POST', headers: { 'Authorization': 'Bearer SUA_CHAVE', 'Content-Type': 'application/json' }, body: JSON.stringify({ to: { number: '+5511988887777' } })});
console.log(response.status); // 202import requests
url = "https://api.turbonotify.com/v1/messages/read"headers = { "Authorization": "Bearer SUA_CHAVE", "Content-Type": "application/json"}data = { "to": {"number": "+5511988887777"}}
response = requests.post(url, json=data, headers=headers)print(response.status_code) # 202package main
import ( "fmt" "net/http" "strings")
func main() { payload := strings.NewReader(`{"to": {"number": "+5511988887777"}}`) req, _ := http.NewRequest("POST", "https://api.turbonotify.com/v1/messages/read", payload) req.Header.Set("Authorization", "Bearer SUA_CHAVE") req.Header.Set("Content-Type", "application/json") resp, _ := http.DefaultClient.Do(req) defer resp.Body.Close() fmt.Println(resp.StatusCode) // 202}<?php$url = 'https://api.turbonotify.com/v1/messages/read';$data = [ 'to' => ['number' => '+5511988887777']];
$options = [ 'http' => [ 'header' => [ 'Authorization: Bearer SUA_CHAVE', 'Content-Type: application/json' ], 'method' => 'POST', 'content' => json_encode($data) ]];
$context = stream_context_create($options);file_get_contents($url, false, $context);var_dump($http_response_header);?>using System.Text;using System.Text.Json;
var client = new HttpClient();client.DefaultRequestHeaders.Add("Authorization", "Bearer SUA_CHAVE");
var data = new { to = new { number = "+5511988887777" }};
var json = JsonSerializer.Serialize(data);var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await client.PostAsync("https://api.turbonotify.com/v1/messages/read", content);Console.WriteLine((int)response.StatusCode); // 202import java.net.http.*;import java.net.URI;
public class MarkAsRead { public static void main(String[] args) throws Exception { var client = HttpClient.newHttpClient();
var json = """ { "to": {"number": "+5511988887777"} } """;
var request = HttpRequest.newBuilder() .uri(URI.create("https://api.turbonotify.com/v1/messages/read")) .header("Authorization", "Bearer SUA_CHAVE") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(json)) .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.statusCode()); // 202 }}Após enviar, o Turbo Notify retorna aceite assíncrono:
{
"operation_id": "op_read_9f3c2a1d47e8",
"status": {
"state": "pending",
"at": "2025-07-16T10:00:00Z"
}
} O aceite assíncrono confirma apenas que a operação foi enfileirada. O histórico de mensagens não lidas é buscado no momento do processamento; se não houver nenhuma mensagem pendente, nada é marcado como lido (o número ainda aparece online), sem gerar erro.
Destinatários disponíveis
O campo to aceita exatamente uma das três formas abaixo, assim como na rota de envio de mensagens:
| Forma | Exemplo | Quando usar |
|---|---|---|
number | {"number": "+5511988887777"} | Número E.164 conhecido |
group_id | {"group_id": "grp_…"} | Grupo do WhatsApp |
contact_id | {"contact_id": "ct_…"} | ID do contato no Turbo Notify (telefone resolvido internamente) |
Marcar um grupo como lido
Para marcar como lidas as mensagens de um grupo do WhatsApp, use to.group_id com o identificador do grupo no lugar de to.number. Como o grupo pode ter várias pessoas com mensagens não lidas, o Turbo Notify agrupa a marcação por remetente dentro do grupo.
curl -X POST \ https://api.turbonotify.com/v1/numbers/ALIAS_DO_NUMERO/messages/read \ -H "Authorization: Bearer SUA_CHAVE" \ -H "Content-Type: application/json" \ -d '{ "to": {"group_id": "grp_a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4"} }'O group_id é o identificador do grupo no formato grp_{hex32}, retornado pelo endpoint de listagem de grupos.
Marcar como lida por contact_id
Use to.contact_id para marcar como lidas as mensagens de um contato do catálogo do Turbo Notify sem informar o telefone diretamente. O telefone é resolvido internamente a partir do registro do contato.
curl -X POST \ https://api.turbonotify.com/v1/numbers/ALIAS_DO_NUMERO/messages/read \ -H "Authorization: Bearer SUA_CHAVE" \ -H "Content-Type: application/json" \ -d '{ "to": {"contact_id": "ct_a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4"} }'Marcar como lida com número extra
Na forma aninhada, o número que marca as mensagens como lidas é sempre o número informado no caminho. Para marcar mensagens como lidas a partir de um número extra cadastrado e ativo, use essa forma com o alias desse número no lugar de {ref}:
curl -X POST \ https://api.turbonotify.com/v1/numbers/vendas-sp/messages/read \ -H "Authorization: Bearer SUA_CHAVE" \ -H "Content-Type: application/json" \ -d '{ "to": {"number": "+5511988887777"} }'As duas formas tratam o número de origem de maneira diferente:
- Aninhada (
POST /v1/numbers/{ref}/messages/read): o número que marca as mensagens é sempre o alias informado no caminho. - Plana (
POST /v1/messages/read): marca sempre a partir do número principal (main).
Para marcar mensagens como lidas a partir de um número extra, use obrigatoriamente a forma aninhada, com o alias do número extra no caminho da URL.
Caso o alias informado no caminho não esteja cadastrado ou o número não esteja ativo, a operação será rejeitada.
Saiba mais sobre números extras.
Eventos de webhook
A marcação como lida não tem confirmação de conclusão: o 202 Accepted confirma apenas o
aceite assíncrono e nenhum evento de webhook é entregue para essas operações.
Erros possíveis
| Status | Código de erro | Descrição |
|---|---|---|
400 | contact_not_found | O contact_id informado em to não pertence a esta organização. |
400 | contacts_not_enabled | A marcação por contact_id está indisponível no momento. Tente de novo mais tarde; se persistir, fale com o suporte. |
400 | groups_not_enabled | O recurso de grupos está indisponível no momento. Tente de novo mais tarde; se persistir, fale com o suporte. |
400 | invalid_recipient | Não foi possível resolver o destinatário informado em to para um endereço de envio. Informar nenhum ou mais de um entre number, group_id e contact_id retorna 422 validation_error. |
402 | feature_not_available | O recurso não está disponível no plano contratado. |
401 | not_authenticated | A chave de API está inválida ou ausente. |
403 | insufficient_scope | A chave de API não possui o escopo messages:send (resposta inclui required_scope). |
404 | number_not_found | O {ref} do caminho não corresponde a nenhum número da conta (na rota plana: a conta ainda não tem número principal). |
400 | invalid_number_id | O valor na URL começa com num_, mas não é um id de número válido. |
404 | group_not_found | O group_id informado em to não foi encontrado. |
409 | number_not_connected | O número não está conectado ao WhatsApp. Reconecte o número e tente de novo. |
422 | sender_not_found | O alias/número informado não corresponde a nenhum remetente da conta. |
422 | validation_error | O corpo da requisição está malformado ou não passou na validação. A resposta inclui details.errors com a lista de campos inválidos. |
500 | internal_error | Erro interno inesperado no servidor. |