> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ararahq.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Migrar do Baileys

> Sair do Baileys (e whatsapp-web.js, wppconnect) para a WhatsApp Business Platform via Arara: de socket persistente com sessão local para API REST e webhook. Diff de arquitetura, código e plano de migração.

Baileys é uma biblioteca open source que conecta um número pelo protocolo do WhatsApp Web: roda na sua infra, autentica por QR Code e mantém um socket aberto. A Arara envia pela WhatsApp Business Platform da Meta, por API REST. Migrar é trocar de arquitetura, não só de biblioteca.

Esta página vale também para `whatsapp-web.js` e `wppconnect`, que seguem o mesmo padrão.

## O que muda

| | Baileys | Arara |
| - | - | - |
| Conexão | Socket persistente + sessão salva em disco | HTTPS, sem estado do seu lado |
| Autenticação | QR Code no celular | chave de API `ara_live_...` |
| Infra | Processo seu, sempre ligado | Nenhum processo a manter |
| Mensagem iniciada pela empresa | Mensagem sem template | Template aprovado pela Meta |
| Mensagem dentro da janela de 24h | A qualquer momento | Dentro da janela de 24h aberta pelo cliente |
| Recebimento | Evento `messages.upsert` no socket | Webhook HTTP assinado |
| Custo | Infra e manutenção próprias | Plano + uso por mensagem. Veja [Preços](/concepts/pricing) |

O que você passa a ter: templates, webhooks de status de entrega e leitura, dashboard com inbox e campanhas, e recursos como [Brain](/brain), [Smart Links](/smart-links) e [recuperação de receita](/recovery).

O que você perde:

* **Mensagem sem template a qualquer hora**: fora da janela de 24h, só template.
* **Latência de aprovação**: template novo depende da Meta.
* **Recursos do WhatsApp Web**: grupos, status, listas de transmissão e stickers não são enviados pela Arara.

## Diff de arquitetura

Baileys roda como processo persistente:

```
[Seu backend] <-> [processo Baileys] <-socket-> [WhatsApp]
                  (sessão local)
```

Se o processo cai, a sessão pode ser perdida e o QR Code precisa ser lido de novo.

Com a Arara, o seu lado é stateless:

```
[Seu backend] --HTTPS--> [API Arara] --> [WhatsApp Business Platform]
[Seu backend] <--webhook-- [API Arara]
```

## Diff de código

### Envio

<CodeGroup>
  ```typescript Baileys (antes) theme={null}
  import makeWASocket, { useMultiFileAuthState } from '@whiskeysockets/baileys';

  const { state, saveCreds } = await useMultiFileAuthState('./auth');
  const sock = makeWASocket({ auth: state });
  sock.ev.on('creds.update', saveCreds);

  sock.ev.on('connection.update', async ({ connection }) => {
    if (connection === 'open') {
      await sock.sendMessage('5511999999999@s.whatsapp.net', {
        text: 'Olá João, seu pedido foi confirmado!',
      });
    }
  });
  ```

  ```typescript Arara (depois) theme={null}
  import { NodeSDK } from '@ararahq/sdk';

  const sdk = new NodeSDK({ apiKey: process.env.ARARA_API_KEY! });

  await sdk.messages.send(
    {
      receiver: '+5511999999999',
      templateName: 'pedido_confirmado',
      templateVariables: ['João', 'ARA-123'],
    },
    { idempotencyKey: 'pedido-ARA-123-confirmado' },
  );
  ```
</CodeGroup>

### Mensagem recebida

<CodeGroup>
  ```typescript Baileys (antes) theme={null}
  sock.ev.on('messages.upsert', async ({ messages }) => {
    for (const msg of messages) {
      if (!msg.message || msg.key.fromMe) continue;
      const from = msg.key.remoteJid;
      const text = msg.message.conversation || msg.message.extendedTextMessage?.text;
    }
  });
  ```

  ```typescript Arara (depois) theme={null}
  // Webhook HTTP. Valide X-Arara-Signature com o corpo cru antes de parsear (veja /webhooks).
  app.post('/arara/webhook', express.text({ type: 'application/json' }), (req, res) => {
    if (!isValidAraraSignature(req)) return res.status(401).end();

    const { event, data } = JSON.parse(req.body);
    if (event === 'message.received') {
      const phone = data.from; // só dígitos, ex.: 5511999999999
      const text = data.body;
    }
    res.status(204).end();
  });
  ```
