---
title: "Um código só para a API oficial e a não oficial do WhatsApp (corpo da Cloud API)"
description: "Use o corpo da WhatsApp Cloud API na API não oficial da WAME: comece por QR Code, migre para a oficial ou rode as duas sem reescrever o envio nem o webhook."
url: "https://wame.api.br/blog/mesmo-codigo-api-oficial-e-nao-oficial-whatsapp"
language: "pt-BR"
og:type: "article"
published_time: "2026-09-28"
modified_time: "2026-09-28"
author: "Raphael Serafim"
keywords: "api whatsapp não oficial, api não oficial whatsapp, whatsapp cloud api formato, migrar api não oficial para oficial, api oficial e não oficial whatsapp, webhook formato meta whatsapp, whatsapp api compatível cloud api"
reading_time: "9 min de leitura"
---

# Um código só para a API oficial e a não oficial do WhatsApp (corpo da Cloud API)

> Use o corpo da WhatsApp Cloud API na API não oficial da WAME: comece por QR Code, migre para a oficial ou rode as duas sem reescrever o envio nem o webhook.

**Sim, dá para escrever uma única integração que serve a API oficial e a não oficial do WhatsApp: na WAME, o endpoint `POST /{key}/message` aceita exatamente o corpo da WhatsApp Cloud API e devolve o mesmo envelope de resposta, e o webhook no formato `meta` entrega os eventos no padrão da Meta.** Você começa pela API não oficial — conectando por QR Code, sem aprovação —, e quando quiser migrar ou rodar as duas, troca a `key` da instância em vez de reescrever envio e recebimento.

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

## O problema que isso resolve

Quem começa com uma API não oficial costuma escrever o código no formato daquela API: `to` e `text` num endpoint, `url` e `caption` noutro, webhook com o formato próprio da biblioteca. Funciona. Até o dia em que o cliente pede a API oficial — por exigência de compliance, volume de notificação ou política interna — e o time descobre que precisa reescrever a camada de mensagens inteira.

O caminho inverso também dói: quem nasceu na Cloud API e quer grupos, status ou ligações precisa aprender outro formato do zero.

A saída é escrever **uma vez, no formato da Meta**, e deixar a plataforma traduzir. É o que o `POST /{key}/message` faz.

## O envio: corpo da Cloud API, qualquer instância

O corpo é o mesmo que você mandaria para o `graph.facebook.com`:

```bash
curl -X POST "https://server.wame.api.br/SUA_KEY/message" \
  -H "Content-Type: application/json" \
  -d '{
    "messaging_product": "whatsapp",
    "recipient_type": "individual",
    "to": "5511999999999",
    "type": "text",
    "text": { "body": "Seu pedido saiu para entrega.", "preview_url": false }
  }'
```

Mídia usa `link`, como na Meta:

```bash
curl -X POST "https://server.wame.api.br/SUA_KEY/message" \
  -H "Content-Type: application/json" \
  -d '{
    "messaging_product": "whatsapp",
    "to": "5511999999999",
    "type": "document",
    "document": {
      "link": "https://exemplo.com/nota-fiscal.pdf",
      "filename": "nota-fiscal.pdf",
      "caption": "Sua nota fiscal"
    }
  }'
```

Os tipos aceitos nesse endpoint são `text`, `image`, `audio`, `video`, `document`, `sticker`, `location`, `reaction`, `interactive` (botões, lista e `cta_url`) e `contacts`. Se a `key` for de uma instância não oficial, a mensagem sai pelo número conectado por QR Code; se for de uma instância oficial, sai pela Cloud API. O seu código não sabe a diferença — e nem precisa saber.

## O recebimento: webhook no envelope da Meta

Do lado da entrada, configure o formato `meta`:

```bash
curl -X PUT "https://server.wame.api.br/SUA_KEY/instance" \
  -H "Content-Type: application/json" \
  -d '{
    "allowWebhook": true,
    "allowNumber": "all",
    "webhookMessage": "https://seu-dominio.com/webhook",
    "webhookFormat": "meta"
  }'
```

