Pular para o conteúdo

Mensagens

Tudo o que você faz com mensagens pela API aparece no chat do painel como se a equipe tivesse feito: o envio, a edição, a reação e a mensagem apagada.

Ação Endpoint
Enviar texto e/ou mídia (para contatos e grupos) POST /messages
Consultar uma mensagem e o status de entrega GET /messages/{message_id}
Editar o texto de uma mensagem enviada (até 15 min) PATCH /messages/{message_id}
Apagar para todos (até 48 h) ou só no painel DELETE /messages/{message_id}
Reagir com um emoji POST /messages/{message_id}/reaction
Ler o histórico de uma conversa GET /contacts/{contact_id}/messages
{
"id": "8d66a526-230c-481a-86e5-be09b6bbb952",
"object": "message",
"contact_id": "3f1c2b9a-7d4e-4c55-8a0e-1b2c3d4e5f60",
"channel_id": "d781e759-4047-4c35-bfcd-eae8c666369a",
"direction": "outbound",
"type": "document",
"text": "Segue o boleto.",
"media": {
"url": "https://exemplo.com/boleto-1234.pdf",
"mime_type": "application/pdf",
"filename": "boleto-1234.pdf"
},
"status": "delivered",
"error": null,
"reply_to_id": null,
"reaction": null,
"sender_name": null,
"transcript": null,
"created_at": "2026-11-11T14:40:31Z",
"edited_at": null
}
Campo Tipo Descrição
id UUID ID da mensagem.
object string Sempre message.
contact_id UUID ou null Contato (conversa) da mensagem. Em grupos, é o id do grupo.
channel_id UUID ou null Canal por onde a mensagem passou.
direction string inbound (o contato mandou) ou outbound (a empresa mandou: equipe, IA, campanha, Agenda ou API).
type string Valores comuns: text, image, video, audio, document e sticker. Trate valores desconhecidos como mídia genérica.
text string ou null Texto ou legenda. Mídia sem legenda pode trazer um rótulo como “📷 Foto”. Mensagem apagada para todos vira “Mensagem apagada”.
media objeto ou null Arquivo anexado: url, mime_type e filename.
status string queued, sent, delivered, read ou failed.
error string ou null Motivo da falha quando status é failed.
reply_to_id UUID ou null Mensagem citada (quando é uma resposta).
reaction string ou null Reação enviada por nós a esta mensagem (ex.: 👍). Veja Reagir a uma mensagem.
sender_name string ou null Em grupos, quem mandou.
transcript string ou null Transcrição de áudio, quando houver.
created_at data Quando a mensagem foi criada.
edited_at data ou null Quando foi editada, se foi.

As mensagens enviadas (outbound) passam por:

queued → sent → delivered → read
↘ failed
Status Significado
queued Na fila para sair.
sent Saiu da TopTalking para o WhatsApp.
delivered Chegou no celular do contato.
read O contato leu (se ele não desativou a confirmação de leitura).
failed Não foi possível entregar; veja error.

Para acompanhar sem ficar consultando, use o webhook message.status_updated.

POST/v1/messages

Envia texto e/ou mídia pelo WhatsApp (ou responde no Chat do site, se a conversa for de lá). A mensagem aparece no chat do painel como qualquer outra. É o endpoint para avisos transacionais (pedido, boleto, lembrete) e para responder conversas.

Destino: informe to (telefone) ou contact_id. Se o telefone ainda não for contato, o contato é criado e a conversa aparece na caixa de entrada do painel. Para grupos, use o id do grupo em contact_id (veja Grupos).

Canal usado, nesta ordem:

  1. o channel_id enviado, se houver;
  2. o canal da conversa, se estiver conectado;
  3. o WhatsApp principal conectado.
