LunaDocumentaçãoEntrar

Migrar da Evolution API para a Luna

A Evolution API é uma camada sobre biblioteca não-oficial; a Luna opera exclusivamente sobre a WhatsApp Cloud API oficial da Meta, na condição de Tech Provider aprovado. As duas fazem coisas parecidas por caminhos diferentes, e a diferença de caminho é o assunto deste documento.

Leia as três diferenças abaixo antes da tabela. Elas são o que quebra uma migração no meio: quem começa pela tabela descobre a primeira delas no primeiro cliente que responde no dia seguinte, com o desenho já pronto.

Três coisas que vão mudar o seu desenho

1. A janela de 24 horas existe, e não há como contorná-la

Na Cloud API oficial, texto livre só sai para quem falou com você nas últimas 24 horas. Passado esse prazo, o único caminho é um template aprovado pela Meta. Numa biblioteca não-oficial essa restrição não aparece, porque ela conversa pelo mesmo canal de um aparelho. O desenho que funcionava lá presume uma liberdade que aqui não existe.

Leia `GET /v1/conversations` antes de decidir como responder. Cada linha traz `windowOpen`, `windowExpiresAt` e `windowSource`: a plataforma avisa **antes** de você gastar a chamada, em vez de devolver um erro depois. Com a janela fechada, o caminho é enviar um template, e ele reabre a conversa.

2. O envio responde `202`, e o identificador da Meta não vem junto

O `POST /v1/messages` devolve `202` com um identificador da Luna e o estado `queued`. Ele não devolve o `wamid`, porque nesse instante a Meta ainda não o emitiu. Quem integrou esperando o identificador definitivo na resposta precisa mudar o desenho, e essa é a segunda coisa que quebra uma migração.

A razão é honesta e vale saber: o limite que mais aperta na Cloud API é de uma mensagem a cada seis segundos para o mesmo destinatário. Um agente que responde em rajada dispara esse limite sozinho, e a resposta certa a isso é fila, nunca um erro devolvido a você. Guarde o identificador da Luna, e receba o `wamid` e o estado de entrega pelo seu webhook, no evento `message.status`.

3. Não há QR Code, e não pode haver

Conectar um número lendo um QR Code com o aparelho é o modelo de uma biblioteca que se apresenta como um WhatsApp Web. A plataforma oficial não funciona assim: cada negócio final precisa da própria conta de WhatsApp Business na Meta, com o método de pagamento dele, e a conexão acontece pelo fluxo que a Meta chama de Embedded Signup: dentro do seu produto, mas contra a Meta.

Esta é a diferença que **não tem contorno**, e ela é a razão de a Luna existir na forma que existe. É também o que separa uma conexão que sobrevive de uma que é desligada: o número é do seu cliente, na conta dele, e a Helsen opera como Tech Provider aprovado pela Meta. O ciclo começa em `POST /v1/onboarding/sessions` e termina em `POST /v1/onboarding/sessions/{id}/complete`.

Capacidade a capacidade

O mapa é por capacidade, e não por assinatura de rota: prometer que uma chamada vira outra seria prometer paridade, e não é o caso. Onde não há equivalente, a razão está escrita, e quase sempre ela é uma regra da plataforma oficial, não uma escolha da Luna.

