API de disparos no WhatsApp e no Telegram

API de disparos no WhatsApp e no Telegram: conecte contas, crie disparos e receba os status direto do seu CRM ou do seu site.

API de disparos em mensageiros do WSENDER
API de disparos: as mensagens saem do seu sistema

Mensagem pra cliente quase nunca é coisa pra "quando der tempo". Ela tem hora certa, a hora do evento: pagou o pedido, marcou um horário, faltou, sumiu há um mês. O evento já aconteceu no seu sistema, e entrar no painel depois disso pra montar um disparo à mão não faz muito sentido.

É pra isso que existe a API pública. Dá pra fazer o disparo inteiro por ela: montagem do público, verificação do texto, ritmo seguro, status de cada destinatário e a resposta dele. Fila, pausas entre mensagens, novas tentativas e proteção do número contra bloqueio você não precisa construir: disso o serviço cuida, e no seu sistema fica uma chamada só.

E o conjunto de métodos é um só pra tudo: contas de WhatsApp e Telegram e bots do Telegram. Pra adicionar outro mensageiro, não precisa escrever uma integração nova: basta mudar um valor na mesma requisição.

O que a API de disparos faz no WhatsApp e no Telegram

Tudo o que você faz à mão no painel está disponível por HTTP:

  • Conexão de mensageiros e bots. Em uma requisição: a conta de mensageiro se conecta por QR code ou pelo número de telefone, e o bot, pelo token. O serviço avisa sozinho como terminou a conexão. Se a conta tem senha de verificação em duas etapas, a senha também é passada pela API.
  • Público. Criar um segmento e carregar números de telefone, até 100 números por requisição; uma lista maior vai em várias requisições. Números que o projeto já conhece não são duplicados.
  • Disparos. Criar, adicionar texto ou mídia (imagem, vídeo, áudio, documento, até dez mensagens por disparo) e escolher os destinatários: um segmento de contatos, a agenda da conta ou conversas que já existem. Depois vêm a verificação do texto, o início, a pausa e o cancelamento.
  • Edição do rascunho. Enquanto o disparo não começou, pela própria API dá pra mudar o texto e os arquivos das mensagens, apagar as mensagens desnecessárias e renomear o disparo. Editar o texto zera a verificação já feita: pra iniciar, o disparo passa pela moderação de novo.
  • Resultado por destinatário. Enviada, entregue, lida, respondida, número que não está no mensageiro.
  • Respostas dos destinatários. Não só o fato de que a pessoa respondeu, mas também o texto: o que exatamente ela escreveu em resposta ao disparo.
  • Envio de mensagem individual. Pros casos transacionais existe um método à parte: texto e anexo próprios em cada requisição, sem montar um disparo pra um número só.
  • A conversa inteira. O histórico da conversa com a pessoa, com mensagens recebidas e enviadas no mesmo fluxo. O serviço manda um evento a cada mensagem nova recebida, e dá pra responder pelo mesmo método de envio individual, inclusive citando a mensagem certa. Nos bots, a mensagem recebida chega na hora; nas contas de mensageiro, a conversa vem pela sincronização, ou seja, com atraso. Nos dois casos é preciso um plano com análise de respostas; falamos disso mais abaixo.
  • Webhooks. A conta conectou ou desconectou, o mensageiro restringiu a conta, o disparo começou, foi pausado, terminou, o destinatário respondeu, chegou uma mensagem nova. Não precisa ficar consultando a API em loop.

Um ponto importante sobre o remetente: as mensagens saem das suas contas, que você mesmo conecta. O serviço não fornece números próprios, e isso é bom: o número e a reputação dele continuam seus, e as respostas dos clientes chegam pra você no aplicativo do mensageiro, como sempre.

Como obter a chave da API

  1. Entre no painel de disparos e abra a seção API.
  2. Clique em "Criar chave", dê um nome (é por ele que você vai saber depois pra qual integração a chave foi criada) e, se quiser, defina uma validade.
  3. Copie o token. Ele aparece uma única vez: o serviço guarda só o hash e não consegue recuperar o valor. Se perder o token, crie uma chave nova e apague a antiga.