Parâmetro Onde Tipo Obrigatório Descrição
to corpo string to ou contact_id Telefone com DDI e DDD. Formatação é ignorada; números brasileiros sem 55 recebem o 55.
contact_id corpo UUID to ou contact_id Conversa de destino. Também aceita o id de um grupo (veja GET /groups).
text corpo string text e/ou media Até 4096 caracteres. Aceita a formatação do WhatsApp: *negrito*, _itálico_, ~tachado~. Com media, vira a legenda.
media corpo objeto text e/ou media Arquivo a enviar (veja abaixo).
channel_id corpo UUID não Força o envio por este canal.
reply_to_id corpo UUID não Responde (cita) esta mensagem da conversa.
contact_name corpo string não Nome usado se o contato ainda não existir.
Idempotency-Key cabeçalho string não (recomendado) Impede que uma retentativa mande a mensagem duas vezes. Veja Idempotência.

Objeto media:

Campo Tipo Obrigatório Descrição
url string sim URL pública HTTPS do arquivo (acessível sem login).
type string sim image, video, audio ou document.
filename string não Nome exibido (documentos). Padrão: o nome na URL.
mime_type string não Tipo do arquivo (ex.: application/pdf). Padrão: deduzido pela extensão.
voice_note booleano não Com type: "audio", envia como nota de voz (sem legenda). Padrão: false.
Janela do terminal
# Texto para um telefone
curl https://platform.toptalking.com.br/v1/messages \
-H "Authorization: Bearer $TOPTALKING_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: pedido-1234-saiu" \
-d '{
"to": "5511999998888",
"text": "Olá, Maria! Seu pedido *#1234* saiu para entrega."
}'
# Documento com legenda para um contato existente
curl https://platform.toptalking.com.br/v1/messages \
-H "Authorization: Bearer $TOPTALKING_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: boleto-1234" \
-d '{
"contact_id": "3f1c2b9a-7d4e-4c55-8a0e-1b2c3d4e5f60",
"text": "Segue o boleto.",
"media": {
"url": "https://exemplo.com/boleto-1234.pdf",
"type": "document",
"filename": "boleto-1234.pdf"
}
}'

A mensagem criada:

{
"id": "03ab9a84-86b0-4a1c-a9b2-bbfa205cc52e",
"object": "message",
"contact_id": "3f1c2b9a-7d4e-4c55-8a0e-1b2c3d4e5f60",
"channel_id": "d781e759-4047-4c35-bfcd-eae8c666369a",
"direction": "outbound",
"type": "text",
"text": "Olá, Maria! Seu pedido *#1234* saiu para entrega.",
"media": null,
"status": "sent",
"error": null,
"reply_to_id": null,
"reaction": null,
"sender_name": null,
"transcript": null,
"created_at": "2026-11-11T14:30:12Z",
"edited_at": null
}
HTTP code Quando acontece
400 missing_field Faltou to/contact_id ou text/media.
400 invalid_phone Telefone em to inválido.
400 invalid_field Campo inválido: texto acima de 4096 caracteres, media.url sem HTTPS, media.type desconhecido…
403 read_only_key Chave somente leitura.
404 resource_not_found contact_id, channel_id ou reply_to_id não encontrado.
409 idempotency_conflict Idempotency-Key reutilizada com outro corpo.
422 channel_unavailable Nenhum WhatsApp conectado (ou o canal escolhido está desconectado). Reconecte o canal.
502 provider_error O WhatsApp recusou o envio. A mensagem fica registrada com status failed.
422 channel_unavailable
{
"error": {
"type": "channel_error",
"code": "channel_unavailable",
"message": "WhatsApp desconectado. Reconecte no painel.",
"request_id": "req_6f1d2c3b4a5e"
}
}

GET/v1/messages/{message_id}

Busca uma mensagem pelo ID. Use para conferir o status de entrega (sent → delivered → read) de um envio importante.