CapacidadeNa Evolution APINa LunaO que saber
Enviar uma mensagem de textoUma rota de envio de texto por instância, respondendo com o resultado do envio.POST /v1/messagesO corpo traz `from`, `to` e `text.body`. A resposta é `202` com o identificador da Luna e o estado `queued`; o `wamid` chega depois, pelo webhook. Um corpo sem `type` é interpretado como texto.
Enviar imagem, áudio, vídeo ou documentoUma rota de envio de mídia por instância, aceitando o arquivo em base64 ou por URL.POST /v1/numbers/{id}/media, depois POST /v1/messagesSão dois passos porque a Meta trabalha com identificador de mídia. Suba o arquivo em `multipart/form-data`, receba o identificador e use-o no envio. Enviar por `link` também funciona, e nesse caso a URL precisa responder sem autenticação. O identificador evita isso e pode ser reaproveitado em várias mensagens.
Iniciar conversa fora da janela de 24 horasNormalmente não existe como conceito: o envio de texto vale a qualquer momento.POST /v1/templates, depois POST /v1/messages com `type: template`É a consequência direta da primeira diferença de modelo. O template é criado, submetido à Meta e usado depois de aprovado, e o estado dele chega por webhook, sem que você precise ficar consultando.
Receber o que chega no númeroUm webhook configurado por instância, com os eventos escolhidos na configuração.POST /v1/webhooks/endpointsUm endpoint para o tenant inteiro, e não por número: os eventos dizem de que número vieram. Toda entrega é assinada, e o segredo pode ser rotacionado sem janela de indisponibilidade por `POST /v1/webhooks/endpoints/{id}/rotacionar`, que mantém o segredo anterior válido por um período.
Recuperar o que o seu servidor não recebeuDepende da instalação; frequentemente não há retentativa nem registro do que falhou.GET /v1/webhooks/dlq, POST /v1/webhooks/dlq/{id}/reenfileirarUm evento chega à fila de rejeitados depois de a política de retentativa se esgotar. Ele não é entregue de novo sozinho: ou você o re-enfileira, ou ele fica lá até a retenção expirar. A resposta não traz total, de propósito: para saber quantos itens há, pagine até `nextCursor` vir nulo.
Consultar o histórico de mensagensUma consulta ao armazenamento da própria instância, com filtros por chat.GET /v1/messages, GET /v1/conversationsFiltre por `phoneNumberId` ou por `conversationId`, e pagine com `nextCursor`. O cursor é opaco: ele carrega posição e não contagem, então não tente construir um à mão.
Saber se a mensagem foi entregue e lidaEventos de atualização de status entregues pelo webhook da instância.Evento `message.status` no seu webhook, e GET /v1/messages/{id}O estado chega por evento, e a consulta por identificador serve para reconciliar. É por aqui que o `wamid` da Meta se liga ao identificador que o `202` devolveu no envio.
Baixar a mídia que o cliente enviouA mídia costuma vir embutida no evento, ou é buscada no armazenamento da instância.GET /v1/messages/{id}/mediaA Luna guarda o arquivo e o serve por esta rota. A URL de download que a Meta emite expira em cinco minutos, e guardar essa URL é a forma mais comum de uma retentativa falhar sempre. Por isso ela nunca é repassada.
Marcar como lida e mostrar “digitando”Rotas de presença e de leitura por instância.POST /v1/messages/{id}/read, POST /v1/messages/{id}/typingExistem e funcionam, e são o que faz um agente automático parecer atendimento e não robô. Ambas agem sobre a mensagem recebida, e não sobre a conversa.
Conectar um número novoCriar uma instância e ler o QR Code com o aparelho que tem o número.POST /v1/onboarding/sessions e o fluxo Embedded Signup**Sem equivalente, e é a diferença que não tem contorno.** O onboarding é Embedded Signup porque cada negócio final precisa da própria conta de WhatsApp Business e do próprio método de pagamento na Meta, que é a condição de operar como Tech Provider. O número é do seu cliente, na conta dele, e é isso que faz a conexão sobreviver.
Listar os números conectados e o estado de cada umUma listagem de instâncias, com o estado da conexão de cada uma.GET /v1/numbers, GET /v1/numbers/{id}O identificador da Luna e o da Meta são campos distintos, e a distinção importa: as rotas de envio pedem o da Meta (`metaPhoneNumberId`), e as de mídia e detalhe pedem o da Luna.
Criar grupo, entrar em grupo, mandar para grupoRotas de grupo, herdadas de a biblioteca se apresentar como um aparelho.Sem equivalente**Sem equivalente.** A Cloud API oficial não expõe grupos a um número de negócio: o produto que a Meta publica é a conversa entre uma empresa e uma pessoa. Não é uma escolha da Luna, e nenhuma plataforma oficial oferece isso.
Ler a agenda, o perfil e a foto de quem escreveuRotas de contato e de perfil, pela mesma razão da linha acima.Sem equivalente**Sem equivalente.** Um número de negócio na plataforma oficial não tem agenda, e o perfil de quem escreve não é publicado. O que chega é o telefone do interlocutor e o nome que ele mesmo expôs no evento, e é sobre isso que dá para trabalhar.
Verificar se um número tem WhatsApp antes de mandarUma rota de verificação, respondendo se o número existe na rede.Sem equivalente**Sem equivalente.** A plataforma oficial não publica essa consulta. O envio para um número sem WhatsApp simplesmente não é entregue, e você fica sabendo pelo evento de status, que é a informação equivalente, um passo depois.
Autenticar as suas chamadasUma chave global da instalação, normalmente num cabeçalho próprio.POST /v1/api-keysA chave vai em `Authorization: Bearer hlsn_…` e carrega **escopos**: uma rota fora do conjunto responde `403`. Dê a cada chave só o que ela precisa: uma que só envia mensagem não deveria poder conectar número. Ela é mostrada uma única vez, e não há rota que a devolva depois.

O que a Helsen cobra, e o que a Meta cobra

A assinatura da Helsen é pela capacidade de números ativos do seu plano, e por nada além disso. O uso da plataforma WhatsApp é cobrado pela Meta, diretamente do seu cliente final, no método de pagamento que ele cadastra na conta dele. A Helsen não intermedeia esse pagamento e não o repassa. É por isso que cada negócio final precisa de conta própria na Meta.

Por onde começar

A documentação da API traz o contrato de cada rota, com exemplos, e há um cliente TypeScript gerado dela, o mesmo que o console da Helsen usa. Se algo neste guia não bater com a documentação, é a documentação que vale: ela é derivada do código que valida as requisições.

WhatsApp e Meta são marcas da Meta Platforms, Inc. Evolution API é projeto de terceiros, sem relação com a Helsen. Este documento descreve o modelo de cada plataforma para quem está migrando, e não é comparação comercial.