Enviar mensagem de texto
POST /send/text
Envia uma mensagem de texto para um contato, grupo ou canal/newsletter.
Recursos Específicos
- Preview de links com suporte a personalização automática ou customizada
- Formatação básica do texto
- Substituição automática de placeholders dinâmicos
Envio para Newsletter
Para enviar texto para um canal, use o mesmo campo number, mas informe o JID completo do canal:
- Exemplo:
120363123456789012@newsletter
{
"number": "120363123456789012@newsletter",
"text": "Post publicado no canal"
}
Responder enquete, lista ou botão
Use este mesmo endpoint para responder uma mensagem interativa que esteja salva no histórico local da instância. Envie:
number: chat onde a mensagem original foi recebida ou enviada;replyid: ID da mensagem interativa original;text: seleção iniciada por>.
O marcador > é obrigatório para gerar uma resposta interativa. Sem ele,
a API envia apenas uma mensagem de texto citando a original.
Responder uma enquete
Use a posição da opção, começando em 1. Nesta documentação pública, responda somente uma opção por requisição.
{
"number": "5511999999999",
"replyid": "3EB0ID_DA_ENQUETE",
"text": ">1"
}
Responder uma lista
Prefira o rowId configurado ao criar a lista. Também são aceitos o texto
exato do item ou sua posição (>1).
{
"number": "5511999999999",
"replyid": "3EB0ID_DA_LISTA",
"text": ">plano_pro"
}
Responder um botão
Prefira o ID do botão de resposta rápida. Também são aceitos o texto exato
exibido ou sua posição (>1). Isso vale para botões rápidos legados,
templates, native flow e carrossel. Botões de URL, ligação ou cópia executam
a própria ação e não são respondidos por este fluxo.
{
"number": "5511999999999",
"replyid": "3EB0ID_DOS_BOTOES",
"text": ">confirmar"
}
A API devolve erro quando a mensagem original não está disponível ou a opção informada não existe.
Campos Comuns
Este endpoint suporta todos os campos opcionais comuns documentados na tag "Enviar Mensagem", incluindo:
delay, readchat, readmessages, replyid, mentions, forward, track_source, track_id, placeholders e envio para grupos.
Preview de Links
Preview Automático
{
"number": "5511999999999",
"text": "Confira: https://exemplo.com",
"linkPreview": true
}
Preview Personalizado
{
"number": "5511999999999",
"text": "Confira nosso site! https://exemplo.com",
"linkPreview": true,
"linkPreviewTitle": "Título Personalizado",
"linkPreviewDescription": "Uma descrição personalizada do link",
"linkPreviewImage": "https://exemplo.com/imagem.jpg",
"linkPreviewLarge": true
}
Autenticação
[
{
"token": []
}
]
{
"token": {
"name": "token",
"type": "apiKey",
"in": "header"
}
}
Corpo da requisição
{
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"number": {
"type": "string",
"description": "ID do chat para o qual a mensagem será enviada. Pode ser um número de telefone em formato internacional, um ID de grupo (`@g.us`), um ID de usuário (com `@s.whatsapp.net` ou `@lid`) ou um ID de canal/newsletter (`@newsletter`).",
"example": "5511999999999"
},
"text": {
"type": "string",
"description": "Texto da mensagem. Para responder enquete, lista ou botão, use uma seleção iniciada por `>` junto com `replyid`. Aceita placeholders em mensagens de texto comuns.",
"example": "Olá {{name}}! Como posso ajudar?"
},
"linkPreview": {
"type": "boolean",
"description": "Ativa/desativa preview de links. Se true, procura automaticamente um link no texto para gerar preview.\n\nComportamento:\n- Se apenas linkPreview=true: gera preview automático do primeiro link encontrado no texto\n- Se fornecidos campos personalizados (title, description, image): usa os valores fornecidos\n- Se campos personalizados parciais: combina com dados automáticos do link como fallback\n- Título ou descrição só com espaço: o preview sai sem esse campo, sem buscar no link\n",
"example": true
},
"linkPreviewTitle": {
"type": "string",
"description": "Define um título personalizado para o preview do link. Vazio usa o título do link; só com espaço (`\" \"`), o preview sai sem título.",
"example": "Título Personalizado"
},
"linkPreviewDescription": {
"type": "string",
"description": "Define uma descrição personalizada para o preview do link. Vazia usa a descrição do link; só com espaço (`\" \"`), o preview sai sem descrição.",
"example": "Descrição personalizada do link"
},
"linkPreviewImage": {
"type": "string",
"description": "URL ou Base64 da imagem para usar no preview do link",
"example": "https://exemplo.com/imagem.jpg"
},
"linkPreviewLarge": {
"type": "boolean",
"description": "Se true, gera um preview grande com upload da imagem. Se false, gera um preview pequeno sem upload",
"example": true
},
"replyid": {
"type": "string",
"description": "ID da mensagem original. Com `text` iniciado por `>`, gera a resposta nativa de enquete, lista ou botão quando o tipo original for suportado.",
"example": "3EB0538DA65A59F6D8A251"
},
"mentions": {
"type": "string",
"description": "Números para mencionar, separados por vírgula (só em grupos). Para mencionar todos, use all ou inclua @all ou @todos no texto da mensagem",
"example": "5511999999999,5511888888888"
},
"readchat": {
"type": "boolean",
"description": "Marca conversa como lida após envio",
"example": true
},
"readmessages": {
"type": "boolean",
"description": "Marca últimas mensagens recebidas como lidas",
"example": true
},
"delay": {
"type": "integer",
"description": "Atraso em milissegundos antes do envio, durante o atraso aparecerá 'Digitando...'",
"example": 1000
},
"forward": {
"type": "boolean",
"description": "Marca a mensagem como encaminhada no WhatsApp",
"example": true
},
"track_source": {
"type": "string",
"description": "Origem do rastreamento da mensagem",
"example": "chatwoot"
},
"track_id": {
"type": "string",
"description": "ID para rastreamento da mensagem (aceita valores duplicados)",
"example": "msg_123456789"
},
"async": {
"type": "boolean",
"description": "Se true, envia a mensagem de forma assíncrona via fila interna. Útil para alto volume de mensagens.",
"example": false
}
},
"required": [
"number",
"text"
]
},
"examples": {
"basic": {
"summary": "Mensagem básica",
"description": "Exemplo mais simples possível",
"value": {
"number": "5511999999999",
"text": "Olá! Como posso ajudar?"
}
},
"withLinkPreview": {
"summary": "Com preview automático",
"description": "Preview automático de link no texto",
"value": {
"number": "5511999999999",
"text": "Confira: https://exemplo.com",
"linkPreview": true
}
},
"customLinkPreview": {
"summary": "Preview personalizado",
"description": "Preview com título, descrição e imagem customizados",
"value": {
"number": "5511999999999",
"text": "Confira nosso site! https://exemplo.com",
"linkPreview": true,
"linkPreviewTitle": "Título Personalizado",
"linkPreviewDescription": "Uma descrição personalizada do link",
"linkPreviewImage": "https://exemplo.com/imagem.jpg",
"linkPreviewLarge": true
}
},
"withPlaceholders": {
"summary": "Com placeholders",
"description": "Texto com placeholders nativos e um campo personalizado",
"value": {
"number": "5511999999999",
"text": "Olá {{first_name}}! Empresa: {{lead_field01}}. Seu email {{lead_email}} está correto?"
}
},
"newsletter": {
"summary": "Envio para newsletter",
"description": "Publica uma mensagem de texto em um canal usando o JID completo `@newsletter`.",
"value": {
"number": "120363123456789012@newsletter",
"text": "Post publicado no canal"
}
},
"pollReply": {
"summary": "Responder enquete",
"description": "Seleciona a opção 1 da enquete identificada por replyid.",
"value": {
"number": "5511999999999",
"replyid": "3EB0ID_DA_ENQUETE",
"text": ">1"
}
},
"listReply": {
"summary": "Responder lista",
"description": "Seleciona pelo rowId configurado no item da lista.",
"value": {
"number": "5511999999999",
"replyid": "3EB0ID_DA_LISTA",
"text": ">plano_pro"
}
},
"buttonReply": {
"summary": "Responder botão",
"description": "Seleciona pelo ID configurado no botão de resposta rápida.",
"value": {
"number": "5511999999999",
"replyid": "3EB0ID_DOS_BOTOES",
"text": ">confirmar"
}
}
}
}
}
}
Respostas
{
"200": {
"description": "Mensagem enviada com sucesso",
"content": {
"application/json": {
"schema": {
"allOf": [
{
"$ref": "#/components/schemas/Message"
},
{
"type": "object",
"properties": {
"response": {
"type": "object",
"properties": {
"status": {
"type": "string",
"example": "success"
},
"message": {
"type": "string",
"example": "Message sent successfully"
}
}
}
}
}
]
}
}
}
},
"400": {
"description": "Requisição inválida",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string",
"example": "Missing number or text"
}
}
}
}
}
},
"401": {
"description": "Não autorizado",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string",
"example": "Invalid token"
}
}
}
}
}
},
"429": {
"description": "Limite de requisições excedido",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string",
"example": "Rate limit exceeded"
}
}
}
}
}
},
"500": {
"description": "Erro interno do servidor",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string",
"example": "WhatsApp server error 463: WhatsApp reported that the currently connected account is under a temporary restriction for starting new conversations, usually related to sending volume or quality."
},
"error_source": {
"type": "string",
"example": "whatsapp_server"
},
"provider": {
"type": "string",
"example": "whatsapp"
},
"provider_code": {
"type": "integer",
"example": 463
},
"error_key": {
"type": "string",
"example": "WHATSAPP_REACHOUT_TIMELOCK"
},
"message": {
"type": "string",
"example": "The WhatsApp server rejected this message. This was not an internal API error."
},
"message_ptbr": {
"type": "string",
"example": "O servidor do WhatsApp recusou esta mensagem. Isso não foi um erro interno da API."
},
"provider_message": {
"type": "string",
"example": "WhatsApp reported that the currently connected account is under a temporary restriction for starting new conversations, usually related to sending volume or quality."
},
"provider_message_ptbr": {
"type": "string",
"example": "O WhatsApp informou que a conta atualmente conectada está sob uma restrição temporária para iniciar novas conversas, normalmente relacionada a volume ou qualidade de envios."
},
"diagnostics_endpoint": {
"type": "string",
"example": "/instance/wa_messages_limits"
},
"details": {
"type": "object",
"properties": {
"new_chat_message_capping": {
"type": "object",
"additionalProperties": true
},
"reachout_timelock": {
"type": "object",
"additionalProperties": true
}
}
}
}
},
"examples": {
"generic": {
"summary": "Erro interno genérico",
"value": {
"error": "Failed to send message"
}
},
"whatsapp_463": {
"summary": "Erro do WhatsApp ao iniciar novas conversas",
"value": {
"error": "WhatsApp server error 463: WhatsApp reported that the currently connected account is under a temporary restriction for starting new conversations, usually related to sending volume or quality.",
"error_source": "whatsapp_server",
"provider": "whatsapp",
"provider_code": 463,
"error_key": "WHATSAPP_REACHOUT_TIMELOCK",
"message": "The WhatsApp server rejected this message. This was not an internal API error.",
"message_ptbr": "O servidor do WhatsApp recusou esta mensagem. Isso não foi um erro interno da API.",
"provider_message": "WhatsApp reported that the currently connected account is under a temporary restriction for starting new conversations, usually related to sending volume or quality.",
"provider_message_ptbr": "O WhatsApp informou que a conta atualmente conectada está sob uma restrição temporária para iniciar novas conversas, normalmente relacionada a volume ou qualidade de envios.",
"diagnostics_endpoint": "/instance/wa_messages_limits",
"details": {
"new_chat_message_capping": {
"available": true,
"status": "CAPPED",
"used_quota": 10,
"total_quota": 10
},
"reachout_timelock": {
"available": true,
"active": true,
"until": "2026-04-07T12:00:00Z",
"enforcement_type": "BIZ_QUALITY"
}
}
}
}
}
}
}
}
}
#/components/schemas/Message
{
"type": "object",
"description": "Representa uma mensagem trocada no sistema",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"description": "ID único interno da mensagem (formato r + 7 caracteres hex aleatórios)"
},
"messageid": {
"type": "string",
"description": "ID original da mensagem no provedor"
},
"chatid": {
"type": "string",
"description": "ID da conversa relacionada"
},
"sender": {
"type": "string",
"description": "ID do remetente da mensagem"
},
"senderName": {
"type": "string",
"description": "Nome exibido do remetente"
},
"isGroup": {
"type": "boolean",
"description": "Indica se é uma mensagem de grupo",
"default": false
},
"fromMe": {
"type": "boolean",
"description": "Indica se a mensagem foi enviada pelo usuário",
"default": false
},
"messageType": {
"type": "string",
"description": "Tipo de conteúdo da mensagem"
},
"source": {
"type": "string",
"description": "Plataforma de origem da mensagem"
},
"messageTimestamp": {
"type": "integer",
"description": "Timestamp original da mensagem em milissegundos",
"default": 0
},
"status": {
"type": "string",
"description": "Status do ciclo de vida da mensagem.\nExemplos comuns: `Queued`, `Canceled`, `Failed`, `Sent`, `Delivered`, `Read`.\nEm mensagem de grupo, segue o participante mais adiantado: `Delivered` quando pelo menos um recebeu, `Read` quando pelo menos um leu e `Played` quando pelo menos um ouviu.\n"
},
"text": {
"type": "string",
"description": "Texto original da mensagem",
"default": ""
},
"quoted": {
"type": "string",
"description": "ID da mensagem citada/respondida",
"default": ""
},
"edited": {
"type": "string",
"description": "Histórico de edições da mensagem",
"default": ""
},
"reaction": {
"type": "string",
"description": "ID da mensagem reagida",
"default": ""
},
"vote": {
"type": "string",
"description": "Dados de votação de enquete e listas",
"default": ""
},
"convertOptions": {
"type": "string",
"description": "Conversão de opções da mensagem, lista, enquete e botões",
"default": ""
},
"buttonOrListid": {
"type": "string",
"description": "ID do botão ou item de lista selecionado",
"default": ""
},
"owner": {
"type": "string",
"description": "Dono da mensagem",
"default": ""
},
"error": {
"type": "string",
"description": "Mensagem de erro caso o envio tenha falhado",
"default": ""
},
"content": {
"description": "Conteúdo bruto da mensagem (JSON serializado ou texto)",
"oneOf": [
{
"type": "object",
"additionalProperties": true
},
{
"type": "string",
"description": "Texto bruto quando não for JSON"
}
]
},
"wasSentByApi": {
"type": "boolean",
"description": "Indica se a mensagem foi enviada via API"
},
"pinned": {
"type": "boolean",
"description": "Mensagem fixada na conversa (fixar e desafixar chegam também em `messages_update`, tipos `Pinned` e `Unpinned`)"
},
"sendFunction": {
"type": "string",
"description": "Função usada para enviar a mensagem (quando enviada via API)"
},
"sendPayload": {
"description": "Payload usado no envio quando disponível. Dados de mídia em base64 são omitidos.",
"oneOf": [
{
"type": "object",
"additionalProperties": true
},
{
"type": "string",
"description": "Texto bruto quando não for JSON"
}
]
},
"fileURL": {
"type": "string",
"description": "URL ou referência de arquivo da mensagem"
},
"callPeer": {
"type": "object",
"description": "Contato conhecido associado a uma ligação, quando disponível em `messageType: call`.",
"properties": {
"jid": {
"type": "string"
},
"name": {
"type": "string"
},
"imagePreviewUrl": {
"type": "string"
}
}
},
"send_folder_id": {
"type": "string",
"description": "Pasta associada ao envio (quando aplicável)"
},
"track_source": {
"type": "string",
"description": "Origem de rastreamento"
},
"track_id": {
"type": "string",
"description": "ID de rastreamento (pode repetir)"
},
"ai_metadata": {
"type": "object",
"description": "Registro de uma rodada da IA. O completo (pedido ao modelo, resposta e `outcome`) fica uma vez, na última mensagem do contato que a rodada respondeu, também quando nada saiu (erro, resposta descartada). Cada mensagem enviada pela IA leva só `agent_id` e `turn` (o `id` dessa mensagem do contato).",
"properties": {
"agent_id": {
"type": "string",
"description": "ID do agente de IA responsável"
},
"turn": {
"type": "string",
"description": "Na mensagem enviada pela IA: o `id` da mensagem do contato onde está o registro completo da rodada."
},
"flow_id": {
"type": "string",
"description": "Mensagem enviada por um fluxo: o `id` do fluxo. A mensagem enviada pela IA traz o `agent_id`."
},
"request": {
"type": "object",
"description": "Dados da requisição à API de IA",
"properties": {
"messages": {
"type": "array",
"description": "Histórico de mensagens enviadas para a API"
},
"tools": {
"type": "array",
"description": "Ferramentas disponíveis para o agente"
},
"options": {
"type": "object",
"description": "Opções de configuração da API",
"properties": {
"model": {
"type": "string"
},
"temperature": {
"type": "number"
},
"maxTokens": {
"type": "integer"
},
"topP": {
"type": "number"
},
"frequencyPenalty": {
"type": "number"
},
"presencePenalty": {
"type": "number"
}
}
}
}
},
"response": {
"type": "object",
"description": "Resposta da API de IA",
"properties": {
"choices": {
"type": "array",
"description": "Resultados retornados pela API"
},
"toolResults": {
"type": "array",
"description": "Resultados da execução de ferramentas"
},
"error": {
"type": "string",
"description": "Mensagem de erro, se houver"
}
}
},
"outcome": {
"type": "object",
"description": "O que a rodada fez de fato (só no registro completo).",
"properties": {
"status": {
"type": "string",
"enum": [
"sent",
"cancelled",
"error",
"empty"
],
"description": "`sent`: enviou algo; `cancelled`: descartada (a conversa pausou, um fluxo começou ou bateu o limite de respostas por hora); `error`: o provedor falhou; `empty`: nada a enviar."
},
"texts": {
"type": "integer",
"description": "Mensagens de texto enviadas."
},
"audio": {
"type": "boolean",
"description": "Respondeu em áudio."
},
"menus": {
"type": "integer",
"description": "Menus enviados."
},
"files": {
"type": "integer",
"description": "Arquivos (mensagens cadastradas) enviados."
},
"handoff": {
"type": "string",
"description": "`chamar_humano`: o resumo para quem atender."
},
"lead": {
"type": "array",
"items": {
"type": "string"
},
"description": "`atualizar_lead`: o que foi gravado no CRM (`lead_email = ana@exemplo.com; column = Agendado`)."
},
"detail": {
"type": "string",
"description": "Por que foi descartada, ou o erro."
}
}
}
}
},
"sender_pn": {
"description": "JID PN resolvido do remetente (quando disponível)",
"oneOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"sender_lid": {
"description": "LID original do remetente (quando disponível)",
"oneOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"sender_image_preview_url": {
"type": "string",
"format": "uri",
"description": "URL temporária de preview do remetente, quando conhecida. A hidratação desta versão preenche mensagens recebidas em grupos; o campo pode ser omitido. Não provoca consulta de foto ao WhatsApp na listagem."
}
}
}