Todo evento passa a chegar como na Cloud API:

```json
{
  "object": "wame",
  "provider": "whatsapp",
  "entry": [{
    "id": "<instance-id>",
    "changes": [{
      "field": "messages",
      "value": {
        "messages": [{
          "from": "5511999999999",
          "id": "wamid.XXXX",
          "type": "text",
          "text": { "body": "qual o prazo de entrega?" }
        }]
      }
    }]
  }]
}
```

O mesmo extrator lê mensagens de instância oficial e não oficial. O campo `provider` indica o canal — o mesmo envelope vale para Instagram e Messenger, como explicado em [um webhook para WhatsApp, Instagram e Messenger](/blog/webhook-whatsapp-instagram-messenger-padrao-meta).

Durante uma migração, o valor `both` ajuda: a instância envia o formato nativo **e** o `meta`, e você troca os consumidores aos poucos sem janela de corte.

## O que muda de verdade entre oficial e não oficial

Formato igual não quer dizer regras iguais. Vale deixar explícito no código o que é de cada lado:

| Recurso | Não oficial | Oficial |
| --- | --- | --- |
| Texto livre para quem nunca falou com você | Sim (com responsabilidade) | Não: exige template aprovado |
| Janela de 24h | Não existe | Manda em tudo |
| Templates (`/message/template`, `/templates`) | Não se aplica | Sim |
| Grupos, comunidades, canais | Sim | Não da mesma forma |
| Status (stories) | Sim | Não |
| Enquete, figurinha, vídeo redondo | Sim | Não |
| Ligação por `/call` | Sim | Calling API própria |
| Flows, analytics, order-status | Não | Sim |

Quando o seu código manda para uma instância oficial um tipo de mensagem que ela não suporta, a API responde **422** com uma mensagem clara. É um erro de lógica — não tente de novo; trate como decisão de produto.

As diferenças de regra estão detalhadas em [API sem template e sem janela de 24h](/blog/api-whatsapp-sem-template-texto-livre) e no [comparativo oficial vs não oficial](/blog/whatsapp-api-oficial-vs-nao-oficial).

## Arquitetura: capacidades por instância

O jeito limpo de lidar com essas diferenças é não espalhar `if (oficial)` pelo código. Declare as capacidades de cada instância num lugar só e consulte antes de montar a mensagem:

