Lembrete de consulta no WhatsApp pela API: rotina, confirmação e LGPD
Falta de paciente é horário perdido. O lembrete 24 horas antes, com resposta 1 para confirmar e 2 para remarcar, é a automação de menor esforço para reduzir faltas. Esta receita monta isso a partir da agenda do seu próprio sistema, sem depender de plataforma de terceiros, e cuida do que costuma dar errado: envio em dobro, mensagem fora de hora e dado sensível na conversa.
Publicado em · 4 min de leitura
De onde vêm os horários
A fonte da verdade é a sua agenda: um banco com a tabela de consultas, um ERP ou o Google Agenda (veja a integração com Google Calendar). Esta receita assume uma tabela appointments com status, horário, nome, telefone, um campo consent_whatsapp (o paciente concordou em receber lembretes) e reminder_sent_at (nulo até o envio). Se a sua agenda for um SaaS fechado, o caminho costuma ser um webhook ou uma exportação; confira o que ele oferece antes de prometer o lembrete.
O campo de consentimento não é enfeite. Dado de agendamento de saúde é dado pessoal, e quase sempre sensível pelo contexto. Colete o consentimento no cadastro ou na marcação ('posso lembrar você da consulta por WhatsApp?') e consulte o campo no filtro do envio.
A rotina: janela, trava e intervalo
A rotina roda a cada 15 minutos e busca consultas confirmadas que começam entre 23 e 24 horas à frente, ainda sem lembrete e com consentimento. A janela de uma hora, somada ao filtro reminder_sent_at, faz cada consulta ser pega uma vez só. Antes de enviar, a rotina 'reivindica' a linha com um UPDATE condicional: se duas execuções se sobrepõem, só uma consegue marcar o envio. Se o envio falhar, a marca é desfeita para a próxima execução tentar de novo.
O intervalo aleatório de alguns segundos entre mensagens evita rajada. Para lembretes de uma clínica, o volume é baixo, mas o princípio vale: um ritmo humano reduz risco. O envio usa POST /api/v1/{instanceId}/send/text com number e text, e a ZapZap ainda aplica atraso e o indicador de digitando por padrão (anti-bloqueio). Verifique antes se o número tem WhatsApp com a rota chat/check, descrita na referência.
Node.js (cron a cada 15 minutos)
// Runs every 15 minutes (cron, queue worker or n8n schedule). Appointments come from YOUR system.
async function remindAppointments() {
const rows = await db.query(`
SELECT id, patient_name, patient_phone, starts_at
FROM appointments
WHERE status = 'confirmed' AND reminder_sent_at IS NULL AND consent_whatsapp = TRUE
AND starts_at BETWEEN now() + interval '23 hours' AND now() + interval '24 hours'`);
for (const a of rows.rows) {
// claim before sending: a second run cannot pick the same row
const claim = await db.query("UPDATE appointments SET reminder_sent_at = now() WHERE id = $1 AND reminder_sent_at IS NULL", [a.id]);
if (!claim.rowCount) continue;
const when = new Date(a.starts_at).toLocaleString("pt-BR", { dateStyle: "short", timeStyle: "short", timeZone: "America/Sao_Paulo" });
try {
await sendWhatsApp(a.patient_phone, "Oi, " + a.patient_name.split(" ")[0] + ". Lembrete da sua consulta amanhã, " + when + ". Responda 1 para confirmar ou 2 para remarcar.");
} catch (e) {
await db.query("UPDATE appointments SET reminder_sent_at = NULL WHERE id = $1", [a.id]); // let the next run retry
console.error("reminder failed", a.id, e.message);
}
await new Promise((r) => setTimeout(r, 4000 + Math.random() * 6000)); // human-like gap between sends
}
}
// Shared helper: one send through the ZapZap API
async function sendWhatsApp(number, text) {
const r = await fetch(`https://api.zapzapapi.com/api/v1/${process.env.ZAPZAP_INSTANCE}/send/text`, {
method: "POST",
headers: {
"x-api-key": process.env.ZAPZAP_API_KEY,
"x-api-secret": process.env.ZAPZAP_API_SECRET,
"Content-Type": "application/json",
},
body: JSON.stringify({ number, text }),
});
if (!r.ok) throw new Error("ZapZap " + r.status + ": " + (await r.text()));
}Receber o 1 ou o 2
Para a resposta funcionar, a instância precisa entregar as mensagens recebidas ao seu servidor: registre a URL com PUT /api/v1/instances/{id}/webhook e o evento de mensagens (configurar webhook). Descarte as mensagens fromMe, ou a sua própria resposta automática pode reentrar no fluxo e criar um loop. Confira o formato exato do payload com uma mensagem real antes de escrever o código; o exemplo abaixo mostra só a lógica.
Trate respostas fora do esperado com cuidado: 'ok', 'sim' e 'confirmo' também são confirmações. Mapeie algumas variações e, se não entender, não responda sozinho: encaminhe para a recepção. Para validar o cabeçalho X-ZapZap-Signature e descartar entregas repetidas, siga o guia de webhooks em produção.
Node.js (Express)
// Receive the patient's "1" or "2" (message webhook registered with PUT /api/v1/instances/{id}/webhook, event "messages")
app.post("/zapzap", express.json(), async (req, res) => {
res.sendStatus(200);
const m = req.body; // check the exact shape with a real message first (see the webhooks reference)
if (m.fromMe) return; // never react to your own messages, or an automatic reply answers itself in a loop
const text = String(m.text || "").trim();
if (text === "1") await markConfirmed(m.from);
else if (text === "2") await askReschedule(m.from);
});O texto: o que dizer e o que NÃO dizer
Diga o essencial: o nome do paciente, o dia e a hora, o nome da clínica e como confirmar ou remarcar. Não escreva o procedimento, o nome do médico em especialidade sensível, o resultado de exame nem o diagnóstico. O WhatsApp é um canal em que o aparelho pode estar com outra pessoa, e dado de saúde numa notificação é um vazamento esperando acontecer. 'Consulta com a Dra. Ana, amanhã às 14h' é suficiente.
Se a clínica tem exigência do conselho profissional sobre comunicação com paciente, siga a norma do seu conselho. Esta receita é técnica e não substitui orientação jurídica ou ética.
Limites e riscos
Lembrete de consulta para quem agendou com você é o uso de menor risco que existe. Mesmo assim, a ZapZap conecta números por um canal não oficial e gerenciado, e nenhum recurso garante ausência de bloqueio. Mantenha o ritmo, não envie para quem pediu para parar e não aproveite o lembrete para divulgar promoção.
Teste primeiro com consultas fictícias e com o seu número. Confira o fuso (o exemplo usa America/Sao_Paulo), a janela de 23 a 24 horas e, principalmente, que rodar a rotina duas vezes seguidas não gera segunda mensagem. Para segmentos específicos, veja as páginas de clínicas e dentistas.
Resumo rápido
- Rotina a cada 15 minutos, janela de 23 a 24 horas e UPDATE condicional para nunca enviar duas vezes.
- Consentimento no cadastro e campo consultado no filtro do envio: dado de saúde pede cuidado.
- Mensagem sem procedimento nem diagnóstico; resposta 1 ou 2 por webhook, ignorando fromMe.
- Teste a idempotência rodando a rotina duas vezes e conferindo que sai uma mensagem só.
Continue lendo
Perguntas frequentes
Qual o melhor momento para lembrar o paciente?
Um lembrete 24 horas antes costuma dar tempo de remarcar. Alguns negócios adicionam um segundo, poucas horas antes. Teste com a sua agenda; a receita usa a janela de 23 a 24 horas.
Preciso de consentimento para lembrar de consulta?
Dado de agendamento de saúde é dado pessoal e costuma ser sensível. Colete o consentimento no cadastro ou na marcação, registre e consulte antes de cada envio. Em caso de dúvida, consulte a sua assessoria jurídica.
Como evito mandar o lembrete duas vezes?
Com um campo de controle e um UPDATE condicional que reivindica a linha antes do envio. Se duas execuções se sobrepuserem, só uma consegue marcar. Em falha de envio, desfaça a marca para tentar de novo.
Posso mencionar o procedimento na mensagem?
Não recomendamos. O aparelho pode estar com outra pessoa, e dado de saúde em notificação vaza fácil. Use nome, dia, hora, clínica e como confirmar ou remarcar.
Como recebo a resposta do paciente?
Registre a URL do seu servidor como webhook da instância com o evento de mensagens, ignore as mensagens fromMe e trate 1 e 2. Confira o formato do payload com uma mensagem real antes de codar.
Isso pode bloquear o número da clínica?
Pode. A ZapZap usa um canal não oficial e nenhum recurso elimina o risco. Lembrete para quem agendou, com ritmo humano e saída para parar, é o uso de menor risco, mas não é risco zero.
Reduza faltas com um lembrete simples
Conecte o número da clínica e rode a rotina da receita. R$15 por número ativo ao mês, com crédito de boas-vindas sujeito à campanha vigente.