A seção API fica disponível só pro dono do projeto: só ele cria chaves e vê a lista delas. Então, se quem faz a integração é um desenvolvedor ou uma empresa contratada, o dono cria a chave e passa o token pra essa pessoa, em vez de dar acesso ao painel.

A chave pertence ao projeto, não a um funcionário. Guarde como se fosse uma senha. Dá pra criar várias chaves, por exemplo uma por integração, pra revogar cada uma sem mexer nas outras.

A chave tem permissões, marcadas na criação: ler os dados do projeto, preparar disparos e públicos, iniciar disparos e enviar mensagens, gerenciar contas e bots, configurar o webhook. Uma chave nova, por padrão, lê e prepara; o resto você libera de forma explícita. As permissões também podem ser alteradas depois, sem trocar a chave: a integração que já recebeu essa chave não precisa parar.

O token vai no cabeçalho de cada requisição. Pra conferir se está tudo funcionando, peça a lista de contas conectadas:

bash
curl https://api.wsender.io/v1/channel \
  -H "Authorization: key SEU_TOKEN"

Todos os métodos estão descritos na documentação da API, e dá pra executar uma requisição com a sua chave direto no navegador, sem escrever uma linha de código. Ao lado fica a especificação pra máquinas, o arquivo OpenAPI: com ele, ferramentas como Swagger Codegen ou NSwag geram automaticamente o cliente na sua linguagem, e você não precisa descrever requisições e modelos à mão.

Um disparo em sete requisições

O cenário mínimo é assim: montar o segmento → criar o disparo → adicionar o texto → indicar os destinatários → mandar pra verificação → iniciar.

  1. PUT /v1/segment cria o segmento.
  2. PUT /v1/segment/{segmentId}/contact carrega os números.
  3. PUT /v1/mailing cria o disparo.
  4. PUT /v1/mailing/{mailingId}/message/text adiciona o texto da mensagem.
  5. PUT /v1/mailing/{mailingId}/recipient/source indica que os destinatários vêm do segmento.
  6. POST /v1/mailing/{mailingId}/moderate manda o texto pra verificação.
  7. POST /v1/mailing/{mailingId}/start inicia o envio pela conta escolhida.

As requisições são as mesmas pra mensageiros e bots: um disparo no WhatsApp é criado do mesmo jeito que no Telegram ou por um bot. Só muda o que está conectado. Daí em diante não precisa consultar nada: os status chegam por webhook.

Uma requisição repetida não cria um segundo disparo

Uma situação comum em integração: a requisição saiu e a resposta não voltou. A rede oscilou, estourou o timeout, o seu serviço reiniciou na hora errada. E aí fica a dúvida: se repetir, você corre o risco de criar um segundo disparo ou iniciar o envio duas vezes; se não repetir, pode ser que nada tenha sido enviado.

Por isso, toda requisição que altera alguma coisa aceita uma chave de idempotência. Você gera uma string (normalmente um UUID) e passa no cabeçalho:

text
Idempotency-Key: 3f0c1b7e-8a2e-4a51-9d2b-6a1e0f2c4d88

A regra é uma só: operação nova, chave nova; repetição da mesma operação, a mesma chave. O resto o serviço resolve. A primeira requisição é executada, e a resposta fica guardada por um dia. A repetição com a mesma chave não executa nada e devolve a mesma resposta da primeira vez. Se a primeira requisição ainda estiver em andamento, a repetição recebe o código 409: espere e tente de novo.

Se você mandar uma requisição diferente com a mesma chave, volta o código 422. É uma proteção contra reaproveitamento por engano: você não recebe o resultado de outra operação.

Na prática, a integração deve repetir só o que ficou sem resultado: queda de conexão, erros do servidor e a resposta 429 (excesso de requisições). Essas respostas não são guardadas, e a repetição executa a operação de verdade. Já uma recusa pelo conteúdo, por exemplo "falta um campo obrigatório no texto", conta como resultado, e a repetição devolve a mesma recusa.

De onde vêm os destinatários