Parâmetro Onde Tipo Obrigatório Descrição
message_id caminho UUID sim ID da mensagem.
Janela do terminal
curl https://platform.toptalking.com.br/v1/messages/03ab9a84-86b0-4a1c-a9b2-bbfa205cc52e \
-H "Authorization: Bearer $TOPTALKING_API_KEY"
{
"id": "03ab9a84-86b0-4a1c-a9b2-bbfa205cc52e",
"object": "message",
"contact_id": "3f1c2b9a-7d4e-4c55-8a0e-1b2c3d4e5f60",
"channel_id": "d781e759-4047-4c35-bfcd-eae8c666369a",
"direction": "outbound",
"type": "text",
"text": "Olá, Maria! Seu pedido *#1234* saiu para entrega.",
"media": null,
"status": "read",
"error": null,
"reply_to_id": null,
"reaction": null,
"sender_name": null,
"transcript": null,
"created_at": "2026-11-11T14:30:12Z",
"edited_at": null
}
HTTP code Quando acontece
404 resource_not_found A mensagem não existe ou é de outra organização.

PATCH/v1/messages/{message_id}

Corrige o texto de uma mensagem de texto enviada pela empresa (outbound) em até 15 minutos depois do envio — o mesmo limite do WhatsApp. O contato vê a mensagem marcada como editada, e o texto novo aparece no painel.

Só mensagens de texto: mídias (inclusive legendas) não podem ser editadas. Mensagens recebidas (inbound) também não.

Parâmetro Onde Tipo Obrigatório Descrição
message_id caminho UUID sim ID da mensagem enviada.
text corpo string sim Novo texto (até 4096 caracteres).
Janela do terminal
curl -X PATCH https://platform.toptalking.com.br/v1/messages/03ab9a84-86b0-4a1c-a9b2-bbfa205cc52e \
-H "Authorization: Bearer $TOPTALKING_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "text": "Olá, Maria! Seu pedido *#1234* sai amanhã cedo." }'

A mensagem com o texto novo e edited_at preenchido:

{
"id": "03ab9a84-86b0-4a1c-a9b2-bbfa205cc52e",
"object": "message",
"contact_id": "3f1c2b9a-7d4e-4c55-8a0e-1b2c3d4e5f60",
"channel_id": "d781e759-4047-4c35-bfcd-eae8c666369a",
"direction": "outbound",
"type": "text",
"text": "Olá, Maria! Seu pedido *#1234* sai amanhã cedo.",
"media": null,
"status": "delivered",
"error": null,
"reply_to_id": null,
"reaction": null,
"sender_name": null,
"transcript": null,
"created_at": "2026-11-11T14:30:12Z",
"edited_at": "2026-11-11T14:38:05Z"
}
HTTP code Quando acontece
400 missing_field Faltou text.
400 invalid_field A mensagem é de mídia (não pode ser editada) ou o texto passou de 4096 caracteres.
403 read_only_key Chave somente leitura.
404 resource_not_found A mensagem não existe.
409 invalid_state A mensagem foi recebida (inbound) ou já passaram 15 minutos do envio.
422 channel_unavailable O WhatsApp da conversa está desconectado.
502 provider_error O WhatsApp recusou a edição.
409 invalid_state
{
"error": {
"type": "conflict_error",
"code": "invalid_state",
"message": "Só é possível editar mensagens enviadas há no máximo 15 minutos.",
"request_id": "req_6f1d2c3b4a5e"
}
}

DELETE/v1/messages/{message_id}

Apaga uma mensagem de um destes dois jeitos:

scope O que acontece Quando dá
everyone (padrão) Apaga para todos no WhatsApp. No painel e na API, o texto vira “Mensagem apagada”. Só mensagens enviadas (outbound), em até 48 horas.
me Só esconde a mensagem: ela some do painel e de GET /contacts/{contact_id}/messages. O contato continua vendo. Qualquer mensagem, a qualquer momento.

Mesmo escondida com scope=me, a mensagem continua acessível por GET /messages/{message_id}.

Parâmetro Onde Tipo Obrigatório Descrição
message_id caminho UUID sim ID da mensagem.
scope query string não everyone (padrão) ou me.
Janela do terminal
# Apagar para todos
curl -X DELETE https://platform.toptalking.com.br/v1/messages/0dd803ad-1be8-4d87-8cf8-3b3d0e94de93 \
-H "Authorization: Bearer $TOPTALKING_API_KEY"
# Só esconder do painel
curl -X DELETE "https://platform.toptalking.com.br/v1/messages/0dd803ad-1be8-4d87-8cf8-3b3d0e94de93?scope=me" \
-H "Authorization: Bearer $TOPTALKING_API_KEY"

