Bad phone numbers quietly destroy outbound campaigns. This script runs every number through the Neutrino API before it is trusted: it confirms the number is real, tells you whether it is a mobile or a landline, normalises it to E.164, and writes it to the right field. When a number fails, it raises a task in Zoho CRM instead of silently discarding it.
Updated in three places. The host moved — Neutrino documents the API at neutrinoapi.net now, not neutrinoapi.com. Authentication moved to the User-ID and API-Key headers; the old form-parameter style still works but is no longer the documented default. And the original used zoho.crm._create and zoho.crm._updateRecord, which are deprecated task names — the current ones are zoho.crm.createRecord and zoho.crm.updateRecord. The valid and type response fields are unchanged, so the logic still holds.
ZohoCRM.modules.ALL and to pass connection:"your_connection" to the zoho.crm tasks.// Trigger: on a Zoho CRM Lead, or from a Creator function
apiKey = "YOUR_NEUTRINO_API_KEY";
userId = "YOUR_NEUTRINO_USER_ID";
phoneNumber = if(!isBlank(Mobile), Mobile, Phone);
if(isBlank(phoneNumber))
{
return;
}
headerMap = Map();
headerMap.put("User-ID",userId);
headerMap.put("API-Key",apiKey);
bodyMap = Map();
bodyMap.put("number",phoneNumber);
// bodyMap.put("country-code","US"); // optional, helps with local-format numbers
resp = invokeurl
[
url : "https://neutrinoapi.net/phone-validate"
type : POST
parameters : bodyMap
headers: headerMap
];
// Neutrino signals auth and quota problems in the body, not the status code
if(resp.getJSON("api-error") != null)
{
info "Neutrino error " + resp.getJSON("api-error") + ": " + resp.getJSON("api-error-msg");
return;
}
isValid = resp.getJSON("valid");
if(isValid == false)
{
taskInfo = Map();
taskInfo.put("Subject","Phone not valid");
taskInfo.put("Description","Neutrino rejected " + phoneNumber + ". Please verify with the contact.");
taskInfo.put("What_Id",LeadID);
taskInfo.put("$se_module","Leads");
createResp = zoho.crm.createRecord("Tasks",taskInfo);
info createResp;
}
else
{
lineType = resp.getJSON("type"); // mobile | fixed-line | premium-rate | toll-free | voip | unknown
e164 = resp.getJSON("international-number");
updateMap = Map();
if(lineType == "mobile")
{
updateMap.put("Mobile",e164);
}
else
{
updateMap.put("Phone",e164);
}
updateResp = zoho.crm.updateRecord("Leads",LeadID.toString(),updateMap);
info updateResp;
}api-error field in the body. Without the check above, an expired key reads as “valid is null” and every number silently looks invalid.international-number, not the raw input. Normalising to E.164 on the way in is what makes deduplication work later.country-code, is-mobile, international-number. Pass output-case if you prefer camel or snake.voip deserves its own handling. A VoIP number is valid but often will not accept SMS. If you text your leads, branch on it rather than treating it as a mobile.This script is part of the free Creator Scripts Deluge Library.
All 39 Deluge scripts, the full Zoho Creator course, and every downloadable asset are now free. Get free access →