WhatsAppMetaAutomationn8nAI News5 min read

Why WhatsApp Auto-Reply Fails When From Is BSUID (2026)

Why WhatsApp Auto-Reply Fails When From Is BSUID (2026)
Archit Jain

Author

Archit Jain

Full Stack Developer & AI Enthusiast

Table of Contents


Introduction

Your inbound webhook fires. The user message is real. Your n8n or Make flow reaches the reply step and dies with an invalid recipient error. You open the payload and see from set to US.13491208655302741918 - or worse, from is null and a BSUID field you never mapped holds the only usable identity.

This is not a Meta outage. It is WhatsApp reply automation BSUID friction: auto-replies built on the assumption that every sender arrives as an E.164 phone number. Meta's username rollout in July 2026 makes that assumption unsafe. Users who hide their number from your business still expect instant replies. Your stack must route on Business Scoped User ID (BSUID) instead.

This post covers runtime reply failures - not CRM schema design. For database migrations and contact keys, read Do WhatsApp Usernames Break Phone-Number CRM Keys?. For OTP and login flows that still need a phone, see REQUEST_CONTACT_INFO automation. Here we fix the moment your bot receives a message and cannot send the answer back. If your symptom is "webhook received, reply step red," you are in the right place.


Why does WhatsApp auto-reply fail when from is not an E.164 phone number?

Auto-reply breaks because your flow validates, stores, or echoes from as a phone number - and BSUID strings or null values fail those checks even though the message is valid. The webhook delivered correctly. Your integration rejected the identity.

Three failure modes show up in production every week:

Validation gates reject BSUID. Many n8n workflows start with an IF node: from matches ^\+\d{10,15}$. When from contains US.1349... or is empty, the branch routes to an error path. The auto-reply never runs.

Reply steps echo the wrong field. Classic pattern: map inbound from directly into outbound to. If from is null and BSUID lives in user_id or fromBSUID, your send node passes null or an empty string. Meta returns invalid recipient.

Contact lookup returns nothing. Flows that query CRM or a Postgres table by phone before replying find no match when only BSUID arrived. The reply step errors out or sends to a stale cached phone from a previous session.

Providers including Azure Communication Services now document that from and to may be empty or null when users interact via username. BSUID fields carry the routable identity instead. Your automation must treat that as normal - not malformed input.

If you run WhatsApp Claude CRM logging, the same payload that breaks reply routing also means Claude never gets conversation context. Fix routing first; logging follows.


What is WhatsApp reply automation BSUID and how does it show up in webhooks?

BSUID is Meta's per-business, per-user identifier that can replace phone numbers in webhook from fields when users adopt WhatsApp usernames and hide their mobile number from your brand. For reply automation, BSUID is the address you must store and send back to.

BSUID values follow a structured format documented across BSPs: a two-letter country prefix, a period, and a long numeric string. Example: US.13491208655302741918. Vendor wrappers may add prefixes like whatsapp: on Twilio's ExternalUserId. Strip only the vendor prefix - never alter the country code or the period inside the BSUID itself.

Field names vary by provider. Map all of these to one internal recipient_id:

Source Typical field Notes
Meta Cloud API user_id, recipient_user_id BSUID in messages and status webhooks
Azure ACS fromBSUID, toBSUID from may be null
Twilio ExternalUserId BSUID with optional whatsapp: prefix
Infobip / Vonage userId, BSUID in from May include phone alongside BSUID

Rollout is wave-based. Infobip documents username availability from July 7, 2026 for Wave 1 countries, with global expansion through September 2026. Before those dates you may still see BSUID alongside phone numbers as Meta populates the new fields. After username adoption, phone may be omitted entirely when the user has no recent phone-based history with your business.

The mental shift for reply automation:

Old assumption July 2026 reality
from = phone from may be BSUID, null, or both
Reply to = echo from Reply to = BSUID when phone absent
One identifier per user Phone optional; BSUID required for routing


How do I send a WhatsApp message without a phone number API using BSUID?

Put the full BSUID string in the to field of your send request - major providers auto-detect BSUID vs phone format and route accordingly. You do not need a separate "send without phone number" endpoint; you need a send path that accepts BSUID as a first-class recipient.

