APINúmerosBreaking
Mudou o padrão: número novo não importa mais o histórico do aparelho
Osettings.historyImportEnabled passa a nascer false. Número criado de hoje em diante começa a existir no instante em que conecta — os até 30 dias de conversa que o aparelho entrega na conexão são descartados em vez de guardados.Números criados antes de hoje mantêm o valor que tinham. Nada foi reescrito, e número já conectado não é afetado.Se você quer o histórico, peça na CRIAÇÃO do número:POST /v1/numbers e o POST /v1/numbers/remote-pairing passam a aceitar o bloco settings inteiro, e o 201 devolve com o que o número foi criado.Criar e depois dar PATCH não funciona — e é por isso que o bloco existe. O WhatsApp entrega o histórico numa rajada única logo após a conexão; a flag é lida mensagem a mensagem conforme elas chegam; nada consegue pedir de novo. Um PATCH depois do POST corre contra essa rajada — e no fluxo de link de pareamento não tem chance nenhuma, porque quem abre o link conecta na hora.No painel, a pergunta agora faz parte do assistente de conexão, ao lado do telefone — o único momento em que a resposta ainda muda alguma coisa.Por que o padrão virou. Guardar um mês de conversa que ninguém pediu é o padrão caro: enche o /chat de histórico que o cliente já leu no celular, e cada reconexão replica tudo de novo. Desligado é a escolha reversível para um número novo; ligado não é, depois que a rajada passou.APINúmerosWebhooks
Desligar Canais do WhatsApp num número: ignoreNewsletters
Documentado. O settings.ignoreNewsletters do PATCH /v1/numbers/{id} descarta publicação de Canal (@newsletter) na entrada: não vira conversa, não vira mensagem guardada e não dispara message.newsletter. O padrão é false, então nada muda para quem hoje recebe canal.caption na entrada de 18 de agosto: aceito pela API e invisível em todo lugar onde alguém procuraria.Parece o ignoreGroups e não é um dos campos avançados. O provedor não-oficial aplica o ignoreGroups ele mesmo, e não tem gate nenhum para @newsletter — a publicação sempre chega na plataforma, então o único lugar onde dá para recusá-la é aqui. O campo aceita só true / false, nunca o null que devolve um campo avançado ao padrão do provedor: para canal não existe padrão do provedor para onde voltar.SDK Python: o numbers.update() copia o settings chave a chave de uma allowlist que não tinha esta — o campo era descartado em silêncio, com a chamada devolvendo 200 e os canais continuando a chegar. Corrigido, sai na próxima release; curl e playground não são afetados.APIMensagensMídia
Vídeo: .mov passa a ser convertido sozinho, e o teto de 16 MB ficou explícito
Corrigido. Enviar um vídeo .mov (QuickTime) para um número da Meta Cloud API falhava. A Cloud API aceita exatamente dois tipos de vídeo no upload — video/mp4 e video/3gpp — e o .mov, que é o que o iPhone e a maioria dos Android gravam, não é um deles. O envio morria com Received file of type 'video/quicktime'.Você não precisa converter nada: .mov e .webm agora viram MP4 automaticamente antes do envio. Quando os codecs já são compatíveis (H.264 + AAC, que é o que câmera de celular grava), é só troca de container, sem recompressão — não há perda de qualidade.Vídeo tem teto de 16 MB. O limite é do WhatsApp, não nosso, e não há como contornar. Acima disso o envio falha com o novo código META_MEDIA_TOO_LARGE, que agora traz o tamanho medido em vez de repassar o erro cru do provedor. Os outros tetos, para referência: imagem 5 MB, áudio 16 MB, documento 100 MB, figurinha 100 KB estática / 500 KB animada.Enviar vídeo como mediaType: "document" não devolve mais 202. Nunca funcionou — a classe documento não tem nenhum tipo de vídeo — e é uma tentativa comum de trocar o teto de 16 MB do vídeo pelo de 100 MB do documento. Em números da Meta Cloud API a requisição passa a ser recusada na entrada:422, antes de a mensagem entrar na fila, em vez de um 202 seguido de falha opaca. Números não oficiais (Pilot Status web) não mudam — eles entregam vídeo como arquivo sem problema, e a restrição é só da Meta.Quem decide a conversão é o arquivo, não a URL. O container é identificado pelos próprios bytes, então um .mov é convertido mesmo quando a URL não tem extensão nenhuma (uma chave .bin, uma URL assinada) ou tem uma extensão que engana. Isso importa porque vídeo com rótulo errado é o pior caso possível: a Meta aceita o upload, devolve um id de mensagem, e depois simplesmente não entrega — sem sinalizar falha nenhuma. Veja o guia de mídia.APIMensagens
Enviar figurinhas: mediaType: "sticker"
Novidade. O modo de mídia direta do POST /v1/messages/send aceita mediaType: "sticker". Funciona igual em números da Meta Cloud API e em números não oficiais (Pilot Status web) — cada um tem a própria rota de figurinha por baixo, e a API escolhe por você.caption junto é recusado com 400, em vez de entregar sem o texto — nenhum provedor tem campo de legenda em figurinha, então aceitar significaria o envio “dar certo” menos aquilo que você escreveu. mediaFilename é recusado pelo mesmo motivo, e figurinha não pode ser mídia de template: cabeçalho de template é TEXT, IMAGE, VIDEO ou DOCUMENT, e não existe cabeçalho de figurinha.O arquivo precisa ser image/webp e ter exatamente 512×512 pixels — estática até 100 KB, animada até 500 KB. A dimensão não é recomendação: uma figurinha 361×363 é recusada. Essas regras são do WhatsApp, não nossas, e quem aplica é ele: arquivo com tamanho, dimensão ou formato errado ainda é aceito aqui com 202 e falha depois, no webhook message.failed, como META_MEDIA_UPLOAD_ERROR (código 131053 da Meta) com o motivo exato em error_data.details. Converta antes de enviar em vez de contar com a API para barrar. Veja o guia de mídia.Se você mandava um .webp como mediaType: "image" para aproximar uma figurinha, aquilo entregava uma imagem comum — troque para "sticker" e você recebe uma figurinha de verdade.Também nesta entrega: caption agora aparece no playground da API. O campo sempre foi aceito em envios de imagem, vídeo e documento, mas faltava no spec OpenAPI, então o playground não tinha a caixa dele.APIAnúncios
De qual anúncio veio cada conversa — e o nome da campanha
Novos:GET /v1/referrals e GET /v1/referrals/summary. Quando alguém toca num anúncio
Click-to-WhatsApp e escreve para o seu número da API oficial, o WhatsApp nos diz qual anúncio
foi clicado. Isso vinha sendo recebido e descartado; agora é guardado e pode ser lido. O
primeiro endpoint lista as mensagens que vieram de anúncio, o segundo agrupa por anúncio com
a contagem de conversas.A Meta anexa a origem apenas na primeira mensagem da conversa e nunca repete, então uma
linha equivale a uma conversa iniciada por aquele anúncio. conversations conta conversas
distintas e messages conta mensagens — duas mensagens na mesma conversa são 1 e 2, então
conversations é a contagem de leads.Os nomes. Ao lado do sourceId cru, o objeto referral passa a trazer adName,
adsetId, adsetName, campaignId, campaignName e namesResolvedAt — os mesmos rótulos
que você usa no Gerenciador de Anúncios, em vez de um opaco 120249828053880703.Nenhum endpoint resolve nome sob demanda. A resolução é assíncrona, fora do caminho da
requisição, então consultar nunca dispara chamada à Marketing API e um null pode virar nome
minutos depois sem você fazer nada. O namesResolvedAt é o que torna isso observável: null
significa “ainda não resolvido”, enquanto data preenchida com nomes nulos significa
“perguntamos e a Meta não devolveu” — anúncio apagado, ou compartilhamento ainda ausente.A atribuição começa nesta versão: não há backfill, então conversas anteriores a hoje não
carregam origem de anúncio.Docs: Atribuição de Click-to-WhatsApp.ConnectEmbed
Estilizar o botão do Connect agora renderiza o botão
Mudança de comportamento. Um link de pareamento gerado combranding.button agora renderiza só o botão — sem cabeçalho, sem card, fundo transparente. Até hoje isso exigia um segundo passo que a resposta nunca mencionava: a sua página também tinha que anexar ?mode=button na URL do iframe. Mandar branding.button e abrir a remotePairingUrl devolvida entregava a página de conexão completa, o que se lia como “o meu estilo foi descartado”.Um objeto, os dois efeitos: estilize um botão e receba um botão. Cole a remotePairingUrl devolvida no navegador e você vê exatamente o que o seu cliente vai ver.Se você quer a página cheia num link estilizado, anexe ?mode=page (ou passe mode: "page" no SDK). É o novo opt-out explícito, e ele mantém o estilo do token no botão dentro do card. Nada mais mudou: link sem estilo continua renderizando a página, e ?mode=button explícito continua renderizando o botão. Links metaFlow: "credentials" e de QR não são afetados — formulário de credenciais e linha do tempo de QR não cabem num botão, então sempre renderizam a página.@pilot-status/embed 0.2.0. O ConnectOptions.mode passa a ter padrão automático em vez de "page": omita e o SDK resolve o modo pelo token, e então dimensiona o iframe de acordo (48 px para um botão, em vez de um mínimo de 520 px). Passe "page" ou "button" explícito para decidir você mesmo.Corrigido: o bundle do SDK servido estava velho. O embed.js entregue às páginas dos clientes não era reconstruído desde 1º de julho, ou seja, era anterior ao modo botão — o PilotStatus.connect.mount(el, { mode: "button" }) renderizava a página completa, em silêncio, para todo mundo que usava o SDK. Reconstruído; o caminho de iframe cru nunca foi afetado.Corrigido: a doc mandava carregar o SDK de um host que não existe. Quatro páginas — as duas de Incorporar Conexão e as duas de Incorporar Chat — traziam <script src="https://embed.pilotstatus.com.br/embed.js">. Esse hostname não tem registro de DNS, então a tag de script não resolvia e o PilotStatus nunca era definido: nada na página funcionava, e o console do navegador culpava o DNS em vez de nós. O SDK sempre foi servido de https://pilotstatus.com.br/embed.js (que é o que a página de Sessões de Embed já usava). As seis referências agora apontam pra lá. Se você copiou o trecho antigo, troque essa URL.Docs: Embedded Signup e Modo botão.WebhooksDocs
Todos os eventos de webhook num lugar só — inclusive os da Meta
A página Eventos de webhook agora abre com um mapa de qual vocabulário cada número fala, e documenta o lado da Meta Cloud API que faltava: os 23 nomes de campo assináveis (messages, message_echoes, os cinco campos de template, phone_number_quality_update, a família de conta, calls, flows, os quatro campos de grupo, payment_configuration_update, user_preferences), o que cada um reporta e quais exigem plano pago.Também escrito por extenso pela primeira vez: número Meta entrega o envelope nativo da Meta e nunca message.received (o events: ["*"] não converte); cada mudança é entregue sozinha, então entry e entry[0].changes têm sempre exatamente um elemento; e nove campos da Meta nunca são encaminhados a webhook de cliente, nem para assinatura "*" — account_alerts, automatic_events, history, messaging_handovers, partner_solutions, security, smb_app_state_sync, standby, tracking_events.APIWebhooks
message.stories, e eventos de grupo/canal deixam de ser exclusivos de plano pago
Evento novo: message.stories. Status (stories) publicados pelos seus contatos passam a ser entregues como evento de webhook, com a mídia re-hospedada em mediaLink. Assine o evento — ou o curinga "*" — e ele começa a chegar.É dirigido por demanda, como grupo: o provedor não envia Status enquanto ninguém pedir, e volta a não enviar quando a última assinatura sai. Isso é proposital. Antes desta mudança um número conectado recebia o Status de todo contato que enxergava e a plataforma descartava todos no fim do pipeline — medido em 1.869 eventos por dia, 17% de tudo que entrava na ingestão, sem nenhum consumidor.Status não é persistido: não cria conversa nem mensagem, e não aparece em GET /v1/messages. O WhatsApp expira stories em 24h; o mediaLink que re-hospedamos é durável, o story não. Também não há campo to — um Status é difundido para a lista de contatos de quem publica, não endereçado ao seu número.message.group, message.newsletter e message.stories deixam de ser exclusivos de plano pago. Eles ficavam escondidos do seletor de eventos em planos não pagos; essa restrição era legado e foi removida. Os três são selecionáveis em qualquer plano.APIWebhooksDashboard
Configuração do número, e histórico não inunda mais o seu webhook
Mudança de comportamento. Quando um número conecta, o WhatsApp entrega ao provedor o histórico do aparelho. Até agora essas mensagens antigas eram encaminhadas ao seu webhook comomessage.received / message.group / message.newsletter — ou seja, cada reconexão re-entregava até 30 dias de conversa, sem nada no payload que permitisse distinguir isso do tráfego que tinha acabado de chegar. Elas continuam sendo importadas para o chat; deixaram de ser entregues. Se quiser o comportamento antigo num número, ligue settings.webhookHistoricalMessages.createdAt passou a significar o que diz. Nos webhooks de mensagem ele carrega quando a mensagem realmente aconteceu, segundo o provedor, em vez do momento em que a processamos. Mesmo campo, mesmo tipo, mesmo formato ISO 8601.Novo: PATCH /v1/numbers/{id}. Configuração por número, parcial — política de retenção mais um bloco settings com o comportamento do histórico e, para números não-oficiais (conectados por QR), os advanced settings do provedor: rejectCall, msgRejectCall, alwaysOnline, readMessages, ignoreGroups, ignoreStatus. Veja a referência. Se você chamava POST /v1/numbers/{id}/settings, essa rota nunca existiu e vinha respondendo 404 em silêncio.Caminho /v1 desconhecido agora devolve JSON. Um caminho errado renderizava a página HTML de 404, o que quebrava clientes HTTP tipados sem dizer o motivo. Agora responde { "error": "Not found", "code": "ROUTE_NOT_FOUND" } como todo o resto da API.Disponível nos SDKs Node (0.5.0), Python (1.4.0) e n8n (1.3.0), e no servidor MCP.API
Endpoint de logout de instância WhatsApp
Novo endpointPOST /v1/numbers/{id}/logout para desconectar uma instância WhatsApp sem removê-la do banco de dados. Isso é útil quando você precisa desconectar um número temporariamente para solução de problemas ou reconexão a um dispositivo diferente, sem perder a configuração da instância. Veja a referência de POST /v1/numbers/{id}/logout.API
Nota de voz com waveform (voice mediaType)
Um novo "voice" mediaType permite controlar como a mensagem de áudio é renderizada. "audio" envia uma nota de voz (PTT) no player padrão; "voice" envia com a forma de onda (ondinha) visível. Em números Meta Cloud API a waveform é ativada quando o servidor envia voice: true no payload de áudio. Ambos os tipos são normalizados no servidor para OGG/Opus mono (metadados removidos, start_time zero), garantindo que todo áudio seja compatível mesmo quando o upload original era um WebM do navegador ou uma gravação do iOS. Veja a referência de POST /v1/messages/send.APIDashboard
Carrossel: preview no editor, variáveis e o OpenAPI
Montar um carrossel no editor de templates ficou fiel de ponta a ponta. O preview ao vivo volta a renderizar a tira de cards (antes não mostrava nada), o editor aplica a exclusividade do carrossel — um carrossel não leva cabeçalho, botões de template, botão de lista nem card de pedido, então esses controles somem ou desabilitam enquanto há um carrossel — e{{variáveis}} dentro de um card (o corpo ou um botão) passam a ser reconhecidas e substituídas no preview, em vez de ficarem como token cru.No lado da API, o campo carousel entrou no OpenAPI de POST /v1/messages/send, então ele aparece no playground interativo e nos clientes gerados. Também corrigimos a doc: um botão de URL no carrossel de sessão só é impossível em números Meta — em números não oficiais (Pilot Status web) o botão de URL sai no avulso.APIDashboard
Mensagens em carrossel
Envie um carrossel — um conjunto de cards de mídia rolável na horizontal — numa única mensagem. Um novo campocarousel em POST /v1/messages/send carrega de 2 a 10 cards, cada um com sua própria imagem, uma linha curta de texto e até dois botões, e o editor de templates ganha um construtor de carrossel com preview ao vivo e arrastável, para você reordenar os cards enquanto monta. Um carrossel de sessão é livre e não precisa de aprovação, mas seus botões são apenas de resposta rápida e ele só é entregue dentro da janela de atendimento de 24 horas — a mesma requisição funciona em números oficiais e não oficiais. Um carrossel de template é um template aprovado pela Meta, então é entregue a qualquer momento e um card pode combinar um botão de resposta rápida com um botão de URL.API
A exclusão de template diz a verdade
DELETE /v1/templates/{id} não reporta mais sucesso quando a Meta se recusa a remover um template. Quando a Meta rejeita a exclusão — por exemplo, quando o token de acesso não tem permissão na conta do WhatsApp Business — o endpoint agora responde 409 com uma mensagem bilíngue nomeando o template e o motivo, e o template é mantido localmente, porque ainda existe na Meta. Só uma remoção genuína dos dois lados retorna { "deleted": true }.DashboardChat
Botões, carrosséis e cards de pedido entregues aparecem no chat
Mensagens que chegam com botões, um carrossel ou um card de pedido agora aparecem como seu balão de verdade na conversa e nos logs de mensagens, em vez de virarem texto puro. Respostas de template mostram seus botões, carrosséis rolam pelos seus cards e cards de pedido listam seus itens — então a conversa é lida do jeito que o destinatário realmente viu.Dashboard
Número Meta com acesso revogado é detectado
Quando um número conectado pela API oficial da Meta perde o acesso — o app foi removido da conta do WhatsApp Business, ou a própria WABA foi excluída — o painel agora detecta e marca o número com o selo “Conexão perdida”. Antes o número simplesmente ficava mudo, sem nenhum sinal de que a Meta havia cortado o acesso; agora o selo avisa para você reconectar.Correção
Links de botão de URL e contagem de variáveis de template
Os exemplos de botão de URL não duplicam mais a URL base quando o valor de exemplo já a inclui, então o link do preview e do envio é o real. E o envio de template agora passa as variáveis do próprio corpo, então um template que usa uma{{variável}} tanto no corpo quanto num botão não falha mais com erro de contagem de parâmetros.Conexão
Embed só do botão para o Embedded Signup
O Embedded Signup hospedado ganha um modo de embed só do botão: coloque apenas o botão de conectar do Facebook na sua própria página, em vez do fluxo inteiro. O estilo do botão viaja no token do embed, e uma conexão concluída retorna já pareada com o número conectado.API
A chave de API de tenant agora age em qualquer número
A chave com escopo de tenant gerenciava números mas não podia usá-los — enviar exigia uma chave separada por número. Agora ela chama qualquer endpoint por número, de qualquer número do tenant, inclusive envio, indicando o número no cabeçalhox-whatsapp-number-id (aceita o id devolvido por GET /v1/numbers). Sem o cabeçalho, os endpoints por número continuam respondendo 403 TENANT_SCOPE_NOT_ALLOWED; um id de outro tenant responde 404. Veja Autenticação.DashboardWebhooks
Entregas de webhook pelo número ativo
A tela de Webhooks lista as entregas do número selecionado. As entregas gravadas sem número — eventos de status de mensagem — apareciam em todos os números ao mesmo tempo; agora são atribuídas ao número que as gerou.DashboardTemplates
Listas e pagamentos como botões de template
O Botão de Lista no editor de template monta uma lista interativa — texto do botão, seções e opções — com contadores ao vivo e um preview que abre as opções numa gaveta inferior, como o próprio WhatsApp faz. Um template com lista é enviado como mensagem interativa, e não como template aprovado: em número oficial ele não vai para aprovação da Meta e só é entregue dentro da janela de 24 horas — o editor avisa isso enquanto você monta.O Botão de Pagamento reúne as duas formas de cobrança num lugar só: o botão de copiar código PIX e o card de pedido com itens, que antes ficava numa seção separada abaixo do editor. Templates salvos antes continuam funcionando igual.Dashboard
Detecção de número que parou de receber
Uma sessão do WhatsApp pode travar só de um lado: o número continua enviando, a conexão se diz saudável e nenhuma mensagem entra por horas. O painel passa a acompanhar o ritmo de recebimento de cada número e sinaliza quando as mensagens param de chegar enquanto o envio continua funcionando — o selo deixa de afirmar uma saúde que não foi verificada.Dashboard
Shadowban web sinalizado já na primeira recusa
Quando o WhatsApp recusa envios por uma conexão não-oficial, o número passa a ser sinalizado na hora, em vez de só após três recusas na mesma janela — quem envia pela API poucas vezes por semana podia ficar semanas bloqueado com o selo verde. A sinalização se resolve sozinha assim que um envio volta a funcionar.Dashboard
Monte listas direto do chat
O composer do chat ganha a ação Lista: monte o texto do botão, as seções e as linhas com validação ao vivo e preview em tempo real, e envie — tanto em números oficiais quanto não oficiais. Listas enviadas agora aparecem como um balão de lista de verdade na conversa e nos logs de mensagens, e responder a uma mensagem ao enviar a lista mantém a citação.API
Mensagens de lista
Novo campolist em POST /v1/messages/send — envie uma lista interativa de seleção única: text vira o corpo da mensagem e buttonText abre um menu de até 10 linhas agrupadas em até 10 seções. Funciona em números oficiais e não oficiais com a mesma requisição, e a seleção do destinatário chega como uma resposta de entrada normal.DashboardTemplates
Insights de template
Todo template já enviado à Meta ganha um botão de insights na lista de templates: enviadas, entregues e lidas com taxa de leitura, cliques por botão, selos de qualidade e status, e seletor de período de 7/30/90 dias — usando o template analytics da Meta (habilitado automaticamente na sua conta na primeira abertura).Dashboard
Preview do perfil comercial nos números oficiais
O bloco de um número conectado pela API oficial da Meta agora mostra o preview do perfil comercial do WhatsApp exatamente como os clientes veem — foto, nome, telefone, descrição, categoria e site — com um botão Compartilhar que copia o linkwa.me do número.APITemplatesPagamentos
API de janela de atendimento, preview por tipo de conexão e pagamentos PIX
Novo endpointGET /v1/service-window — verifique se a janela de atendimento de 24 horas está aberta ou fechada para um contato antes de enviar: passe destinationNumber e receba { open, windowType, lastInboundAt, expiresAt }. Números Meta reportam a janela real de 24h; números não oficiais sempre reportam aberta.Preview do editor de templates agora mostra exatamente o que o destinatário vê para o número conectado: o card de template da Meta em números oficiais, e a forma entregue (texto + botões) em números não oficiais — com substituição ao vivo das {{variáveis}} usando seus valores de exemplo, e o bloco de preview acompanhando o scroll da página.Botão de pagamento PIX (PAYMENT_REQUEST) agora funciona em todos os tipos de número: números oficiais com WhatsApp Pay renderizam o card de pagamento nativo, e números não oficiais entregam um botão “Copiar código Pix” com o BR Code completo (sem limite de tamanho).Card de pedido itemizado: templates podem carregar um bloco de pedido (itens, quantidades, total e forma de pagamento). Números não oficiais EVO_V2 entregam como um card de pedido de verdade — acompanhado do texto e botões do template numa primeira mensagem quando presentes. Campos numéricos (preço, quantidade, totais) aceitam {{variável}} resolvida no envio.Também: o modal “enviar pela API” agora mostra o nome do template como templateId, e a submissão de templates ORDER_DETAILS à Meta passa a ser tentada para contas com pagamentos habilitados em vez de recusada localmente.API
API de preços de mensagem
Novo endpointGET /v1/meta/pricing — o preço por mensagem publicado do Meta / WhatsApp para um mercado + moeda + categoria (ex.: ?market=BR¤cy=BRL&category=marketing → { "pricePerMessage": 0.3217 }). Chame sem parâmetros para listar mercados, moedas e categorias, e adicione ?tiers=1 para os volume tiers. Também disponível como ferramenta MCP meta_pricing_get e no playground interativo.API
Liste seus logs de mensagem pela API
Novo endpointGET /v1/messages — pagine as mensagens enviadas e recebidas pelo seu número sem abrir o painel. Filtre por direção, status, período e número de telefone; cada linha traz o mesmo messageId que você já usa em GET /v1/messages/{id}, então uma chamada de lista e uma de status conversam entre si. Também disponível como ferramenta MCP messages_list.Dashboard