Mensagens, BSUID e Graph API
O backend do parceiro envia diretamente à Meta usando o token da instância conectada. O Partner gerencia conexão, credenciais, capacidade e configuração do callback.
Credencial e IDs corretos
Use reveal-partner-instance-meta-token com o escopo instances.credentials.read. A resposta fornece meta_access_token, meta_phone_number_id, meta_waba_id e send_message_url. O token fica no backend; a Partner API Key não autentica chamadas à Graph.
curl --request POST 'https://api.hookcloud.app/functions/v1/swift-worker' \
--header 'apikey: SUA_PUBLISHABLE_KEY_DO_STAGE' \
--header 'Authorization: Bearer hc_partner_live_SUA_CHAVE' \
--header 'Content-Type: application/json' \
--data '{
"route": "reveal-partner-instance-meta-token",
"instance_id": "UUID_DA_INSTANCIA"
}'O PHONE_NUMBER_ID no caminho da Graph identifica o número comercial remetente. O BSUID identifica a pessoa destinatária. São identificadores diferentes, e o número comercial continua necessário para provisionar a conexão.
BSUID, user_id e username
| Campo | Onde aparece | Como usar |
|---|---|---|
contacts[].user_id / messages[].from_user_id | Webhook recebido da Meta | BSUID da pessoa dentro do portfólio do cliente empresarial. Preserve o valor completo e seu vínculo ao portfólio. |
recipient | JSON enviado a /messages | Recebe o BSUID ou Parent BSUID. Não se chama user_id no body de envio. |
parent_user_id | Webhook, somente para portfólios inscritos | Parent BSUID opcional. Só use se a Meta habilitou o recurso para os portfólios envolvidos. |
to | JSON enviado a /messages | Compatibilidade com telefone internacional. Se to e recipient forem enviados juntos, a Meta prioriza to. |
username | Perfil e webhooks | Nome opcional e mutável. Não é chave estável nem substituto de recipient. |
recipient_user_id | statuses[] | BSUID do destinatário no callback de status; correlacione também pelo statuses[].id (wamid). |
Use o BSUID recebido da Meta, sem remover o prefixo do país nem converter em número. Nunca gere um BSUID a partir do telefone. O mesmo usuário tem BSUIDs diferentes em portfólios diferentes. Exemplos desta página usam placeholders: substitua pelo identificador real do webhook.
Referência: Identificadores e nomes de usuário — Meta (atualização de 24/08/2026).
Enviar texto com BSUID
curl --request POST 'https://graph.facebook.com/v26.0/PHONE_NUMBER_ID/messages' \
--header 'Authorization: Bearer META_ACCESS_TOKEN' \
--header 'Content-Type: application/json' \
--data '{
"messaging_product": "whatsapp",
"recipient_type": "individual",
"recipient": "BR.BSUID_RECEBIDO_DA_META",
"type": "text",
"text": {
"preview_url": false,
"body": "Olá! Como podemos ajudar?"
}
}'Para responder a uma mensagem específica, adicione context: {"message_id":"wamid.DA_MENSAGEM_RECEBIDA"}. Quando houver necessidade de envio por telefone, substitua recipient por to; não mantenha os dois por engano.
Enviar template com BSUID
curl --request POST 'https://graph.facebook.com/v26.0/PHONE_NUMBER_ID/messages' \
--header 'Authorization: Bearer META_ACCESS_TOKEN' \
--header 'Content-Type: application/json' \
--data '{
"messaging_product": "whatsapp",
"recipient": "BR.BSUID_RECEBIDO_DA_META",
"type": "template",
"template": {
"name": "confirmacao_agendamento",
"language": {
"code": "pt_BR"
},
"components": [
{
"type": "body",
"parameters": [
{
"type": "text",
"text": "Ana"
},
{
"type": "text",
"text": "15/09 às 15h"
}
]
}
]
}
}'O template precisa existir na WABA, no idioma indicado, e estar aprovado e enviável. Consulte o catálogo e o guia de criação, edição e exclusão. Para parâmetros nomeados, cada parâmetro de texto inclui parameter_name com o nome definido no template.
Mídia: upload, envio, consulta e exclusão
Para usar um arquivo do backend, envie multipart, guarde o id retornado e use esse ID no payload da mensagem.
curl --request POST 'https://graph.facebook.com/v26.0/PHONE_NUMBER_ID/media' \
--header 'Authorization: Bearer META_ACCESS_TOKEN' \
--form 'messaging_product=whatsapp' \
--form 'file=@/caminho/imagem.jpg;type=image/jpeg'{
"messaging_product": "whatsapp",
"recipient": "BR.BSUID_RECEBIDO_DA_META",
"type": "image",
"image": {
"id": "MEDIA_ID",
"caption": "Imagem solicitada"
}
}| Operação | Método e caminho Graph |
|---|---|
| Obter URL e metadados | GET /v26.0/MEDIA_ID?phone_number_id=PHONE_NUMBER_ID |
| Baixar arquivo | GET MEDIA_URL com Bearer Meta; URL temporária |
| Excluir mídia | DELETE /v26.0/MEDIA_ID?phone_number_id=PHONE_NUMBER_ID |
A URL de download expira em cinco minutos. Consulte novamente o MEDIA_ID para obter outra. Para documento, use type:"document" e document:{id,filename,caption}; para áudio, type:"audio" e audio:{id}; para vídeo, type:"video" e video:{id,caption}. Os tipos também aceitam link HTTPS acessível à Meta quando suportado. Não envie id e link juntos.
Referência: Mídias, formatos e limites.
Outros tipos e confirmação de leitura
O mesmo POST /PHONE_NUMBER_ID/messages envia localização, contatos, reações, botões e listas, com a estrutura específica de cada type. O envio continua no backend do parceiro.
{
"messaging_product": "whatsapp",
"recipient": "BR.BSUID_RECEBIDO_DA_META",
"type": "interactive",
"interactive": {
"type": "button",
"body": {
"text": "Como podemos ajudar?"
},
"action": {
"buttons": [
{
"type": "reply",
"reply": {
"id": "suporte",
"title": "Suporte"
}
},
{
"type": "reply",
"reply": {
"id": "comercial",
"title": "Comercial"
}
}
]
}
}
}Para marcar uma mensagem recebida como lida, use o ID dessa mensagem. Não envie destinatário nesta operação:
curl --request POST 'https://graph.facebook.com/v26.0/PHONE_NUMBER_ID/messages' \
--header 'Authorization: Bearer META_ACCESS_TOKEN' \
--header 'Content-Type: application/json' \
--data '{
"messaging_product": "whatsapp",
"status": "read",
"message_id": "wamid.DA_MENSAGEM_RECEBIDA"
}'Referência: Tipos de mensagens.
Referência: Marcar como lida.
Resposta da API e status no webhook
{
"messaging_product": "whatsapp",
"contacts": [
{
"input": "BR.BSUID_RECEBIDO_DA_META",
"user_id": "BR.BSUID_RECEBIDO_DA_META"
}
],
"messages": [
{
"id": "wamid.DA_MENSAGEM_ENVIADA"
}
]
}HTTP 200 e messages[].id confirmam a aceitação do envio. A entrega e a leitura são confirmadas depois nos webhooks sent, delivered e read. Falhas podem chegar como failed, com errors[].
{
"object": "whatsapp_business_account",
"entry": [
{
"id": "WABA_ID",
"changes": [
{
"field": "messages",
"value": {
"messaging_product": "whatsapp",
"metadata": {
"phone_number_id": "PHONE_NUMBER_ID"
},
"contacts": [
{
"user_id": "BR.BSUID_RECEBIDO_DA_META"
}
],
"statuses": [
{
"id": "wamid.DA_MENSAGEM_ENVIADA",
"status": "delivered",
"recipient_user_id": "BR.BSUID_RECEBIDO_DA_META",
"timestamp": "1789055123"
}
]
}
}
]
}
]
}O webhook pode trazer contacts[].profile.username e recipient_parent_user_id quando disponíveis. Em falhas de envio por telefone, a Meta pode omitir recipient_user_id e contacts; use o wamid para correlacionar. Veja um parser que preserva os identificadores.
Username comercial e nomes reservados
Um username reservado pertence ao número comercial da empresa. Ele não é um destinatário de mensagem nem altera o BSUID das pessoas. Consulte primeiro o nome atual e as sugestões reservadas:
curl --request GET 'https://graph.facebook.com/v26.0/PHONE_NUMBER_ID/username' \
--header 'Authorization: Bearer META_ACCESS_TOKEN'curl --request GET 'https://graph.facebook.com/v26.0/PHONE_NUMBER_ID/username_suggestions' \
--header 'Authorization: Bearer META_ACCESS_TOKEN'curl --request POST 'https://graph.facebook.com/v26.0/PHONE_NUMBER_ID/username' \
--header 'Authorization: Bearer META_ACCESS_TOKEN' \
--header 'Content-Type: application/json' \
--data '{
"username": "nome_da_empresa",
"transfer_action": "none"
}'A consulta de sugestões retorna data[].username_suggestions[]. O nome atual retorna username e status; reserved indica reserva e não garante que já esteja visível aos usuários. A Meta controla elegibilidade, aprovação e disponibilidade.
Para remover o nome comercial, a API é DELETE /PHONE_NUMBER_ID/username. A alteração usa POST, não PATCH. transfer_action:"force_transfer" pode retirar um username de outro número do mesmo portfólio; não aplique automaticamente. A operação requer permissão Meta whatsapp_business_management e acesso ao ativo.
O campo de webhook business_username_updates comunica mudanças. Reivindicações ligadas ao Facebook ou Instagram podem exigir que o número comercial esteja vinculado à Página ou conta correspondente.
Referência: API de usernames, reservas e requisitos.
Falhas, repetição e limites de responsabilidade
Se houver timeout após um POST de mensagem, o resultado pode ser incerto. Não reenvie cegamente: uma segunda chamada pode gerar outra mensagem. Preserve o wamid quando recebido e use os callbacks para reconciliar. A chave de idempotência de algumas rotas HookCloud não torna a Graph API idempotente.
| Erro | Tratamento |
|---|---|
| 401/403 | Conferir token, permissões e acesso à WABA; reconectar se necessário. |
| 429 | Respeitar o limite informado e reduzir concorrência. |
| 131062 | Tipo de mensagem não aceita BSUID; verificar a exigência de telefone. |
| 131049 | Revisar elegibilidade e engajamento; não repetir imediatamente. |
| 132000 / 132018 | Corrigir a estrutura e os parâmetros do template. |
| 132001 | Revalidar nome, idioma e disponibilidade do template. |
O Partner cobre conexão, credenciais, catálogo, capacidade e configuração dos callbacks. A lógica de envio, filas, atendimento e processamento no ambiente externo pertence ao parceiro.
