# 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`

```json
{
  "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.

```json
{
  "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`).

```json
{
  "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.

```json
{
  "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
```json
{
  "number": "5511999999999",
  "text": "Confira: https://exemplo.com",
  "linkPreview": true
}
```

### Preview Personalizado
```json
{
  "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

```json
[
  {
    "token": []
  }
]
```

```json
{
  "token": {
    "name": "token",
    "type": "apiKey",
    "in": "header"
  }
}
```

## Corpo da requisição

```json
{
  "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

```json
{
  "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

```json
{
  "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."
    }
  }
}
```

## Guias relacionados

[Autenticação](/docs/authentication) · [Erros e retries](/docs/errors-and-retries) · [Server URL](/docs/server-url)