O quinto passo merece uma explicação à parte: a fonte define tanto o resultado quanto o risco pra conta. Existem três fontes.

  • Segmento de contatos. Os números quem carrega é você. Um disparo ligado a um segmento continua enviando pros contatos que você adicionar depois. Pra integração, essa é a fonte principal, e mais abaixo tem uma seção só sobre ela.
  • Contatos da conta. A agenda do número conectado. Por padrão, as mensagens vão só pra quem já conversou com você: esse público responde melhor e quase não gera denúncias. Dá pra tirar essa restrição, mas é melhor não.
  • Conversas da conta. As conversas que já existem. Aqui também dá pra deixar só quem já conversou com você e, além disso, excluir as conversas com bots, pra não escrever em chats de serviço.

Um detalhe pra levar em conta ao planejar a integração: quando o disparo é iniciado pela primeira vez, a fonte fica fixa, junto com o mensageiro, e não muda mais. Pra usar outra fonte, é preciso um disparo novo.

Bots do Telegram: a mesma API

Não temos uma "API de bots" separada, e isso é de propósito: a integração escrita pra disparos por conta de mensageiro funciona com bots sem ajustes. Os mesmos métodos de conexão, os mesmos status, os mesmos webhooks, o mesmo caminho do disparo, do rascunho ao relatório por destinatário.

São só duas diferenças, e as duas aparecem logo de cara.

Conexão por token. O token você pega do lado da plataforma: no Telegram, quem gera é o @BotFather. Depois vem a mesma requisição da conta, só que com o token no lugar do modo de login. Se o token foi gerado de novo, o bot não se perde: uma requisição específica de atualização troca o token do bot já conectado, e inscritos, disparos e histórico continuam onde estavam (no painel, o link "Atualizar token" na página do bot faz a mesma coisa).

Destinatários: os inscritos do bot. O bot escreve pra quem escreveu pra ele primeiro: o segmento de números carregado não está disponível pra ele. A regra é da própria plataforma: pela Bot API não dá pra puxar conversa primeiro, e ninguém consegue contornar isso.

Daí vem uma divisão simples de papéis na integração. A conta de mensageiro continua sendo a única forma de alcançar alguém com quem você ainda não conversou. O bot serve pra trabalhar com quem já é inscrito: nesse disparo não há motivo pra bloqueio, o número de telefone nem entra na história, e a velocidade esbarra nos limites da plataforma, não num aquecimento cauteloso pra proteger a conta.

Disparos por gatilho: uma chamada por evento

O que o segmento tem de mais útil: o disparo ligado a ele não termina depois de enviar pra todo mundo que estava no segmento. Ele continua ativo e espera contatos novos: assim que você adiciona alguém ao segmento, o envio recomeça na hora.

Na prática, um disparo em andamento funciona como uma fila de envio. Então o esquema fica assim:

  1. Uma vez só, você cria o segmento e um disparo pra ele, adiciona o texto e inicia. Pode ser pela API ou à mão no painel, tanto faz.
  2. Depois, a cada evento no seu sistema, você faz uma requisição: adicionar o número ao segmento.

Pronto. A mensagem sai sozinha, num ritmo seguro, com o texto já verificado e respeitando os limites. Pagou o pedido, marcou horário, faltou, sumiu há um mês: você ganha os seus próprios disparos por gatilho e só precisa manter uma chamada por motivo.

O descadastro é igualmente simples, e vale pensar nele desde o início: se a pessoa pediu pra não receber mais mensagens, tire o número dela do segmento com uma requisição, e a fila não pega mais esse contato. O contato continua no projeto com o histórico, só sai desse público.

O texto desse disparo é um só pra todos os destinatários, com o nome inserido automaticamente e variações de frase. Por isso cada motivo ganha o próprio par "segmento e disparo": boas-vindas, lembrete de horário, reativação de cliente. Você cria uma vez, e depois eles só esperam os números.

As respostas dos clientes voltam pro seu sistema

O disparo não termina no envio: as pessoas respondem, e a resposta costuma ser justamente o resultado que motivou tudo. Pela API dá pra ver não só que a pessoa respondeu, mas o que ela escreveu.

