Jindal India — Mobile App API Handover
1. Project Overview
This backend service powers the Jindal India mobile app (Retailer & Dealer modules). It exposes APIs for:
Dealer/Retailer registration
Login & authentication
Password management (encrypt/decrypt, reset)
Notifications & mail triggers
Utility functions (random password generation, global variables)
The APIs integrate with Zoho CRM (for user data storage, auth validation, and mail workflows). Notifications are triggered on key state changes (e.g., activation of a Retailer).
2. Architecture
Backend: Zoho Deluge
4. API Endpoints
Retailer APIs
POST /retailer/register → Register a retailer in CRM
curl --location 'https://www.zohoapis.in/crm/v7/functions/registeruserapi/actions/execute?auth_type=apikey&zapikey=1003.bf06a30b1844b21cc47b37e0587bffe8.ae7fb8c43e6cc0eebcc3f0bd787cab99' \
--data-raw '{
"data": {
"Last_Name": "Hashib Raja",
"Email": "hashib@extensioncrm.com",
"Company": "Marrier Pvt Ltd",
"Retailer_Type": "Strong",
"Date_of_Onboarding": "2023-05-10",
"Date_of_Birth": "1990-08-15",
"Date_of_Marriaage": "2018-02-20",
"Account_Name": "1019885000000426373",
"Phone": "555-555-5555",
"Alternate_Phone_Number": "555-111-2222",
"City": "Delhi",
"State": "Delhi",
"Pin_code": "1019885000000590143",
"Zone": "North"
},
"send_email": true
}'Dealer APIs
POST /dealer/register → Register dealer
curl --location 'https://www.zohoapis.in/crm/v7/functions/registeruserapi/actions/execute?auth_type=apikey&zapikey=1003.bf06a30b1844b21cc47b37e0587bffe8.ae7fb8c43e6cc0eebcc3f0bd787cab99' \
--data-raw '{
"data": {
"Account_Name": "Hashib Account",
"Organization": "King Enterprises Pvt Ltd",
"Date_of_Onboarding": "2023-04-12",
"Email": "hashib@extensioncrm.com",
"Phone": "555-555-5555",
"Aadhaar_Number": "1234-5678-9012",
"Alternate_Phone_Number": "555-111-9999",
"PAN_Number": "ABCDE1234F",
"GST_Number": "22ABCDE1234F1Z5",
"City": "Mumbai",
"State": "Maharashtra",
"Pincode": "1019885000000590143"
},
"module": "Accounts",
"send_email": true
}'Auth APIs
POST /auth/login → Login with encrypted password
curl --location --request POST 'https://www.zohoapis.in/crm/v7/functions/loginretailerdealer/actions/execute?auth_type=apikey&zapikey=1003.bf06a30b1844b21cc47b37e0587bffe8.ae7fb8c43e6cc0eebcc3f0bd787cab99&identifier=hashib%40extensioncrm.com&password=DGSZJ5'POST /auth/reset-password → Reset password (uses random generator)
curl --location --request POST 'https://www.zohoapis.in/crm/v7/functions/resetprofilepasswordapi/actions/execute?auth_type=apikey&zapikey=1003.bf06a30b1844b21cc47b37e0587bffe8.ae7fb8c43e6cc0eebcc3f0bd787cab99&moduleName=Contacts&recordId=1019885000000958001&newPassword=Hashib%20Raja&sendEmail=true'Utility APIs
string standalone.generateRandomPassword(Int length)
{
if(length == null)
{
length = 6;
}
chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789@#%$";
password = "";
i = 0;
iterations = "".leftpad(length).toList("");
for each iteration in iterations
{
r = randomnumber(1,chars.length());
password = password + chars.substring(r,r + 1);
i = i + 1;
}
return password;
}string standalone.sendWelcomeEmail(String recordId,String moduleName,String plainPassword,String encryptedPassword,Map opts)
{
resp = Map();
resp.put("status","error");
resp.put("message","unhandled path");
if(opts == null)
{
opts = Map();
}
emailField = ifnull(opts.get("email_field"),"Email");
login_url = ifnull(opts.get("login_url"),"https://your-app-login.example.com");
logo_url = ifnull(opts.get("logo_url"),"https://www.jindalindia.com/images/demo/choose-jindal-log.png");
from_user = ifnull(opts.get("from_user"),zoho.adminuserid);
// validate inputs
if(recordId == null || recordId == "" || moduleName == null || moduleName == "")
{
resp.put("message","recordId or moduleName missing");
return resp.toString();
}
// fetch record by id (string)
rec = zoho.crm.getRecordById(moduleName,recordId);
if(rec == null)
{
resp.put("message","record fetch failed");
resp.put("module",moduleName);
resp.put("id",recordId);
return resp.toString();
}
toEmail = ifnull(rec.get(emailField),"");
if(toEmail == "" || toEmail == null)
{
resp.put("message","recipient email not found");
resp.put("email_field",emailField);
return resp.toString();
}
// determine plain temporary password
temp_pass = "";
if(encryptedPassword != null && encryptedPassword != "")
{
try
{
decRes = standalone.decryptPassword(encryptedPassword);
if(decRes != null && decRes != "")
{
// If decrypt helper returned a map-like string, try to parse and get the password key
try
{
decMap = decRes.toMap();
// common shapes: {"status":"success","password":"plain"} or {"status":"success","data":"plain"}
if(decMap.containsKey("password") && decMap.get("password") != null)
{
temp_pass = decMap.get("password");
}
else if(decMap.containsKey("data") && decMap.get("data") != null)
{
temp_pass = decMap.get("data");
}
else if(decMap.containsKey("result") && decMap.get("result") != null)
{
temp_pass = decMap.get("result");
}
else if(decMap.containsKey("status") && decMap.get("status") == "success" && decMap.containsKey("plain"))
{
temp_pass = decMap.get("plain");
}
else
{
// If parse succeeded but no expected key, assume decRes itself is the plain string
temp_pass = decRes;
}
}
catch (pe)
{
// not a map-string; assume decRes is plain password
temp_pass = decRes;
}
}
}
catch (e)
{
// decrypt call failed; fallback later to plainPassword
temp_pass = "";
}
}
// fallback to plainPassword when decrypt not available/failed
if((temp_pass == null || temp_pass == "") && plainPassword != null && plainPassword != "")
{
temp_pass = plainPassword;
}
// prepare user details
user_email = toEmail;
user_name = "";
if(rec.containsKey("Full_Name"))
{
user_name = ifnull(rec.get("Full_Name"),"");
}
else if(rec.containsKey("First_Name") || rec.containsKey("Last_Name"))
{
user_name = ifnull(rec.get("First_Name"),"") + " " + ifnull(rec.get("Last_Name"),"");
user_name = user_name.trim();
}
if(user_name == "")
{
user_name = user_email;
}
user_role = moduleName;
// role-based subject/heading
if(user_role == "Accounts")
{
subject_text = "Welcome Dealer — Your Jindal account and temporary password";
role_heading = "Dealer Account Created";
user_role = "Dealer";
}
else if(user_role == "Contacts")
{
subject_text = "Welcome Retailer — Your Jindal account and temporary password";
role_heading = "Retailer Account Created";
user_role = "Retailer";
}
else
{
subject_text = "Welcome to Jindal — Your account and temporary password";
role_heading = "Account Created";
}
// === THE HTML TEMPLATE YOU PROVIDED (kept intact) ===
msg_html = "<!doctype html><html><head><meta charset='utf-8'/><meta name='viewport' content='width=device-width'/><title>Welcome to Jindal</title></head><body style='margin:0;padding:0;background:#ffffff;font-family:Helvetica, Arial, sans-serif;'><table width='100%' cellpadding='0' cellspacing='0' border='0' style='padding:20px 0;'><tr><td align='center'><table width='600' cellpadding='0' cellspacing='0' border='0' style='max-width:600px;border:1px solid #eee;border-radius:8px;overflow:hidden;'><tr><td style='padding:20px 24px;text-align:center;background:#fff;'><img src='" + logo_url + "' alt='Jindal' width='180' style='display:block;margin:0 auto;max-width:80%;height:auto;'/></td></tr><tr><td style='padding:16px 24px;background:#fff;'><h1 style='font-size:20px;margin:0 0 8px 0;color:#cc0000;text-align:left;'>" + role_heading + "</h1><p style='margin:0 0 12px 0;color:#444;line-height:1.45;'>Hi <strong>" + user_name + "</strong>,<br/>Your account has been created successfully. Use the temporary password below to sign in, then update your password in your profile.</p><table cellpadding='10' cellspacing='0' border='0' width='100%' style='margin:12px 0 18px 0;background:#f8f8f8;border-radius:6px;'><tr><td style='font-size:14px;color:#333;'><div style='margin-bottom:6px;'><strong>Role:</strong> " + user_role + "</div><div style='margin-bottom:6px;'><strong>Email / Username:</strong> " + user_email + "</div><div style='margin-bottom:6px;'><strong>Temporary Password:</strong></div><div style='font-size:18px;font-weight:700;color:#cc0000;padding:8px 10px;border-radius:4px;background:#fff;display:inline-block;'>" + temp_pass + "</div></td></tr></table><p style='margin:0 0 18px 0;'><a href='" + login_url + "' style='display:inline-block;padding:10px 16px;border-radius:6px;text-decoration:none;font-weight:600;border:1px solid #cc0000;color:#fff;background:#cc0000;'>Sign in to Jindal</a></p><p style='margin:0;color:#666;font-size:13px;line-height:1.4;'>Note: This password is temporary — please change it inside your profile after first login. If you did not request this account, please contact support.</p></td></tr><tr><td style='padding:14px 24px;background:#fafafa;color:#777;font-size:12px;text-align:center;'>© " + zoho.currentdate.toString("yyyy") + " Jindal. All rights reserved.</td></tr></table></td></tr></table></body></html>";
// sendmail
try
{
sendmail
[
from :from_user
to :user_email
subject :subject_text
message :msg_html
]
resp.put("status","success");
resp.put("message","email sent");
resp.put("to",user_email);
resp.put("module",moduleName);
resp.put("record_id",recordId);
if(encryptedPassword != null && encryptedPassword != "")
{
if(temp_pass != null && temp_pass != "")
{
resp.put("password_source","decrypted");
}
else if(plainPassword != null && plainPassword != "")
{
resp.put("password_source","plain_fallback");
}
else
{
resp.put("password_source","none");
}
}
else if(plainPassword != null && plainPassword != "")
{
resp.put("password_source","plain");
}
}
catch (e)
{
resp.put("message","sendmail failed");
resp.put("details",e.toString());
resp.put("to",user_email);
}
return resp.toString();
}string standalone.customEncryptPassword(String plainText)
{
encrypted = zoho.encryption.base64Encode(plainText);
return encrypted;
}6. Sample cURL (from Postman)
Retailer Registration
curl --location 'https://www.zohoapis.in/crm/v7/functions/registeruserapi/actions/execute?auth_type=apikey&zapikey=1003.bf06a30b1844b21cc47b37e0587bffe8.ae7fb8c43e6cc0eebcc3f0bd787cab99' \
--header 'Content-Type: application/json' \
--data '{
"name": "ABC Retailer",
"phone": "9876543210",
"email": "retailer@test.com"
}'
Login
curl --location 'https://www.zohoapis.in/crm/v7/functions/loginretailerdealer/actions/execute?auth_type=apikey&zapikey=1003.bf06a30b1844b21cc47b37e0587bffe8.ae7fb8c43e6cc0eebcc3f0bd787cab99&identifier=hashib%40extensioncrm.com&password=DGSZJ5' \
--header 'Content-Type: application/json' \
--data '{
"email": "retailer@test.com",
"password": "encrypted_value_here"
}'
Reset Password
curl --location 'https://www.zohoapis.in/crm/v7/functions/resetprofilepasswordapi/actions/execute?auth_type=apikey&zapikey=1003.bf06a30b1844b21cc47b37e0587bffe8.ae7fb8c43e6cc0eebcc3f0bd787cab99&moduleName=Contacts&recordId=1019885000000958001&newPassword=Hashib%20Raja&sendEmail=true' \
--header 'Content-Type: application/json' \
--data '{
"userId": "12345"
}'
7. Blueprint Actions & Notifications
Retailer Activate → Mail Trigger (sends activation mail to retailer)

Dealer Register → Mail Trigger (sends welcome mail)
Password Reset → Mail Trigger (sends random password)
