Is this number on WhatsApp? What a signup phone check can and cannot tell you
A public question asks how to know whether a phone number is WhatsApp-enabled before sending a message through the WhatsApp Cloud API. We cannot answer for that platform, do not represent the person who asked, and nothing here changes how WhatsApp behaves. The adjacent decision for a small B2B team is narrower: when a signup form collects a number, what may your application conclude before it tries to reach that number on any channel? This article runs the checked four-branch synthetic phone example. It shows that none of its outputs establish messaging-app presence, reachability or ownership, and it sets out how your code should route each result.
curl https://gridzen.ai/console/api/quickstart/trial \
-H 'Content-Type: application/json' \
-d '{"task": "signup_phone", "scenario": "success"}'The problem and the decision you own
Your team wants to send onboarding messages, and someone proposes filtering out numbers that are not on WhatsApp at signup. The tempting design calls a phone check, reads a pass as "reachable on WhatsApp" and treats anything else as a reason to reject the user. That design merges three questions. Is the number well formed and valid? What kind of line might it be? Will a specific messaging app deliver a message to the person who typed it? A phone check speaks at most to the first two. Whether a particular messaging service will deliver a message can only be learned from that channel, through its own documented rules, and usually only when you actually attempt delivery. So the decision is not how to detect WhatsApp presence with a phone check. It is what your signup flow should do with each phone-check outcome, and where a channel-specific delivery attempt belongs in that flow. That routing is a proposed application design. The fixture described below only demonstrates the inputs and outputs the routing must handle.
What the checked example actually implements
The downloadable example runs offline on Python 3.10 or later, with no credentials and no network calls. Its phone task takes one input, branch, and returns these fields: mode, branch, state, valid, line_type, next, otp_sent and live_line_type_available. In every branch mode is synthetic_fixture, otp_sent is false and live_line_type_available is false. There is no field for WhatsApp or any other messaging app, for reachability or for ownership. The line_type value of mobile in the normal branch is simulated data. The current free Basic Lookup route does not request line type, and it does not check ownership, reachability or OTP delivery. Even a mobile line type would not mean the number is registered with a particular app. Do not confuse this four-branch example with the separate anonymous HTTP trial, which covers three scenarios.
Worked hypothetical scenario with expected fixture outputs
Hypothetical: a team's signup form receives four numbers, and the developer maps each one to a branch to test routing before touching any live service. Branch normal returns state simulated, valid true, line_type mobile and next continue_customer_policy. Proposed handling: accept the number as a contact field and let your own policy decide whether to attempt a message later. Do not mark the user as WhatsApp-reachable. Branch unknown returns state unknown, valid null, line_type null and next review_or_existing_otp. Proposed handling: do not reject the user. Queue the account for review, or use an OTP flow you already run. Branch provider_failure returns state unknown, valid null, line_type null and next bounded_retry_then_review. Proposed handling: retry a fixed small number of times, then send the account to review. Never block signup indefinitely. Branch otp returns state unsupported, valid null, line_type null and next customer_otp_provider. Proposed handling: hand off to your existing OTP provider. The fixture sends no code, and otp_sent stays false.
Where a channel delivery attempt fits
If the business goal is to message users on a specific app, treat delivery as a later, separate step governed by that platform's documentation, consent requirements and response handling. Record the delivery outcome as its own state, for example attempted, delivered or failed according to what the channel reports. Keep it apart from the phone-check fields. A failed delivery should not rewrite valid to false, and a valid number should not be stored as "on WhatsApp." Keeping these states apart makes later fallback to SMS, email or review explicit and testable. This is a design proposal. The fixture neither implements nor tests any messaging channel.
Failure handling your code must own
The fixture names next steps. Executing them is the caller's job. An unrecognized branch raises UNSUPPORTED_FIXTURE, and your harness should treat that as a test error, not as a user verdict. Null in valid means no conclusion, not invalid. Bound your retries and log which branch produced each route. The engineering tests cover simulated transitions only. They do not prove production success. Live route availability needs separate confirmation, and synthetic results never grant real business permission.
Acceptance checklist
Before integrating, confirm each of the following. All four branches run, and the outputs match the fields above exactly. Unknown and provider_failure never cause automatic rejection. The otp branch hands off to your provider, and nothing waits for a code the fixture never sent. No stored field claims messaging-app presence, ownership or reachability. Delivery outcomes live in a separate state. Retries are bounded and then end in review. Every record keeps mode synthetic_fixture until an authorized live route is confirmed. Once these pass, decide whether to save a sandbox request for the free Basic Lookup route, keeping in mind that it does not return line type.
Run the checked synthetic example
Download and extract https://gridzen.ai/downloads/verification-delivery.zip, enter verification_delivery, then run with Python 3.10+. This local example makes no network calls. Use a fresh database for an independent identity run.
python3 delivery.py phone --branch unknown
python3 delivery.py phone --branch provider_failureSources and scope
https://gridzen.ai/guides/signup-phone-check/ https://gridzen.ai/guides/current-capabilities/ Based on the checked source snapshot and local fixture; proposed application rules are design advice, not proven production behavior. Written with AI assistance and reviewed independently.
Separately try three sandbox outcomes Create an account to continue integrating
A download does not prove a successful run. Local examples and the online sandbox are tested separately.