Funciona assim: chega o webhook "destinatário respondeu", e aí você pede as respostas desse destinatário e recebe o horário, o texto, o tipo de mensagem e os nomes dos arquivos anexados.

bash
curl https://api.wsender.io/v1/mailing/{ID_DO_DISPARO}/recipient/{ID_DO_DESTINATARIO}/reply \
  -H "Authorization: key SEU_TOKEN"

Voltam só as respostas a esse disparo, não a conversa toda com a pessoa: o serviço pega as mensagens que chegaram depois do envio pra esse destinatário. O status "respondeu" segue a mesma regra, então status e conteúdo não se desencontram.

Daí a resposta vai pro seu CRM: numa tarefa do vendedor, no chat da equipe de vendas, num dashboard. Duas ressalvas, pra não contar com o que não existe: a conversa é puxada da conta de tempos em tempos, então passa um tempo entre a resposta da pessoa e o momento em que ela aparece na API; e a lista pode vir vazia se a pessoa só reagiu à mensagem, sem escrever nada.

Se você ainda não tem CRM próprio, as mesmas respostas aparecem no Dialogs, que abre a partir do painel: o atendente lê e responde por lá. As mensagens enviadas pela API aparecem ali com a marca "API", e passando o mouse sobre a marca dá pra ver com qual chave elas foram enviadas.

E o mais importante sobre os planos. As respostas, e junto com elas as conversas e os contatos da conta, vêm da sincronização da conta conectada, e ela não está em todos os planos: no gratuito não tem. Nele dá pra montar e testar a integração, e os disparos são criados e enviados, mas sem retorno: o webhook de resposta não chega, e a consulta de respostas devolve o erro 403 explicando que o recurso não faz parte do plano. Isso é proposital, pra não devolver uma lista vazia: com uma resposta vazia, você ia entender "a pessoa não respondeu" e procurar o erro no seu código.

Com bots é igual. No plano gratuito, o bot só envia: os disparos saem, mas as mensagens dos inscritos não são recebidas nem guardadas e não aparecem nem na API, nem no painel. Os inscritos continuam aparecendo, e dá pra fazer disparos pra eles.

Webhooks: o serviço avisa o que aconteceu

Não precisa ficar perguntando pra API em loop "e aí, alguma novidade?". Informe o seu endereço, e os eventos chegam sozinhos:

bash
curl -X PUT https://api.wsender.io/v1/webhook \
  -H "Authorization: key SEU_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://example.com/wsender","secret":"seu-segredo"}'

É um webhook por projeto, e o endereço tem que ser HTTPS. Troque o endereço e o segredo do exemplo pelos seus: no segredo, use só letras sem acento, números, hífen e sublinhado. O serviço manda o segredo de volta no cabeçalho X-WSender-Secret-Token de cada requisição, e assim você separa os seus eventos de chamadas estranhas no mesmo endereço.

Os eventos se dividem em quatro grupos:

  • Conta: conectada, desconectada e, durante a conexão: QR code pronto, código de pareamento pronto, aguardando o código de confirmação ou a senha de duas etapas, tudo certo.
  • Restrições do mensageiro: conta restrita e restrição removida. Talvez o mais valioso: no bloqueio, a conta continua conectada, e sem o evento o disparo para em silêncio.
  • Disparo: aprovado na verificação, reprovado com observações, iniciado, pausado com o motivo, concluído, cancelado.
  • Destinatários: mensagens enviadas, a pessoa respondeu, o envio falhou, o número não está no mensageiro.

Os eventos por destinatário e por mensagem individual só chegam com assinatura explícita. Liste os tipos que você quer em events: a lista vazia não inclui esses eventos, pra que um disparo grande não gere um fluxo desnecessário.

Primeiro salve o evento recebido em lugar seguro, depois responda com um código 2xx e só então processe. Se o seu servidor não responder em 10 segundos ou devolver erro, o serviço tenta de novo com intervalos de 30 segundos a meia hora. Cada evento fica na fila por no máximo um dia a partir da criação.

