---
title: "Onboarding de WhatsApp no SaaS com código de pareamento"
description: "Conecte o WhatsApp do cliente dentro do seu SaaS, com a sua marca e sem QR Code: fluxo, estados da tela, backend em Node.js e webhook de conexão."
url: "https://api-wa.me/blog/onboarding-saas-whatsapp-codigo-pareamento"
language: "pt-BR"
og:type: "article"
og:site_name: "WAME API"
---

[Início](https://api-wa.me/)/[Blog da API do WhatsApp](https://api-wa.me/blog)/Onboarding de WhatsApp no seu SaaS com código de pareamento (sem QR, com a sua marca)

Raphael Serafim· Publicado em 28 de setembro de 2026· 9 min de leitura

Compartilhar

# Onboarding de WhatsApp no seu SaaS com código de pareamento (sem QR, com a sua marca)

Conecte o WhatsApp do cliente dentro do seu SaaS, com a sua marca e sem QR Code: fluxo, estados da tela, backend em Node.js e webhook de conexão.

Copiar para LLM[Ver como Markdown](https://api-wa.me/blog/onboarding-saas-whatsapp-codigo-pareamento.md)

**Para conectar o WhatsApp do cliente dentro do seu SaaS sem QR Code, seu backend chama `POST /{key}/instance/pairing-code` com o número do cliente, recebe o código de 8 caracteres em `code` e mostra na sua tela; o cliente digita no próprio celular e o webhook de conexão avisa quando terminou.** Tudo acontece com a sua marca, na sua interface, e funciona até quando o cliente está com o celular como único aparelho.

Este guia é para quem desenvolve o produto: estados da tela, backend em Node.js, confirmação por webhook e as métricas do funil. A visão geral dos métodos de conexão está em [conectar WhatsApp na API sem QR Code](https://api-wa.me/blog/conectar-whatsapp-codigo-pareamento-sem-qr-code), e o passo a passo para o usuário final está em [conectar o WhatsApp só pelo celular](https://api-wa.me/blog/conectar-whatsapp-api-pelo-celular-sem-qr-code).

> A camada não oficial da WAME é independente e não é afiliada, endossada ou suportada pelo WhatsApp ou pela Meta. O uso é de responsabilidade de quem envia.

## Por que código em vez de QR no onboarding

O QR Code tem um problema estrutural para SaaS: ele exige **duas telas**. O cliente precisa ver o QR no computador e ler com o celular. Quem faz o cadastro pelo celular (e no pequeno negócio isso é muito comum) trava ali: não tem como o celular ler um QR exibido nele mesmo.

O código de pareamento resolve isso e ainda traz outras vantagens:

- **Funciona no mesmo aparelho.** O cliente copia o código e cola no WhatsApp.
- **Não depende de câmera**, de enquadramento ou de o QR não expirar enquanto a pessoa procura o celular.
- **Funciona remoto.** O suporte consegue guiar por telefone: "abra Aparelhos conectados e digite o código que aparece na tela".
- **É white label.** O cliente vê a sua tela e as suas instruções.

Em produto, isso vira métrica: menos gente abandonando o onboarding e menos chamados do tipo "não consigo ler o QR".

## Os estados da tela

Antes do código, desenhe a máquina de estados. É ela que evita tela travada e cliente perdido.

| Estado | O que a tela mostra | Próximo |
| --- | --- | --- |
| `pedir_numero` | Campo de telefone com DDI | `gerando` |
| `gerando` | Carregando | `mostrando_codigo`, `conectado` ou `erro` |
| `mostrando_codigo` | Código grande, botão copiar, instruções | `conectado` ou `expirado` |
| `expirado` | "O código expirou" e botão para gerar outro | `gerando` |
| `conectado` | Confirmação e próximo passo do onboarding | fim |
| `erro` | Mensagem clara e opção de tentar de novo | `pedir_numero` |

Três detalhes de UX que fazem diferença:

1. **Mostre o código grande**, em blocos (`XXXX-XXXX`), com botão **Copiar**. É assim que o painel da própria WAME faz.
2. **Instruções ao lado do código**, e não em outra página: "WhatsApp → Aparelhos conectados → Conectar um aparelho → Conectar com número de telefone".
3. **Ofereça o QR como alternativa**, com um link discreto ("Prefere ler um QR Code?"), para quem está no computador.

## Normalizando o número

O `phoneNumber` precisa estar no formato internacional, só dígitos, e ser **o número do celular onde o código será digitado**. Normalize no backend, nunca confie no que veio do formulário:

javascript

Copiar

```
function normalizarTelefone(entrada, ddiPadrao = '55') {
  let d = String(entrada).replace(/\D/g, '');
  if (d.startsWith('00')) d = d.slice(2);
  // Número brasileiro sem DDI: 10 ou 11 dígitos (DDD + número)
  if (d.length === 10 || d.length === 11) d = ddiPadrao + d;
  if (d.length < 12 || d.length > 15) return null;
  return d;
}
```

No front, deixe claro que é o número do WhatsApp que será conectado, e não um telefone de contato qualquer. É a causa mais comum de "o código não funciona".

## O backend: gerar o código

A key da instância autentica todas as chamadas. **Ela nunca vai para o navegador.** O front chama o seu backend, que sabe qual instância pertence ao cliente logado:

javascript

Copiar

```
import express from 'express';

const app = express();
app.use(express.json());
const BASE = 'https://us.api-wa.me';

// Cliente autenticado pede o código para o próprio número
app.post('/api/whatsapp/codigo', exigirLogin, async (req, res) => {
  const cliente = await db.clientes.buscar(req.user.id);
  const telefone = normalizarTelefone(req.body.telefone);
  if (!telefone) return res.status(400).json({ erro: 'telefone_invalido' });

  const r = await fetch(`${BASE}/${cliente.instanceKey}/instance/pairing-code`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ phoneNumber: telefone }),
  });
  const dados = await r.json();

  if (!r.ok) {
    await metricas.registrar('onboarding_erro', { cliente: cliente.id, status: r.status });
    return res.status(502).json({ erro: 'falha_ao_gerar' });
  }

  // Instância já pareada: não vem código, e está tudo certo
  if (dados.isConnected) {
    await db.clientes.marcarConectado(cliente.id);
    return res.json({ estado: 'conectado' });
  }

  await db.clientes.atualizar(cliente.id, {
    whatsappStatus: 'aguardando_codigo',
    codigoGeradoEm: new Date(),
  });
  await metricas.registrar('onboarding_codigo_gerado', { cliente: cliente.id });

  res.json({ estado: 'mostrando_codigo', codigo: dados.code });
});
```

Repare no `isConnected`. A API não gera código para uma sessão que já está pareada, porque pedir código numa sessão ativa derrubaria a conexão existente. Para o seu produto, isso é sucesso: pule direto para o próximo passo.

Se a sua plataforma cria instâncias por cliente, o `instanceKey` vem do provisionamento. O ciclo de criar, ativar, suspender e remover está em [provisionar WhatsApp para vários clientes por API](https://api-wa.me/blog/provisionar-whatsapp-multiplos-clientes-api).

Um caso à parte: instâncias criadas para registro mobile, sem aparelho vinculado, não usam código de pareamento e respondem com erro `400`. Esse fluxo é outro, descrito em [WhatsApp sem celular](https://api-wa.me/blog/whatsapp-sem-celular-conexao-mobile-api).

## Confirmando a conexão pelo webhook

Configure o webhook de conexão da instância uma vez, no provisionamento:

bash

Copiar

```
curl -X PUT "https://us.api-wa.me/SUA_KEY/instance" \
  -H "Content-Type: application/json" \
  -d '{
    "allowWebhook": true,
    "allowNumber": "all",
    "webhookConnection": "https://seusaas.com.br/wame/conexao",
    "webhookFormat": "meta"
  }'
```

Quando o cliente digita o código e o pareamento conclui, chega um evento com `field: "connection"` e `value.connection.status` igual a `"open"`. O campo `instance`, no topo do envelope, traz a key da instância que conectou:

javascript

Copiar

```
app.post('/wame/conexao', async (req, res) => {
  res.sendStatus(200); // responda rápido; processe depois

  const entry = req.body?.entry?.[0];
  const change = entry?.changes?.[0];
  if (change?.field !== 'connection') return;

  const cliente = await db.clientes.porInstancia(req.body.instance);
  if (!cliente) return;

  if (change.value?.connection?.status === 'open') {
    await db.clientes.marcarConectado(cliente.id);
    await metricas.registrar('onboarding_conectado', { cliente: cliente.id });
    avisarFront(cliente.id, { estado: 'conectado' });
  }
});
```

Proteja esse endpoint como qualquer webhook: URL difícil de adivinhar, validação de origem e idempotência. Os cuidados estão em [segurança da API do WhatsApp: token, webhook e dados](https://api-wa.me/blog/seguranca-api-whatsapp-token-webhook).

## Levando o status até a tela

O webhook chega no backend; a tela do cliente precisa saber. Duas opções simples:

**Server-Sent Events**, que empurra o status assim que ele muda:

javascript

Copiar

```
const conexoes = new Map(); // clienteId -> res

app.get('/api/whatsapp/status', exigirLogin, (req, res) => {
  res.set({ 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache' });
  res.flushHeaders();
  conexoes.set(req.user.id, res);
  req.on('close', () => conexoes.delete(req.user.id));
});

function avisarFront(clienteId, evento) {
  conexoes.get(clienteId)?.write(`data: ${JSON.stringify(evento)}\n\n`);
}
```

No front, poucas linhas:

javascript

Copiar

```
const fonte = new EventSource('/api/whatsapp/status');
fonte.onmessage = (e) => {
  const { estado } = JSON.parse(e.data);
  if (estado === 'conectado') mostrarTela('conectado');
};
```

**Polling**, se a sua infraestrutura não mantém conexões abertas: o front consulta o seu backend a cada poucos segundos, e o backend responde com o status do banco.

Nos dois casos, tenha uma **rede de segurança**. Se o webhook falhar ou atrasar, o backend consulta `GET /{key}/instance` para ver o estado real antes de declarar o código como expirado.

## Expiração e "gerar outro"

O código vale por pouco tempo, na casa de poucos minutos, e é de uso único. Não tente adivinhar o momento exato da expiração. Use um tempo de tela conservador:

javascript

Copiar

```
const TEMPO_TELA_MS = 2 * 60 * 1000; // ajuste ao que você observar

setTimeout(async () => {
  const { estado } = await fetch('/api/whatsapp/estado').then((r) => r.json());
  if (estado !== 'conectado') mostrarTela('expirado');
}, TEMPO_TELA_MS);
```

Na tela `expirado`, um botão **Gerar novo código** volta para `gerando`. Limite quantas vezes por minuto o mesmo cliente pode pedir código: além de evitar abuso do seu endpoint, isso impede que um script com erro fique gerando códigos em loop.

## Segurança: o código é uma senha

O código de pareamento vincula um aparelho à conta do cliente. Trate como senha:

- **Mostre só em tela autenticada**, para o dono da conta.
- **Não envie o código** por e-mail, SMS ou chat de suporte. O cliente gera e digita do lado dele.
- **Não registre o código em log** nem em ferramenta de analytics.
- **Eduque o cliente:** "nunca informe esse código a ninguém, nem ao nosso suporte". Isso também protege contra o golpe clássico em que alguém pede "o código que chegou no seu WhatsApp".

## Medindo o funil

Com os eventos acima, você tem o funil de onboarding do WhatsApp:

| Etapa | Evento |
| --- | --- |
| Iniciou | Abriu a tela de conexão |
| Gerou código | `onboarding_codigo_gerado` |
| Conectou | `onboarding_conectado` |
| Expirou sem conectar | Tela `expirado` exibida |
| Erro | `onboarding_erro` |

Acompanhe o tempo entre gerar e conectar, a taxa de expiração e quantos precisaram de um segundo código. Taxa de expiração alta quase sempre é instrução pouco clara ou número errado. Melhore o texto da tela antes de mexer em qualquer outra coisa.

## Depois do onboarding

Conectado, o cliente começa a usar o seu produto. Se o número for novo, oriente sobre ritmo nas primeiras semanas: número recém-conectado que dispara volume alto chama atenção do anti-spam. A WAME não apoia spam, e a taxa de bloqueio é muito baixa para quem usa do jeito certo: atendimento, notificações para quem pediu, grupos e bots. O plano está em [como aquecer um número novo](https://api-wa.me/blog/aquecer-numero-whatsapp-api-nao-oficial).

Também vale ligar o webhook de conexão ao seu monitoramento, e não só ao onboarding. Quedas depois de conectado são sinal a acompanhar, como mostra [sinais de que o número está em risco](https://api-wa.me/blog/sinais-numero-whatsapp-risco-bloqueio).

## Conclusão

Onboarding de WhatsApp com código de pareamento é o fluxo que o seu cliente consegue concluir sozinho, pelo celular, sem QR e sem chamar o suporte. A receita: normalize o número no backend, chame `POST /{key}/instance/pairing-code` com a key do cliente (nunca no navegador), mostre o `code` grande com botão de copiar, trate `isConnected` como sucesso e confirme pelo webhook de conexão com `status: "open"`. Adicione a tela de código expirado, meça o funil e trate o código como senha. O resultado é um onboarding white label, com a sua marca, e menos gente parada no primeiro passo. A referência completa dos endpoints está na [documentação](https://api-wa.me/docs).

### Pronto para automatizar seu WhatsApp?

Crie sua conta gratuita e comece a enviar mensagens pela API em minutos.

[Começar grátis](https://portal.api-wa.me/sign-up)

## Perguntas frequentes

Como conectar o WhatsApp do meu cliente sem mandar QR Code?+

Na tela de onboarding do seu sistema, o cliente informa o número. Seu backend chama POST /{key}/instance/pairing-code com o phoneNumber, recebe o campo code e mostra os 8 caracteres na tela. O cliente digita o código no próprio celular, em Aparelhos conectados > Conectar com número de telefone. O webhook de conexão avisa quando terminou.

Posso chamar a API de pareamento direto do navegador?+

Não deve. A key da instância autentica todas as chamadas e não pode ficar exposta no front. O navegador chama o seu backend, que conhece a key do cliente e fala com a API. O front só recebe o código e o status.

Como sei que o cliente terminou de conectar?+

Configure o webhookConnection pelo PUT /{key}/instance. Quando o pareamento conclui, chega um evento com field connection e status open. Seu backend atualiza o banco e avisa o front por Server-Sent Events, WebSocket ou polling. Como rede de segurança, consulte GET /{key}/instance.

E se a instância já estiver conectada?+

A resposta do pairing-code vem com isConnected true e sem código. Trate como sucesso e pule para o próximo passo do onboarding. A API não gera código para sessão já pareada, porque isso derrubaria a conexão existente.

O cliente vai ver a marca WAME no onboarding?+

Não precisa. A tela, as instruções e o código aparecem dentro do seu produto. No celular do cliente, a conexão aparece na lista de Aparelhos conectados como uma sessão de navegador. É um fluxo white label.

## Continue lendo

[### Conectar WhatsApp na API sem QR Code: código de pareamento e Passkey

Três jeitos de conectar um número na API não oficial do WhatsApp: QR Code, código de pareamento de 8 caracteres e WAME Passkey. Com cURL, webhooks e reconexão.](https://api-wa.me/blog/conectar-whatsapp-codigo-pareamento-sem-qr-code)[### Conectar o WhatsApp à API só pelo celular, sem QR Code (código de 8 dígitos)

Só tem o celular? Conecte seu WhatsApp à API sem QR Code: gere o código de 8 dígitos no painel WAME e digite no app. Passo a passo e soluções.](https://api-wa.me/blog/conectar-whatsapp-api-pelo-celular-sem-qr-code)[### 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.](https://api-wa.me/blog/agente-voz-whatsapp-latencia-interrupcao)

[Voltar ao blog](https://api-wa.me/blog)

## Structured data

```json
{
  "@context": "https://schema.org",
  "@type": "WebSite",
  "name": "WAME API",
  "alternateName": "API Oficial e Não Oficial de WhatsApp, Instagram, Messenger e Telegram",
  "url": "https://api-wa.me",
  "inLanguage": "pt-BR",
  "publisher": {
    "@id": "https://api-wa.me/#organization",
    "@type": "Organization",
    "name": "WAME API",
    "url": "https://api-wa.me"
  }
}
{
  "@context": "https://schema.org",
  "@type": "Organization",
  "@id": "https://api-wa.me/#organization",
  "name": "WAME API",
  "alternateName": [
    "WAME",
    "Wame API",
    "wame.api.br",
    "api-wa.me"
  ],
  "url": "https://api-wa.me",
  "logo": {
    "@type": "ImageObject",
    "url": "https://api-wa.me/images/web-app-manifest-512x512.png",
    "width": 512,
    "height": 512
  },
  "disambiguatingDescription": "WAME API é uma empresa brasileira de software, fundada em 2017 e parceira oficial da Meta (Meta Business Partner), que fornece APIs de WhatsApp, Instagram Direct e Messenger. Não tem relação com o wa.me, que é o encurtador de links operado pela WhatsApp LLC.",
  "identifier": {
    "@type": "PropertyValue",
    "propertyID": "INPI-BR",
    "name": "Pedido de registro de marca (INPI, classe NCL 42)",
    "value": "944724159"
  },
  "foundingDate": "2017",
  "slogan": "Parceira Oficial da Meta — WhatsApp, Instagram, Messenger e Telegram numa instância só. Desde 2017.",
  "description": "Plataforma brasileira e Parceira Oficial da Meta (Meta Business Partner) para as APIs oficiais de WhatsApp (Cloud API), Instagram Direct e Messenger — os três numa única instância, com os mesmos endpoints e um único formato de webhook. Também oferece a API não oficial via QR Code e o Telegram, na mesma plataforma. No mercado desde 2017, com mais de 50 mil instâncias criadas, 99,9% de uptime e suporte humano 24/7 em português. SDKs oficiais para Node.js/TypeScript e PHP.",
  "knowsAbout": [
    "WhatsApp Cloud API oficial (Meta)",
    "API oficial de Instagram (Direct)",
    "API oficial de Messenger",
    "API multicanal Meta",
    "Meta Business Partner",
    "WhatsApp API",
    "API não oficial de WhatsApp",
    "automação de WhatsApp",
    "números virtuais",
    "webhooks"
  ],
  "sameAs": [
    "https://github.com/wame-api",
    "https://www.linkedin.com/company/wameapi",
    "https://www.instagram.com/wame.api/",
    "https://www.youtube.com/@wameapi"
  ],
  "contactPoint": {
    "@type": "ContactPoint",
    "contactType": "customer support",
    "url": "https://api-wa.me/contact",
    "availableLanguage": [
      "Portuguese"
    ]
  }
}
{
  "@context": "https://schema.org",
  "@type": "BlogPosting",
  "headline": "Onboarding de WhatsApp no seu SaaS com código de pareamento (sem QR, com a sua marca)",
  "description": "Conecte o WhatsApp do cliente dentro do seu SaaS, com a sua marca e sem QR Code: fluxo, estados da tela, backend em Node.js e webhook de conexão.",
  "image": "https://api-wa.me/blog/onboarding-saas-whatsapp-codigo-pareamento/opengraph-image",
  "datePublished": "2026-09-28",
  "dateModified": "2026-09-28",
  "author": {
    "@type": "Person",
    "name": "Raphael Serafim",
    "url": "https://github.com/raphaelvserafim",
    "sameAs": [
      "https://github.com/raphaelvserafim"
    ]
  },
  "publisher": {
    "@type": "Organization",
    "name": "api-wa.me",
    "logo": {
      "@type": "ImageObject",
      "url": "https://api-wa.me/images/screenshot.png"
    }
  },
  "mainEntityOfPage": {
    "@type": "WebPage",
    "@id": "https://api-wa.me/blog/onboarding-saas-whatsapp-codigo-pareamento"
  },
  "keywords": "api whatsapp não oficial, api não oficial whatsapp, código de pareamento whatsapp, onboarding whatsapp saas, pairing code whatsapp api, conectar whatsapp do cliente api, whatsapp white label api",
  "inLanguage": "pt-BR"
}
{
  "@context": "https://schema.org",
  "@type": "BreadcrumbList",
  "itemListElement": [
    {
      "@type": "ListItem",
      "position": 1,
      "name": "Home",
      "item": "https://api-wa.me"
    },
    {
      "@type": "ListItem",
      "position": 2,
      "name": "Blog da API do WhatsApp",
      "item": "https://api-wa.me/blog"
    },
    {
      "@type": "ListItem",
      "position": 3,
      "name": "Onboarding de WhatsApp no seu SaaS com código de pareamento (sem QR, com a sua marca)",
      "item": "https://api-wa.me/blog/onboarding-saas-whatsapp-codigo-pareamento"
    }
  ]
}
{
  "@context": "https://schema.org",
  "@type": "FAQPage",
  "mainEntity": [
    {
      "@type": "Question",
      "name": "Como conectar o WhatsApp do meu cliente sem mandar QR Code?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Na tela de onboarding do seu sistema, o cliente informa o número. Seu backend chama POST /{key}/instance/pairing-code com o phoneNumber, recebe o campo code e mostra os 8 caracteres na tela. O cliente digita o código no próprio celular, em Aparelhos conectados > Conectar com número de telefone. O webhook de conexão avisa quando terminou."
      }
    },
    {
      "@type": "Question",
      "name": "Posso chamar a API de pareamento direto do navegador?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Não deve. A key da instância autentica todas as chamadas e não pode ficar exposta no front. O navegador chama o seu backend, que conhece a key do cliente e fala com a API. O front só recebe o código e o status."
      }
    },
    {
      "@type": "Question",
      "name": "Como sei que o cliente terminou de conectar?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Configure o webhookConnection pelo PUT /{key}/instance. Quando o pareamento conclui, chega um evento com field connection e status open. Seu backend atualiza o banco e avisa o front por Server-Sent Events, WebSocket ou polling. Como rede de segurança, consulte GET /{key}/instance."
      }
    },
    {
      "@type": "Question",
      "name": "E se a instância já estiver conectada?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "A resposta do pairing-code vem com isConnected true e sem código. Trate como sucesso e pule para o próximo passo do onboarding. A API não gera código para sessão já pareada, porque isso derrubaria a conexão existente."
      }
    },
    {
      "@type": "Question",
      "name": "O cliente vai ver a marca WAME no onboarding?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Não precisa. A tela, as instruções e o código aparecem dentro do seu produto. No celular do cliente, a conexão aparece na lista de Aparelhos conectados como uma sessão de navegador. É um fluxo white label."
      }
    }
  ]
}
```