A mensagem apagada (com scope=everyone):

{
"id": "0dd803ad-1be8-4d87-8cf8-3b3d0e94de93",
"object": "message",
"contact_id": "3f1c2b9a-7d4e-4c55-8a0e-1b2c3d4e5f60",
"channel_id": "d781e759-4047-4c35-bfcd-eae8c666369a",
"direction": "outbound",
"type": "text",
"text": "Mensagem apagada",
"media": null,
"status": "delivered",
"error": null,
"reply_to_id": null,
"reaction": null,
"sender_name": null,
"transcript": null,
"created_at": "2026-11-11T14:41:00Z",
"edited_at": null
}

Com scope=me, a resposta é a mensagem como estava (o texto não muda): ela só deixa de aparecer no painel e no histórico.

HTTP code Quando acontece
403 read_only_key Chave somente leitura.
404 resource_not_found A mensagem não existe.
409 invalid_state Com scope=everyone: a mensagem foi recebida (inbound) ou já passaram 48 horas. Use scope=me.
422 channel_unavailable Com scope=everyone: o WhatsApp da conversa está desconectado.
502 provider_error O WhatsApp recusou apagar a mensagem.
409 invalid_state
{
"error": {
"type": "conflict_error",
"code": "invalid_state",
"message": "Só é possível apagar para todos mensagens enviadas há no máximo 48 horas. Para esconder do painel, use scope=me.",
"request_id": "req_6f1d2c3b4a5e"
}
}

POST/v1/messages/{message_id}/reaction

Envia uma reação com emoji a uma mensagem da conversa — recebida ou enviada —, como o “segurar e reagir” do WhatsApp. Útil para confirmar que viu um pedido sem mandar uma mensagem nova. Enviar emoji vazio ("") remove a reação.

Não disponível para conversas do Chat do site (webchat).

Parâmetro Onde Tipo Obrigatório Descrição
message_id caminho UUID sim ID da mensagem que vai receber a reação.
emoji corpo string sim Um emoji (ex.: "👍"). "" remove a reação.
Janela do terminal
curl https://platform.toptalking.com.br/v1/messages/b7fa4c19-3e25-4ce9-9794-4e7f60efa4ba/reaction \
-H "Authorization: Bearer $TOPTALKING_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "emoji": "👍" }'

A mensagem com a reação em reaction:

{
"id": "b7fa4c19-3e25-4ce9-9794-4e7f60efa4ba",
"object": "message",
"contact_id": "3f1c2b9a-7d4e-4c55-8a0e-1b2c3d4e5f60",
"channel_id": "d781e759-4047-4c35-bfcd-eae8c666369a",
"direction": "inbound",
"type": "text",
"text": "Vocês entregam no sábado?",
"media": null,
"status": "delivered",
"error": null,
"reply_to_id": null,
"reaction": "👍",
"sender_name": null,
"transcript": null,
"created_at": "2026-11-11T14:12:40Z",
"edited_at": null
}
HTTP code Quando acontece
400 missing_field Faltou emoji.
400 invalid_field Mais de um emoji, ou a conversa é do Chat do site.
403 read_only_key Chave somente leitura.
404 resource_not_found A mensagem não existe.
409 invalid_state A mensagem ainda não tem identificador no WhatsApp (ex.: ainda está queued). Tente de novo em instantes.
422 channel_unavailable O WhatsApp da conversa está desconectado.
502 provider_error O WhatsApp recusou a reação.
400 invalid_field
{
"error": {
"type": "invalid_request_error",
"code": "invalid_field",
"message": "Reações não estão disponíveis no Chat do site.",
"request_id": "req_6f1d2c3b4a5e"
}
}