Azure Communication Services documents that from June 2026 its Send Notification API accepts either E.164 or BSUID in to, with automatic format detection. Vonage's Messages API matches this behavior. The rule across providers: include the entire BSUID value - country prefix, period, and all characters. Trimming or reformatting causes silent send failures that look like network errors.

Conceptual reply flow for a username-only user:

Inbound:  from = null, fromBSUID = "US.13491208655302741918"
Outbound: to   = "US.13491208655302741918"

For n8n HTTP Request nodes or Make's WhatsApp modules, pass BSUID exactly as received. Do not attempt to coerce BSUID into E.164. Do not strip the US. prefix thinking it is metadata - it is part of the address.

Store two fields on every inbound event before your reply logic runs:

  1. recipient_user_id (or normalized BSUID) - canonical send target
  2. recipient_phone (nullable) - display and fallback only

Your send node should read recipient_user_id first. Fall back to phone only when BSUID is absent and you have confirmed phone routing still works in your market.


What is recipient_user_id in Cloud API and how do I use it for replies?

recipient_user_id is the Cloud API field that carries BSUID for message routing when the user's phone number is not available in the webhook payload. Treat it as the reply address when from or wa_id no longer contain E.164.

In Meta's evolving webhook schema, older payloads keyed everything on wa_id (phone). Newer events add user_id and recipient_user_id alongside or instead of phone fields. Parsing order for reply routing:

  1. Read messages[0].from - if valid E.164, store as phone
  2. Read messages[0].from - if BSUID pattern, store as recipient_user_id
  3. If from is null, read user_id or nested identity fields
  4. Set outbound to = recipient_user_id when present, else phone

For Cloud API direct integrations, the send endpoint accepts BSUID in to the same way BSPs do. Your middleware layer should normalize whichever field your webhook vendor exposes into one internal key before any Claude or template logic runs.

If you use Claude MCP WhatsApp handoffs, pass recipient_user_id into the session context so draft replies route to the correct thread even when phone is null. MCP tools that "text the customer at from" will break without this field.


How do I fix n8n and Make webhook reply routing for BSUID-first automation?

Add a normalization node immediately after the webhook trigger that extracts BSUID into recipient_user_id, never validates from as phone-only, and maps that field into outbound to. This is a small logic change with outsized impact.

n8n pattern

After your Webhook node, add a Code or Set node:

const msg = $input.first().json.messages?.[0] ?? $input.first().json;
const from = msg.from ?? msg.wa_id ?? null;
const userId = msg.user_id ?? msg.fromBSUID ?? msg.recipient_user_id ?? null;

const isE164 = typeof from === 'string' && /^\+\d{10,15}$/.test(from);
const isBsuid = typeof from === 'string' && /^[A-Z]{2}\.[A-Za-z0-9]+$/.test(from);

const recipient_user_id = userId ?? (isBsuid ? from : null);
const recipient_phone = isE164 ? from : null;

return [{
  json: {
    ...msg,
    recipient_user_id,
    recipient_phone,
    reply_to: recipient_user_id ?? recipient_phone,
  },
}];

Downstream:

  • CRM lookup: filter on recipient_user_id first, then recipient_phone
  • Send node: to = {{ $json.reply_to }}
  • Error branch: only fire when both identifiers are null

Make pattern

Same logic in a Router or Set multiple variables module after the webhook. Replace any module that assumes from is always + followed by digits.

What to remove

  • IF nodes that mark non-E.164 from as invalid
  • Hardcoded to: {{from}} without BSUID fallback
  • Error notifications titled "malformed webhook" when from is null but BSUID exists

How should I test phone vs BSUID vs both identifiers in my flows?

Run three fixture payloads through every reply workflow before July 7, 2026: phone only, BSUID only, and both together. Infobip documents that webhooks may include both identifiers when phone is available, and BSUID alone when phone is hidden.

Test case 1: Phone only (legacy)

{
  "messages": [{
    "from": "+15551234567",
    "user_id": "US.13491208655302741918",
    "text": { "body": "legacy phone user" }
  }]
}

Expected: reply sends to phone or BSUID (either works); store both identifiers.

Test case 2: BSUID only (username user)

{
  "messages": [{
    "from": null,
    "user_id": "US.13491208655302741918",
    "text": { "body": "username only user" }
  }]
}

Expected: reply sends to US.13491208655302741918; no validation error; CRM creates record with null phone.

Test case 3: BSUID in from field