</CodeGroup>

`isValidAraraSignature` recalcula `sha256=` + HMAC-SHA256 de `{X-Arara-Timestamp}.{corpo cru}` com o secret da organização e compara em tempo constante. Implementação completa em [Webhooks](/webhooks) e [SDK Node](/sdks/node).

### Localização, reação e botões

A API aceita esses tipos em `POST /v1/messages`, dentro da janela de 24h. O SDK Node 2.0.0 aceita `interactive`, `location` e `reaction` em `sdk.messages.send`, mas os tipa só como objeto genérico, então confira a forma de cada um na tabela:

| Operação | Baileys | Arara (`POST /v1/messages`) |
| - | - | - |
| Localização | `sendMessage(jid, { location: { degreesLatitude, degreesLongitude } })` | `{ receiver, location: { latitude, longitude, name?, address? } }` |
| Reação | `sendMessage(jid, { react: { text, key } })` | `{ receiver, reaction: { emoji, messageId } }` com o `ara_msg_...` da mensagem |
| Botões / lista | varia por versão | `{ receiver, interactive: { type, body, buttons?, sections?, buttonText? } }`, com `type` igual a `button` ou `list` |
| Sticker | `sendMessage(jid, { sticker })` | Não suportado |

```typescript theme={null}
await sdk.messages.send(
  {
    receiver: '+5511999999999',
    location: { latitude: -23.5614, longitude: -46.6559, name: 'Loja Paulista' },
  },
  { idempotencyKey: 'pedido-ARA-123-localizacao' },
);
```

Cada requisição leva **um** tipo: `templateName`, `body`, `interactive`, `location` ou `reaction`. Mais de um responde 400.

## Plano de migração

### 1. Inventário

* Todos os pontos do backend que usam o socket.
* Todos os tipos de mensagem enviados (texto, mídia, localização).
* Integrações que dependem disso (CRM, loja, ERP).

### 2. Templates

Tudo que é enviado **sem o cliente ter falado nas últimas 24h** vira template aprovado:

* "Oi João, recebemos seu pedido" → `pedido_confirmado`, `UTILITY`
* "Promoção da semana" → `oferta_semana`, `MARKETING`
* "Seu código é 1234" → `codigo_verificacao`, `AUTHENTICATION`

Crie pelo dashboard ou `POST /v1/templates` e aguarde a aprovação antes do cutover.

### 3. Código

* `makeWASocket` → `new NodeSDK({ apiKey })` ou chamadas HTTP.
* `sock.sendMessage` → `sdk.messages.send` (template ou texto) ou `POST /v1/messages` (outros tipos).
* `sock.ev.on('messages.upsert')` → rota HTTP de webhook com validação de assinatura.

### 4. Número

* **Número no app WhatsApp Business**: pode ser conectado em coexistência, mantendo o app. Mensagens enviadas pelo celular chegam como `message.echo`.
* **Número que só existe na sessão do Baileys**: registrado na plataforma, deixa de funcionar pelo WhatsApp Web. Planeje a janela de troca.
* **Número novo**: roda em paralelo e migra a base aos poucos.

A conexão é feita no dashboard ([https://app.ararahq.com](https://app.ararahq.com)), em Números.

### 5. Cutover

Deploy do código novo, acompanhamento no dashboard e desligamento do processo Baileys depois de validado.

## Pegadinhas

### Sessão local

Depois de migrar, remova arquivos de sessão, volumes e credenciais do Baileys.

### Formato do telefone

Baileys usa JID (`5511999999999@s.whatsapp.net`). Na Arara, o envio usa `+5511999999999` e o webhook de entrada traz `data.from` só com dígitos.

### Grupos

A Arara não envia para grupos. Se a operação dependia disso, valide antes de migrar.

## Próximos passos

<CardGroup cols={2}>
  <Card title="Conceitos WhatsApp" icon="lightbulb" href="/concepts/whatsapp">
    Janela de 24h e templates.
  </Card>

  <Card title="Migrar do Z-API" icon="arrow-right-arrow-left" href="/migrate/z-api">
    Outro gateway via WhatsApp Web, mesma lógica.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.