O mesmo evento pode chegar mais de uma vez: confira o id dele pra não repetir a ação no CRM.

Se já passou um dia desde a primeira falha sem nenhuma entrega bem-sucedida nesse período, o webhook é pausado automaticamente. O dono do projeto recebe um aviso pelo bot de notificações do WSENDER no Telegram, se ele estiver conectado. O estado pode ser conferido com GET /v1/webhook: no objeto health ficam o status Active ou Suspended, o último erro e as datas.

Depois de corrigir o seu receptor, chame POST /v1/webhook/resume com uma chave que tenha permissão de gerenciar o webhook:

bash
curl -X POST https://api.wsender.io/v1/webhook/resume \
  -H "Authorization: key SEU_TOKEN"

O serviço manda pro seu endereço o evento de teste webhook.test com o segredo de sempre. Só uma resposta 2xx retoma a entrega. O POST /v1/webhook/test comum ajuda a testar o endereço, mas não tira o webhook da pausa.

Durante a pausa, os eventos novos não se acumulam, e o prazo de guarda dos que já existem não é prorrogado. Os eventos vencidos e os do período da pausa não chegam depois da retomada. Por isso, depois de uma parada longa, consulte pela API os status atuais das mensagens e dos disparos. Os detalhes dos campos e dos erros estão na documentação da API.

Velocidade: por que a API não envia tudo de uma vez

É aqui que a expectativa dos desenvolvedores mais bate de frente com a realidade dos mensageiros. A API aceita a requisição na hora, mas o ritmo de envio fica por conta da Autoestratégia: ela começa devagar e aumenta a velocidade conforme a conta acumula histórico de envios. Se a plataforma frear a conta, o serviço pausa o disparo e continua mais devagar.

É assim que o serviço protege o seu número: se você disparar pra base inteira em uma hora, o mensageiro provavelmente vai restringir a conta. Por isso o serviço não oferece essa opção.

Mais quatro pontos que vale considerar antes da integração:

  • O texto é verificado antes do início. A IA analisa a mensagem e pode devolver observações. A lista de observações também pode ser consultada pela API, e em cada observação dá pra ver o que está errado e em qual mensagem. As recomendações são aceitas com uma requisição; temas proibidos só se resolvem editando o texto.
  • Os limites do plano funcionam como no painel. As mensagens consomem a cota diária: quando ela acaba, o disparo é pausado e não sai da pausa sozinho, é preciso iniciar de novo, no painel ou pela API.
  • O limite de requisições é por projeto. Ele é compartilhado por todas as chaves do projeto: criar chaves novas não aumenta o limite.
  • Números frios vão mais devagar. Se o número não está nas suas conversas, primeiro é preciso perguntar ao mensageiro se ele está cadastrado. No Telegram essa consulta é bem mais limitada, então um disparo pra números desconhecidos lá anda num ritmo bem mais calmo do que no WhatsApp.

Onde a API de disparos é útil

  • CRM: avisos de status da negociação e do pedido, e as respostas dos clientes voltam pra ficha.
  • Loja virtual: confirmação do pedido, pagamento, entrega.
  • Site ou landing page: resposta imediata a quem preencheu o formulário, no mensageiro que a pessoa usa.
  • Agendamento online: lembrete do horário um dia antes.
  • Reativação: o segmento "não compra há 3 meses" é alimentado pela sua base, e o disparo vai processando a fila sozinho.

Próximos passos

A API não é cobrada à parte, valem os planos normais. Ela funciona até no plano gratuito, com 15 mensagens por dia, o suficiente pra montar e testar a integração.

Comece pequeno: crie uma chave, peça a lista de contas, conecte uma conta e faça um disparo pra um segmento com um único número, o seu. Em meia hora dá pra entender o fluxo inteiro. Depois é só montar o par "segmento e disparo" de verdade e adicionar números a ele a partir do ponto do seu sistema onde o evento acontece.

A descrição completa dos métodos está na documentação da API, e a especificação pra gerar o cliente fica no arquivo OpenAPI.