{
  "messages": [{
    "from": "US.13491208655302741918",
    "text": { "body": "from field is bsuid" }
  }]
}

Expected: parser recognizes BSUID pattern; reply routes correctly; no attempt to format as phone.

Log delivery receipts keyed by recipient_user_id. Failed sends with "invalid recipient" almost always mean a truncated or reformatted BSUID - compare outbound to character-by-character against inbound.

Whapi.Cloud describes a three-layer fallback: direct BSUID send, LID lookup when you have phone but no BSUID, phone retry when lookup fails. Implement at minimum layer one before July waves; add layers two and three if you serve mixed markets.


What daily and weekly checks keep reply automation running through July 2026?

Track reply success rate by identifier type, alert on null-from volume, and regression-test all three fixtures after every workflow change. BSUID rollout is gradual; monitoring catches market-specific breaks early.

Daily (5 minutes)

  • Check n8n/Make error queue for "invalid recipient" or validation failures on WhatsApp reply nodes
  • Count inbound events where from is null but user_id is present - confirm replies still sent
  • Spot-check one delivered reply to a BSUID-only thread in your WhatsApp manager UI

Weekly (30 minutes)

  • Re-run phone-only, BSUID-only, and both fixtures through lead capture, support, and time-to-lead flows
  • Compare recipient_user_id population in your conversation store vs inbound webhook volume
  • Review countries in Wave 1 (July 7) and Wave 2 (July 20) against your customer base - prioritize testing for those markets

Before July 7 checklist

  1. Normalization node deployed on every WhatsApp webhook flow
  2. Outbound send accepts BSUID in to
  3. No phone-only validation on from
  4. Three fixture tests pass in production-like environment
  5. CRM or conversation DB stores recipient_user_id on every thread
  6. On-call runbook documents BSUID reply failures (not "Meta is down")


When should I book a roadmap call to fix BSUID reply failures?

Book a 45-minute roadmap call when reply failures span more than one workflow - lead bots, support, Claude agents, ads handoffs - and you need a ordered fix list before July 2026 waves hit production revenue.

Symptoms that justify a session:

  • Webhooks arrive but multiple n8n flows error on the same BSUID payload shape
  • You fixed CRM schema per the BSUID CRM post but replies still fail at send time
  • Click-to-WhatsApp ads drive traffic you cannot answer when from is null
  • No one on the team owns identifier normalization across BSP, n8n, and Claude layers

You leave with a ranked backlog: parser changes, send routing, conversation storage, regression fixtures, and which markets to harden first. The goal is one afternoon of architecture clarity - not a six-month replatform.

Ready to stop losing replies to BSUID payloads? Book your roadmap call. We map your current webhook shape, patch reply routing, and set up the three fixture tests so auto-replies survive the username rollout.


Frequently asked questions

Quick answers on the topics covered in this article.

Users who adopted usernames and hid their phone number send BSUID-only payloads. Flows that still require E.164 in from skip those users. Phone-only users continue working until your market fully rolls out username behavior.

BSUID (Business Scoped User ID) is the technical address Meta assigns each user per business. When phone numbers are hidden, BSUID replaces from as the field you use to send replies.

Yes. Put the full BSUID string in the to field. Azure, Vonage, Infobip, and Meta Cloud API paths accept BSUID with automatic format detection. Do not modify the BSUID format.

Map to from user_id, fromBSUID, or recipient_user_id - whichever your webhook provides. Never leave to empty when a BSUID field exists on the payload.

No. Null from with a populated BSUID field is expected for username-only users. Treat it as "phone not shared," not "invalid message."

Both carry BSUID in Cloud API contexts. Vendor docs use different names; normalize them into one internal recipient_user_id field in your automation layer.

Yes. Any platform that validates or echoes from as a phone number fails the same way. Add a normalization step after the webhook trigger in Make.

Claude does not care about identifier format, but your orchestration must pass recipient_user_id into send tools. Stop instructing the model to "call the number in from" when from may be BSUID or null.

The CRM post covers database schema, contact merge, and primary keys. This post covers runtime reply failures: webhook parsing, outbound to routing, and n8n/Make send errors when from is not E.164.

When multiple workflows, countries, or integrations fail on the same payload change and July rollout dates risk live revenue. A roadmap session ranks parser vs send vs storage fixes in dependency order.

Share this article