```js
const INSTANCIAS = {
  loja_sp:   { key: process.env.KEY_SP,   oficial: false },
  loja_rj:   { key: process.env.KEY_RJ,   oficial: true  },
};

const capacidades = (inst) => ({
  textoLivreFrio: !inst.oficial,
  grupos: !inst.oficial,
  status: !inst.oficial,
  templates: inst.oficial,
});

async function enviar(instId, corpoMeta) {
  const inst = INSTANCIAS[instId];
  const r = await fetch(`https://server.wame.api.br/${inst.key}/message`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ messaging_product: 'whatsapp', ...corpoMeta }),
  });
  if (r.status === 422) throw new Error(`Tipo não suportado em ${instId}`);
  if (r.status === 429) throw new Error('Freio de envio: desacelere a fila');
  return r.json(); // mesmo envelope de resposta da Cloud API
}
```

Com isso, a regra de negócio pergunta "essa instância pode iniciar conversa com texto livre?" em vez de "essa instância é oficial?". Quando uma loja migrar, você muda um booleano.

Para recursos que só existem num lado — criar grupo, postar status, ligar —, use os endpoints específicos (`/groups`, `/status/text`, `/call`) guardados atrás da capacidade correspondente. São exatamente os recursos que tornam a camada não oficial interessante; veja [as vantagens da API não oficial](/blog/api-whatsapp-nao-oficial-vantagens).

## Três estratégias que funcionam

**1. Validar na não oficial, migrar depois.** Você conecta um número em minutos, testa o produto com clientes reais e, quando o volume ou o contrato exigir, cria a instância oficial e troca a `key`. O esforço da migração vira regra de negócio (templates para iniciar conversa), não reescrita de integração. O passo a passo de levar o número está em [migrar para a API oficial sem perder o número](/blog/migrar-whatsapp-api-oficial-sem-perder-numero).

**2. Rodar as duas lado a lado.** Oficial para notificação transacional em volume (confirmação, cobrança, rastreio, com template), não oficial para atendimento rico, grupos de clientes e status. O mesmo código envia para as duas; o que muda é a instância escolhida por tipo de mensagem.

**3. Oferecer as duas no seu SaaS.** Se você revende WhatsApp dentro de um CRM ou ERP, pode deixar o cliente escolher o tipo de conexão. A sua camada de mensagens não muda — só a tabela de capacidades. Mais sobre esse modelo em [WhatsApp API para CRM e SaaS](/whatsapp-api-para-crm-e-saas).

## Cuidados que não mudam com o formato

Escrever no formato da Meta não muda o que protege o número na camada não oficial:

- **Fale com quem pediu.** Texto livre é liberdade, não licença para disparo. A WAME não apoia spam.
- **Respeite o 429.** Ele aparece quando a instância fala com números novos demais em pouco tempo ou repete o mesmo texto para números demais. Desacelere a fila em vez de insistir.
- **Contato frio: texto antes de interativa.** Botões e listas podem não aparecer na primeira mensagem de uma conversa que nunca existiu. Abra com texto.
- **Ouça o evento de saúde.** No webhook de conexão chega o evento `health` com `should_pause`; quando vier verdadeiro, pare a fila.

Com isso, a taxa de bloqueio na camada não oficial fica muito baixa para quem usa do jeito certo. Os detalhes estão em [o que realmente derruba um número](/blog/api-whatsapp-nao-oficial-bane-o-que-derruba-numero).

## Conclusão

A escolha entre API oficial e não oficial não precisa ser uma aposta irreversível no código. Escrevendo o envio no corpo da Cloud API com `POST /{key}/message` e o recebimento no webhook `meta`, a mesma integração serve os dois tipos de instância: você começa rápido na não oficial, migra ou combina com a oficial trocando a `key`, e isola as diferenças reais — templates e janela de um lado, grupos, status e ligações do outro — numa tabela de capacidades por instância. A referência completa está na [documentação](/docs).

## Perguntas frequentes

### Posso enviar mensagem na API não oficial usando o corpo da Cloud API?

Sim. O endpoint POST /{key}/message da WAME aceita exatamente o corpo da WhatsApp Cloud API (messaging_product, to, type e o objeto do tipo) e devolve o mesmo envelope de resposta. Funciona em instâncias não oficiais e oficiais.

### O webhook também fica igual ao da API oficial?

Fica, se você configurar webhookFormat como meta em PUT /{key}/instance. Todo evento chega no envelope entry, changes, value da Cloud API, com o campo provider indicando o canal. Há também a opção both, que envia o formato nativo e o meta ao mesmo tempo, útil durante uma migração.

### O que não funciona igual nos dois tipos de instância?

Templates e a janela de 24 horas são regras da API oficial. Grupos, status, canais, enquetes, figurinhas e ligações pelo endpoint /call são recursos da camada não oficial. Enviar para uma instância oficial um tipo que ela não suporta devolve 422.

### Vale começar pela não oficial se pretendo ir para a oficial depois?

Vale, se o código for escrito no formato da Cloud API desde o início. Você valida o produto em minutos, sem aprovação, e quando migrar troca a key da instância em vez de reescrever a integração. O que muda é a regra de negócio: templates para iniciar conversa fora da janela.

### Dá para rodar oficial e não oficial ao mesmo tempo?

Dá. Cada instância tem sua key; o mesmo código envia para as duas. Um desenho comum é usar a oficial para notificações transacionais em volume e a não oficial para grupos, status e atendimento com recursos ricos.
