Should an unknown phone result reject a signup?
A signup form calls a phone check and gets back something that is neither valid nor invalid. Either the result is unknown or the provider call failed. The tempting shortcut is to reject anything other than a clean pass. This article argues against that shortcut and walks through the four-branch synthetic example to show how to route each outcome. The core distinction is simple. An unknown result is missing evidence, not negative evidence. If you reject on missing evidence, every provider outage becomes a user lockout.
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
The decision in front of you is not whether a number is good. It is what your signup flow should do when the check cannot answer. Three outcomes look alike in code but mean different things. A confirmed invalid number is evidence. An unknown result means the check returned no usable signal. A provider failure means the check never completed. Only the first justifies blocking on format grounds. The other two need an explicit path: bounded recovery, manual review, or a possession step through an OTP provider you already run. Keep in mind what no phone check establishes. Validity and line type are different from possession and identity. The current free production route does not request line type, ownership, reachability or OTP delivery. Its approved controlled pilot covers basic number format and validity only.
What the downloadable example implements
The downloadable example runs offline in Python 3.10 or later. It needs no credentials and makes no network calls. It has four branches: normal, unknown, provider_failure and otp. Every output includes the fields mode, branch, state, valid, line_type, next, otp_sent and live_line_type_available. Two values never change across branches. The mode field is always synthetic_fixture. The otp_sent field is always false, so the example never sends a code. The live_line_type_available field is always false, which reflects that the free route does not return line type. The mobile line type you will see in the normal branch is fixture data, not something a live check would return. Any branch name outside the four raises UNSUPPORTED_FIXTURE. This example is not the same as the anonymous HTTP trial, which covers three scenarios. Do not treat results from one as results from the other.
Worked hypothetical: four signups, four routes
Imagine a hypothetical marketplace that receives four signups in one hour. The fixture's expected outputs map onto them as follows. The first signup takes the normal branch. The output is state simulated, valid true, line_type mobile and next continue_customer_policy. Your own rules decide what happens next. The check alone does not admit the user. The second signup takes the unknown branch. The output is state unknown, valid null, line_type null and next review_or_existing_otp. The account is held for review or sent to your existing OTP step. It is not rejected. The third signup takes the provider_failure branch. The output is also state unknown with valid null and line_type null, but next is bounded_retry_then_review. You retry a limited number of times and then hand the case to review. The fourth signup takes the otp branch, which models a request to prove possession. The output is state unsupported, valid null, line_type null and next customer_otp_provider. GridZen sends nothing here. That step belongs to your OTP provider. All four outputs carry otp_sent false.
Proposed application design for failure handling
The following is design guidance for your application, not behavior the fixture implements. Bound retries with a fixed attempt count and a deadline, so a provider failure cannot loop forever or block the form indefinitely. Store unknown and failed outcomes as their own state, kept separate from invalid. That way, reviewers and analytics do not mistake an outage for fraud. When review is the route, decide what the user may do while pending. You might let them browse but block payouts or listings until the case is resolved. If you route to OTP, call your existing provider and record its result separately from the phone check result. Do not let a null valid value coerce to false anywhere in your code.
Limits you should state plainly
The fixture produces synthetic outputs only. It proves branch handling in your code, not production success. Its tests cover simulated transitions, bindings, duplicate callbacks, restart and timeouts. They do not demonstrate live accuracy, external adoption or agent superiority. An OTP recommendation does not send a code and does not establish possession. Live route availability requires separate confirmation. Production phone checks are limited to the controlled pilot, and self-service live verification is disabled.
Acceptance checklist
Before you ship, confirm each of the following. - Running all four branches reproduces exactly the next values listed above. - Your code treats a null valid value as unknown, never as invalid. - The unknown branch never auto-rejects a signup. - The provider_failure branch retries a bounded number of times, then moves to review. - The otp branch calls only your own OTP provider and records otp_sent as false on the GridZen side. - No logic reads line_type from a live result. - Your code handles UNSUPPORTED_FIXTURE. - The unit tests pass. - Documentation does not claim ownership, reachability or identity from a phone check.
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.