Enviar WhatsApp pela planilha do Google Sheets (Apps Script + API)
Envie WhatsApp a partir do Google Sheets com Apps Script e a API não oficial: coluna de status, espaçamento, tratamento de 429 e confirmação do Google Forms.
Dá para enviar WhatsApp direto do Google Sheets com o Apps Script, que já vem na planilha: cada linha vira uma chamada POST /{key}/message/text na API não oficial da WAME, feita com UrlFetchApp, e o script anota o resultado numa coluna de status. Com três cuidados — chave guardada fora da planilha, envio só para quem consentiu e parada quando a API responder 429 —, a planilha vira uma automação confiável para confirmações, lembretes e avisos.
Planilha é onde muita operação pequena vive: a lista de inscritos do evento, as consultas da semana, os pedidos do dia. Levar essa lista para o WhatsApp sem sair do Google Sheets resolve muita coisa sem precisar de servidor. Este tutorial monta o script completo, do primeiro envio ao gatilho do Google Forms.
A planilha
Crie uma aba chamada Envios com estas colunas:
| A | B | C | D | E | F |
|---|---|---|---|---|---|
| Nome | Telefone | Mensagem | Consentiu | Status | Enviado em |
| Ana | 5511999999999 | Sua consulta é amanhã às 14h. | SIM | ||
| Bruno | 5521988888888 | Seu pedido saiu para entrega. | SIM |
Algumas regras:
- Telefone no formato internacional, só dígitos: código do país, DDD e número. Formate a coluna como texto para o Sheets não transformar em notação científica.
- Consentiu é a trava de segurança. O script só envia nas linhas com
SIM. - Status e Enviado em são preenchidos pelo script. Linha com status já preenchido não é enviada de novo.
Guarde a chave fora da planilha
A key da instância autentica o envio. Se ela estiver numa célula, qualquer pessoa com acesso de leitura à planilha pode mandar mensagem pelo seu número. Guarde nas propriedades do script:
- Na planilha, abra Extensões > Apps Script.
- Em Configurações do projeto, na seção Propriedades do script, adicione
WAME_KEYcom a chave da sua instância.
No código, leia assim:
function chave() {
const key = PropertiesService.getScriptProperties().getProperty('WAME_KEY');
if (!key) throw new Error('Defina WAME_KEY nas propriedades do script.');
return key;
}Enviar uma mensagem
O envio é um POST com UrlFetchApp. O muteHttpExceptions faz o Apps Script devolver a resposta mesmo quando o status é erro, para você decidir o que fazer:
function enviarTexto(telefone, texto) {
const url = 'https://us.api-wa.me/' + chave() + '/message/text';
const resposta = UrlFetchApp.fetch(url, {
method: 'post',
contentType: 'application/json',
payload: JSON.stringify({ to: String(telefone), text: texto }),
muteHttpExceptions: true,
});
return {
codigo: resposta.getResponseCode(),
corpo: resposta.getContentText(),
};
}Teste com o seu próprio número antes de rodar na lista.
Percorrer a planilha com segurança
Agora o laço que lê as linhas, envia e anota. Ele pula o que já foi enviado, respeita o consentimento, espaça os envios e para se a API pedir:
const ABA = 'Envios';
const COL = { nome: 0, tel: 1, msg: 2, consentiu: 3, status: 4, quando: 5 };
const LIMITE_POR_EXECUCAO = 40;
function enviarPendentes() {
const aba = SpreadsheetApp.getActive().getSheetByName(ABA);
const dados = aba.getDataRange().getValues();
let enviados = 0;
for (let i = 1; i < dados.length; i++) {
const linha = dados[i];
const status = String(linha[COL.status]);
if (status && !status.startsWith('AGUARDANDO')) continue; // já tratado
if (String(linha[COL.consentiu]).toUpperCase() !== 'SIM') continue;
if (enviados >= LIMITE_POR_EXECUCAO) break; // continua na próxima execução
const texto = String(linha[COL.msg]).replace('{nome}', linha[COL.nome]);
const r = enviarTexto(linha[COL.tel], texto);
if (r.codigo === 429) {
// A API pediu calma: pare aqui e deixe o resto para depois.
aba.getRange(i + 1, COL.status + 1).setValue('AGUARDANDO (429)');
break;
}
const ok = r.codigo >= 200 && r.codigo < 300;
aba.getRange(i + 1, COL.status + 1).setValue(ok ? 'ENVIADO' : 'ERRO ' + r.codigo);
aba.getRange(i + 1, COL.quando + 1).setValue(new Date());
enviados++;
// Espaçamento entre envios, com variação.
Utilities.sleep(8000 + Math.floor(Math.random() * 7000));
}
}Por que cada detalhe está ali:
- Coluna de status como memória. Se o script parar no meio — erro, limite de tempo,
429—, a próxima execução continua de onde parou sem mandar duas vezes para ninguém. - Limite por execução. O Apps Script encerra execuções longas depois de alguns minutos. Processar um lote por vez e continuar num gatilho é mais seguro que tentar tudo de uma vez.
- Espaçamento com variação. Mensagens em intervalo fixo e curto têm cara de robô. Os valores acima são uma sugestão conservadora; ajuste ao seu caso, sempre sem pressa.
- Personalização. O
{nome}na coluna de mensagem vira o nome da pessoa. Texto idêntico para muita gente é um dos padrões que o anti-spam procura — e que a própria API freia.
A linha marcada como AGUARDANDO (429) não conta como tratada: a próxima execução tenta de novo exatamente a partir dela.
O que o 429 significa
A API não oficial da WAME tem freios contra padrões de disparo em massa. Ela responde 429 quando a instância fala com gente nova demais por minuto ou quando o mesmo texto vai para números demais em poucos minutos. É um sinal para desacelerar, não um erro para repetir em seguida.
Por isso o script para em vez de tentar de novo no mesmo instante. Insistir é exatamente o comportamento que transforma um freio em problema para o número. Se o 429 aparece com frequência, reveja a lista e o ritmo — os princípios estão em fila, rate limit e retry.
Rodar sozinho, de hora em hora
Para a planilha se esvaziar sem ninguém clicar, crie um gatilho de tempo. Rode esta função uma vez:
function criarGatilhoDeHora() {
ScriptApp.newTrigger('enviarPendentes')
.timeBased()
.everyHours(1)
.create();
}Cada execução processa um lote, e a próxima continua. Envios distribuídos ao longo do dia são mais naturais que uma rajada às 9h.
Confirmação automática do Google Forms
Um uso excelente — e totalmente dentro das regras — é confirmar a inscrição de quem acabou de preencher um formulário. A pessoa acabou de pedir; a mensagem é esperada.
- No Google Forms, vincule as respostas a uma planilha.
- No Apps Script dessa planilha, crie a função que trata cada resposta:
function aoEnviarFormulario(e) {
const valores = e.namedValues; // campos pelo título da pergunta
const nome = valores['Nome'][0];
const telefone = valores['WhatsApp'][0].replace(/\D/g, '');
const aceitou = valores['Aceito receber confirmação pelo WhatsApp'][0];
if (aceitou !== 'Sim') return;
const r = enviarTexto(
telefone,
'Oi, ' + nome + '! Recebemos sua inscrição. Qualquer dúvida, é só responder aqui.'
);
if (r.codigo !== 200 && r.codigo !== 201) console.log('Falha no envio', r.codigo, r.corpo);
}- Crie o gatilho instalável de envio de formulário, rodando uma vez:
function criarGatilhoDoFormulario() {
ScriptApp.newTrigger('aoEnviarFormulario')
.forSpreadsheet(SpreadsheetApp.getActive())
.onFormSubmit()
.create();
}Ajuste os títulos das perguntas no namedValues para bater com o seu formulário. A pergunta de consentimento é a mesma trava da coluna Consentiu: sem ela, não envia.
Se você quiser validar que o número digitado tem WhatsApp antes de mandar, veja como verificar se um número tem WhatsApp.
O que não fazer com a planilha
Planilha facilita enviar para muita gente — e é justamente aí que mora o risco. A WAME não apoia spam, e nenhuma camada técnica salva um número que manda para quem não pediu:
- Não importe lista comprada nem contatos que não conhecem sua empresa.
- Não remova a coluna de consentimento para "ganhar tempo".
- Não mande o mesmo texto para centenas de pessoas de uma vez; personalize e distribua.
- Ofereça uma saída. Se alguém pedir para parar, marque na planilha e nunca mais envie. O processo está em opt-in e opt-out automático.
Usada para confirmar, lembrar e avisar quem pediu, a planilha tem risco de bloqueio muito baixo — ainda mais porque cada envio da API já sai com tempo humano de digitação.
A camada não oficial da WAME não é afiliada, endossada ou suportada pelo WhatsApp ou pela Meta. O uso é de responsabilidade de quem envia.
Quando sair da planilha
A planilha é ótima até precisar receber e reagir: responder ao cliente, abrir um atendimento, atualizar um CRM. Aí você precisa de um endpoint de webhook, e um script de planilha não é o lugar certo. Os próximos passos naturais são um bot com a API não oficial ou um fluxo no n8n, como em bot de IA com n8n.
Conclusão
Com o Apps Script, o Google Sheets vira uma automação de WhatsApp sem servidor: UrlFetchApp chama a API não oficial, a coluna de status garante que ninguém recebe duas vezes e o gatilho de tempo esvazia a fila aos poucos. Guarde a chave nas propriedades do script, envie só para quem consentiu e pare quando a API responder 429. A referência dos endpoints está na documentação, e o panorama do que a camada não oficial oferece está em vantagens da API não oficial.
Pronto para automatizar seu WhatsApp?
Crie sua conta gratuita e comece a enviar mensagens pela API em minutos.
Começar grátisPerguntas frequentes
Dá para enviar WhatsApp direto do Google Sheets?+
Sim. Com o Apps Script, que já vem no Google Sheets, você chama a API não oficial da WAME com UrlFetchApp. Cada linha vira um POST em /{key}/message/text, e o script anota o resultado numa coluna de status.
Onde guardo a chave da API no Apps Script?+
Nas propriedades do script, com PropertiesService. Nunca numa célula da planilha: qualquer pessoa com acesso de leitura veria a chave e poderia enviar mensagens pelo seu número.
O que fazer quando a API responde 429?+
Parar o envio e retomar mais tarde. O 429 indica que a instância está falando com gente nova demais por minuto ou repetindo o mesmo texto para muitos números. O script deve encerrar a execução, deixar as linhas pendentes como estão e continuar num gatilho posterior.
Posso usar a planilha para mandar mensagem para uma lista de contatos?+
Só para quem pediu para receber. A planilha deve ter uma coluna de consentimento, e o script só envia nas linhas marcadas. Lista comprada ou contatos que não conhecem sua empresa geram denúncia e derrubam o número; a WAME não apoia esse uso.
Como mandar confirmação automática quando alguém responde um Google Forms?+
Vincule o formulário à planilha e crie um gatilho instalável de envio de formulário no Apps Script. A cada resposta, o script lê o nome e o telefone da nova linha e envia a confirmação pela API.
Continue lendo
Agente de voz no WhatsApp: latência, interrupção (barge-in) e silêncio
Como deixar um agente de voz no WhatsApp natural: latência, streaming, detecção de fala, interrupção (barge-in), silêncio e eco, com exemplos em Node.js.
Anti-detecção na API não oficial do WhatsApp: como a WAME protege seu número
Como funciona a camada de anti-detecção da API não oficial da WAME: identidade de dispositivo, tempo humano, ritmo de envio, reconexão e monitor de saúde.
API do WhatsApp em C# (.NET): enviar mensagens e receber webhook
Tutorial de API do WhatsApp em C# e .NET: HttpClient tipado, envio de texto, imagem e lista, webhook em ASP.NET Core com fila em background e tratamento de 429.