Histórico de recibos
Após uma mensagem ser enviada, o WhatsApp retorna confirmações de entrega e leitura. O histórico de recibos registra essas confirmações: delivered (entregue no dispositivo) e read (lida pelo destinatário), em ordem cronológica crescente.
Consultar recibos
Para listar o histórico de recibos de uma mensagem, faça uma requisição GET informando o message_id retornado no envio.
Endpoint: GET /v1/messages/{message_id}/receipts para o número principal. Para números extras, use GET /v1/numbers/{ref}/messages/{message_id}/receipts, em que {ref} é o alias atual do número ou o id do número (num_…, o number_id da mensagem).
Escopo obrigatório: messages:read
Parâmetros de caminho:
| Parâmetro | Tipo | Descrição |
|---|---|---|
ref | string | (apenas na rota de número extra) Alias do número ao qual a mensagem pertence (main ou o alias de um número extra) ou o id dele (num_…). |
message_id | string | Identificador público da mensagem (msg_{hex32}) |
curl -X GET \ https://api.turbonotify.com/v1/messages/msg_0198d3c5a1b24d3e9f01a2b3c4d5e6f7/receipts \ -H "Authorization: Bearer SUA_CHAVE"const response = await fetch( 'https://api.turbonotify.com/v1/messages/msg_0198d3c5a1b24d3e9f01a2b3c4d5e6f7/receipts', { method: 'GET', headers: { 'Authorization': 'Bearer SUA_CHAVE' } });
const result = await response.json();console.log(result);import requests
url = "https://api.turbonotify.com/v1/messages/msg_0198d3c5a1b24d3e9f01a2b3c4d5e6f7/receipts"headers = { "Authorization": "Bearer SUA_CHAVE"}
response = requests.get(url, headers=headers)result = response.json()print(result)package main
import ( "fmt" "io" "net/http")
func main() { req, _ := http.NewRequest("GET", "https://api.turbonotify.com/v1/messages/msg_0198d3c5a1b24d3e9f01a2b3c4d5e6f7/receipts", nil) req.Header.Set("Authorization", "Bearer SUA_CHAVE") resp, _ := http.DefaultClient.Do(req) defer resp.Body.Close() body, _ := io.ReadAll(resp.Body) fmt.Println(string(body))}<?php$url = 'https://api.turbonotify.com/v1/messages/msg_0198d3c5a1b24d3e9f01a2b3c4d5e6f7/receipts';
$options = [ 'http' => [ 'header' => [ 'Authorization: Bearer SUA_CHAVE' ], 'method' => 'GET' ]];
$context = stream_context_create($options);$result = file_get_contents($url, false, $context);$response = json_decode($result, true);var_dump($response);?>var client = new HttpClient();client.DefaultRequestHeaders.Add("Authorization", "Bearer SUA_CHAVE");
var response = await client.GetAsync( "https://api.turbonotify.com/v1/messages/msg_0198d3c5a1b24d3e9f01a2b3c4d5e6f7/receipts");var result = await response.Content.ReadAsStringAsync();Console.WriteLine(result);import java.net.http.*;import java.net.URI;
public class TurboNotify { public static void main(String[] args) throws Exception { var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder() .uri(URI.create("https://api.turbonotify.com/v1/messages/msg_0198d3c5a1b24d3e9f01a2b3c4d5e6f7/receipts")) .header("Authorization", "Bearer SUA_CHAVE") .GET() .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); }}Exemplos de resposta
Com histórico completo (mensagem direta)
{
"message_id": "msg_0198d3c5a1b24d3e9f01a2b3c4d5e6f7",
"receipts": [
{
"from": {
"contact_id": "ct_a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4",
"name": "Ana Souza",
"number": "5511988887777"
},
"status": "delivered",
"at": "2025-07-16T10:00:05Z"
},
{
"from": {
"contact_id": "ct_a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4",
"name": "Ana Souza",
"number": "5511988887777"
},
"status": "read",
"at": "2025-07-16T10:01:12Z"
}
]
} Em grupo (múltiplos destinatários)
O campo contact_id aparece apenas para participantes cujo contato já esteja registrado no Turbo Notify. O campo name (o nome de exibição no WhatsApp) é independente: pode aparecer mesmo sem contact_id. No exemplo abaixo, Ana Souza já é um contato registrado; Carlos Lima tem nome de exibição, mas ainda não é um contato registrado.
{
"message_id": "msg_0198d3c5a1b24d3e9f01a2b3c4d5e6f7",
"receipts": [
{
"from": {
"contact_id": "ct_b1c2d3e4f5a6b1c2d3e4f5a6b1c2d3e4",
"name": "Ana Souza",
"number": "5511988887777"
},
"status": "delivered",
"at": "2025-07-16T10:00:05Z"
},
{
"from": {
"name": "Carlos Lima",
"number": "5511977776666"
},
"status": "delivered",
"at": "2025-07-16T10:00:08Z"
},
{
"from": {
"contact_id": "ct_b1c2d3e4f5a6b1c2d3e4f5a6b1c2d3e4",
"name": "Ana Souza",
"number": "5511988887777"
},
"status": "read",
"at": "2025-07-16T10:01:12Z"
}
]
} Sem recibos ainda
{
"message_id": "msg_0198d3c5a1b24d3e9f01a2b3c4d5e6f7",
"receipts": []
} Estrutura da resposta
| Campo | Tipo | Descrição |
|---|---|---|
message_id | string | Identificador público da mensagem. |
receipts | array | Lista de transições de status, em ordem cronológica crescente. |
receipts[].from | object | Quem confirmou o recibo. Omitido quando o WhatsApp não informa nenhum dado de quem confirmou o recibo. |
receipts[].from.contact_id | string | Identificador público do contato (ct_{hex32}). Omitido quando não disponível. |
receipts[].from.name | string | Nome de exibição no WhatsApp (dado pessoal, sob responsabilidade da sua organização). Omitido quando não disponível. |
receipts[].from.number | string | Número E.164 sem + de quem confirmou o recibo. Omitido quando o WhatsApp não revela o número de quem confirmou o recibo. |
receipts[].status | string | Status atingido nesta transição (delivered ou read). |
receipts[].at | string | Data e hora ISO 8601 em que o status foi registrado. |
Tabela de status
| Status | Descrição |
|---|---|
delivered | Confirmação do WhatsApp de que a mensagem foi entregue ao dispositivo. |
read | Confirmação do WhatsApp de que a mensagem foi lida pelo destinatário. |
Nota: Apenas confirmações enviadas pelo WhatsApp (
deliverederead) são registradas nos recibos. O statussent(envio ao WhatsApp) pode ser consultado viaGET /v1/numbers/{ref}/messages/{id}/status.
Exige plano Empresarial ou superior
O histórico detalhado de recibos (GET .../messages/{id}/receipts) requer o recurso read_receipts, disponível a partir do plano Empresarial. Organizações nos planos Gratuito e Lobo Solitário recebem:
{
"error": "feature_not_available"
} Essa restrição vale para as duas rotas (a aninhada /v1/numbers/{ref}/messages/{id}/receipts e a rota curta /v1/messages/{id}/receipts do número principal). A restrição não afeta o status geral da mensagem: GET .../messages/{id}/status continua disponível em todos os planos, inclusive no Gratuito e no Lobo Solitário. Só o histórico detalhado, mudança a mudança, exige o plano Empresarial ou superior.
Veja Cota e uso para os limites e restrições de cada plano.
Erros possíveis
| Status | Código de erro | Descrição |
|---|---|---|
402 | feature_not_available | Organização no plano Gratuito ou Lobo Solitário: o histórico de recibos exige o plano Empresarial ou superior. |
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:read. |
404 | not_found | A mensagem não foi encontrada, pertence a outra organização ou pertence a um número diferente do da URL (na rota atalho sem {ref}, o número principal): todos esses casos devolvem a mesma resposta, sem distinção. |
404 | number_not_found | (apenas na rota com {ref}) O alias ou o id informado na URL não corresponde a nenhum número cadastrado. |
400 | invalid_number_id | (apenas na rota com {ref}) O valor na URL começa com num_, mas não é um id de número válido. |
500 | internal_error | Erro interno inesperado no servidor. |