As developers, we frequently switch between coding, debugging, and optimizing tasks. The last thing we want is to be burdened by manual user management. Adding users one by one to a channel is tedious and prone to errors, taking up more time than we could devote to actual development.
Let's explore how to create a custom workflow using Cliq's platform components to streamline the process of bulk-adding users to a channel via a Zoho Sheet or CSV file. This approach facilitates a smooth onboarding experience without the need for manual effort.
Pre-requisite :
Before beginning to script the code below, we must create a connection with Zoho Cliq. Once a connection is created and connected, you can use it in
Deluge integration tasks and
invoke URL scripts to access data from the required service.
Create a Zoho Oauth default connection with any unique name and the scopes - ZohoCliq.Channels.All and ZohoSheet.dataApi.ALL
Refer to the below links to learn more :
Step 1 : Creation of slash command
- After a successful login in Cliq, hover to the top right corner and click your profile. Post clicking, navigate to Bots & Tools > Commands.
- At your right, click the button - Create Command.
- To know more about slash commands and their purposes, refer to Introduction to slash commands.
- Create a slash command using your preferred name. Specify the following details: the command name, a hint (to give users an idea of what the command is for), and the access level.
- Finally, click "Save & edit code".

- inputs = List();
- inputs.add({"name":"channels","label":"Pick a channel","placeholder":"Choose a channel where you need to add members","max_selections":"1","multiple":false,"mandatory":true,"type":"native_select","data_source":"channels"});
- inputs.add({"name":"headername","label":"Header name","placeholder":"Email ID","hint":"In which the Email ID is present","min_length":"0","max_length":"25","mandatory":true,"type":"text"});
- inputs.add({"type":"radio","label":"Import type","name":"import_Type","hint":"Choose a type that you need to import users","options":[{"label":"CSV","value":"csv"},{"label":"Zoho sheet","value":"zohosheet"}],"trigger_on_change":"true"});
- return {"name":"addbulkuser","type":"form","title":"Add bulk users","hint":"To add maximum of upto 1000 users in a channel.","button_label":"Add Users","inputs":inputs,"action":{"type":"invoke.function","name":"addbulkusers"};
Step 2 : Scripting form function
- We need to create a function for the form that manages submission responses, including the Zoho Sheet link or CSV file, the name of the column containing the email addresses, and the channel details where users should be added in bulk.
- Hover to the top right corner and click your profile. After clicking, navigate to Bots & Tools > Functions.
- To your right, click the Create Function button.
- Name the function "addbulkusers," provide a description as desired, and select "form" as the function type. Then, click "Save and edit code," and paste the following code.
- emailIdList = list();
- successlist = list();
- failedlist = list();
- try
- {
- info form;
- formValues = form.get("values");
- columnName = formValues.get("headername");
- headerName = formValues.get("headername");
- if(formValues.get("import_Type").get("value") == "zohosheet")
- {
- url = formValues.get("url");
- spreadSheetId = url.getPrefix("?").getSuffix("open/");
- sheetName = url.getSuffix("?").getPrefix("&").getSuffix("=");
- worksheetname = sheetName.replaceAll(" ","%20");
- columnName = columnName.replaceAll(" ","%20");
- allDatas = list();
- params = Map();
- params.put("column_names",columnName);
- params.put("method","worksheet.records.fetch");
- params.put("worksheet_id",sheetName + "#");
- sheetDetails = invokeurl
- [
- url :"https://sheet.zoho"+environment.get("tld")+"/api/v2/" + spreadSheetId
- type :GET
- parameters:params
- connection:"addbulkusers"
- ];
- info sheetDetails;
- if(sheetDetails.get("status") == "success" && sheetDetails.get("records").size() <= 1000)
- {
- allDatas.addAll(sheetDetails.get("records"));
- }
- else if(sheetDetails.get("status") == "success" && sheetDetails.get("records").size() > 1000)
- {
- return {"type":"form_error","text":"I can only able to add 1000 user. Kindly try passing with 1000 records in the sheet!!!"};
- }
- else
- {
- return {"type":"form_error","text":"I can't find any email ids. Kindly re-check the column name and header row!!!"};
- }
- info "allData: " + allDatas.size();
- if(allDatas.size() > 1000)
- {
- return {"type":"form_error","text":"I can only able to add 1000 user. Kindly try passing with 1000 records in the sheet!!!"};
- }
- for each data in allDatas
- {
- if(data.get(formValues.get("headername")) == null)
- {
- return {"type":"form_error","text":"I can't find any email ids. Kindly re-check the column name and header row!!!"};
- }
- emailIdList.add(data.get(formValues.get("headername")));
- if(emailIdList.size() == 100)
- {
- channelID = formValues.get("channels").get("id");
- params = {"email_ids":emailIdList};
- info "Params: " + params;
- addUsers = invokeurl
- [
- url :environment.get("base_url") + "/api/v2/channels/" + channelID + "/members"
- type :POST
- parameters:params.toString()
- detailed:true
- connection:"addbulkusers"
- ];
- info "Adduser: " + addUsers;
- if(addUsers.get("responseCode") == "204")
- {
- successlist.addAll(emailIdList);
- }
- else
- {
- failedlist.addAll(emailIdList);
- }
- info "100: " + emailIdList.size();
- emailIdList = list();
- }
- }
- if(emailIdList.size() > 0)
- {
- channelID = formValues.get("channels").get("id");
- params = {"email_ids":emailIdList};
- info "Params: " + params;
- addUsers = invokeurl
- [
- url :environment.get("base_url") + "/api/v2/channels/" + channelID + "/members"
- type :POST
- parameters:params.toString()
- detailed:true
- connection:"addbulkusers"
- ];
- info "Adduser: " + addUsers;
- if(addUsers.get("responseCode") == "204")
- {
- successlist.addAll(emailIdList);
- }
- else
- {
- failedlist.addAll(emailIdList);
- }
- info "Email id: " + emailIdList;
- }
- info "Successlist: " + successlist;
- info "Failedlist: " + failedlist;
- if(successlist.size() > 0 && failedlist.size() > 0)
- {
- postMessage = {"text":"Successfully added " + successlist.size() + " member(s) and failed for " + failedlist.size() + " Member(s)"};
- }
- else if(successlist.size() > 0 && !failedlist.size() > 0)
- {
- postMessage = {"text":"Successfully added " + successlist.size() + " member(s)"};
- }
- else if(!successlist.size() > 0 && failedlist.size() > 0)
- {
- postMessage = {"text":"Adding members in channel failed for " + failedlist.size() + " member(s)"};
- }
- info zoho.cliq.postToChat(chat.get("id"),postMessage);
- }
- else
- {
- csvFile = formValues.get("csvFile");
- csvFile = csvFile.getfilecontent();
- allDatas = csvFile.toList("\n");
- i = 0;
- indexValue = 0;
- indexBoolean = false;
- for each data in allDatas
- {
- if(i == 0)
- {
- headers = data.toList(",");
- for each header in headers
- {
- info header;
- if(headerName == header)
- {
- indexBoolean = true;
- indexValue = headers.indexOf(headerName);
- }
- }
- if(indexBoolean == false)
- {
- return {"type":"form_error","text":"I can't find any email ids. Kindly re-check the column name and header row!!!"};
- }
- }
- else
- {
- emailIdList.add(data.get(indexValue));
- }
- i = i + 1;
- if(emailIdList.size() == 100)
- {
- channelID = formValues.get("channels").get("id");
- params = {"email_ids":emailIdList};
- info "Params: " + params;
- addUsers = invokeurl
- [
- url :environment.get("base_url") + "/api/v2/channels/" + channelID + "/members"
- type :POST
- parameters:params.toString()
- detailed:true
- connection:"addbulkusers"
- ];
- info "Adduser: " + addUsers;
- if(addUsers.get("responseCode") == "204")
- {
- successlist.addAll(emailIdList);
- }
- else
- {
- failedlist.addAll(emailIdList);
- }
- info "100: " + emailIdList.size();
- emailIdList = list();
- }
- }
- if(emailIdList.size() > 0)
- {
- channelID = formValues.get("channels").get("id");
- params = {"email_ids":emailIdList};
- info "Params: " + params;
- addUsers = invokeurl
- [
- url :environment.get("base_url") + "/api/v2/channels/" + channelID + "/members"
- type :POST
- parameters:params.toString()
- detailed:true
- connection:"addbulkusers"
- ];
- info "Adduser: " + addUsers;
- if(addUsers.get("responseCode") == "204")
- {
- successlist.addAll(emailIdList);
- }
- else
- {
- failedlist.addAll(emailIdList);
- }
- }
- info "Successlist: " + successlist;
- info "Failedlist: " + failedlist;
- if(successlist.size() > 0 && failedlist.size() > 0)
- {
- postMessage = {"text":"Successfully added " + successlist.size() + " member(s) and failed for " + failedlist.size() + " Member(s)"};
- }
- else if(successlist.size() > 0 && !failedlist.size() > 0)
- {
- postMessage = {"text":"Successfully added " + successlist.size() + " member(s)"};
- }
- else if(!successlist.size() > 0 && failedlist.size() > 0)
- {
- postMessage = {"text":"Adding members in channel failed for " + failedlist.size() + " member(s)"};
- }
- info zoho.cliq.postToChat(chat.get("id"),postMessage);
- }
- }
- catch (e)
- {
- info e;
- return {"type":"form_error","text":"I can't find any email ids. Kindly re-check the column name and header row!!!"};
- }
- return Map();
Step 3 : Configuring form change handler
- After copying and pasting the code into the form submission handler, navigate to the form change handler for the created form function.
- You can find this in the top left corner of the editor, where you will see an arrow next to the form submission handler. Clicking on this arrow will display the form change handler in a dropdown menu.
- Click it to edit the code in the form change handler, which is necessary for real-time modifications to a form's structure or behaviour based on user input in a specific field.
- targetName = target.get("name");
- info targetName;
- inputValues = form.get("values");
- info inputValues;
- actions = list();
- if(targetName.containsIgnoreCase("import_Type"))
- {
- fieldValue = inputValues.get("import_Type").get("value");
- info fieldValue;
- if(fieldValue == "csv")
- {
- actions.add({"type":"add_after","name":"import_Type","input":{"label":"CSV File","name":"csvFile","placeholder":"Please upload a zCSV File","mandatory":true,"type":"file"}});
- actions.add({"type":"remove","name":"url"});
- }
- else if(fieldValue == "zohosheet")
- {
- actions.add({"type":"add_after","name":"import_Type","input":{"name":"url","label":"Enter the sheet url","placeholder":"https://sheet.zoho.com/sheet/open/6xhgb324f142e91d845e5b4b472f7422379c9","min_length":"0","max_length":"400","mandatory":true,"type":"text","format":"url"}});
- actions.add({"type":"remove","name":"csvFile"});
- }
- }
- return {"type":"form_modification","actions":actions};

Business use cases:
- HR onboarding: Seamlessly add new employees to internal communication channels.
- Event management: Quickly invite attendees to event-specific channels.
- Education platforms: Enroll students in course groups in one go.
- Community building: Grow large communities by importing member lists effortlessly.
Bottom line
Bulk user addition in Cliq channels through Zoho Sheet or CSV files allows us to eliminate tedious tasks, reduce errors, and manage large-scale data effortlessly. Is onboarding consuming too much of your valuable development time? If so, it might be time to shake things up with a customized workflow!
We're here to help, so don't hesitate to reach out to support@zohocliq.com with any questions or if you need assistance in crafting even more tailored workflows.
Recent Topics
Zoho CRM Workflow Automation: Activate & Deactivate Workflows Using API
Zoho has now enabled: ✅ Activate / Deactivate workflows using API ✅ Schedule workflow activation & deactivation This is extremely useful for real-world automation use cases 💡 🧩 My Use Case I created a scheduled automation that: ☀️ Activates workflows
{Action Required} Re-authenticate your Google Accounts to Continue Data Sync
Hello Users! To align with Google’s latest updates on how apps access files in Google Drive, we’ve enhanced our integration to comply with the updated security and privacy standards, ensuring safer and more reliable access to your data. With this update,
Function #53: Transaction Level Profitability for Invoices
Hello everyone, and welcome back to our series! We have previously provided custom functions for calculating the profitability of a quote and a sales order. There may be instances where the invoice may differ from its corresponding quote or sales order.
Project-Based Inventory Consumption and Proforma Invoice in Zoho ERP
While working with customers across different industries, we have identified a few functional questions and gaps that commonly arise—especially for project-based and service-oriented businesses. Many organizations, such as those in shipping, construction,
[Free Webinar] Zoho RPA - OCR, PDF Automation, & More
Hello Everyone! Greetings from the Zoho RPA Training Team! We’re excited to invite you to our upcoming webinar on the latest release updates for Zoho RPA, where we’ll unveil powerful new capabilities designed to make your automation journey smarter, faster,
Zobot Execution Logs & Run History (Similar to Zoho Flow)
Dear Zoho SalesIQ Team, We would like to request an enhancement for Zoho SalesIQ Zobot: adding an execution log / run history, similar to what already exists in Zoho Flow. Reference: Zoho Flow In Zoho Flow, every execution is recorded in the History tab,
Global Search Settings
I'd love a way to remove some modules from being included in the global search. This would allow use to provide a better user experience, limiting the global search to only those modules that are regularly used removing any models used for background
Card Location in Zobot
Hello, when using the “Location” card in a codeless builder Zobot, the behavior in WhatsApp is inconsistent. When asking the user to share their location, they can type a message, which will return the message “Sorry, the entered location is invalid.
Automation Series: Auto-create Dependent Task on Status Change
In Zoho Projects, you can automatically create and assign a dependent task when a task’s status is updated. This helps teams stay aligned, ensures reviews happen on time, and reduces manual effort. In this post, we’ll walk through an easy setup using
Languages in Zobot
Hello, I have found a list of supported languages for the Zobot. The information specifies the languages are supported in the following 3 features: SalesIQ supports 34 different languages in the following features. Resources (Articles, FAQs, Small Talks)
Composite items inside of composite items; bill of materials needed
Hi Zoho and Everyone, I am evaluating whether Zoho Inventory will work for my small business. I grow and harvest herbs and spices but also get from wholesalers. I use all these items to make herbal teas, but also sell them as individual items on my Shopify store and Etsy. I discovered the composite item bundling and am wondering if I could get some assistance since there is no bill of materials: Our herbal company's best selling tea is a sleepytime tea. Sleepytime Tea can be purchased in three weights
Action required: Reauthorizing your Google account in Zoho Sign for automatic cloud backup to Google Drive
This is applicable to users who have already configured automatic cloud backup to Google Drive. Hi there! Google has mandated reauthorization of all preconfigured third-party integrations to ensure only the necessary scopes are shared as an improved security
Zoho CRM Layouts
I have customised all our modules, Leads, Contacts and deals, and within them, I have created lots of different layouts depending on the type of Lead or contact, for example. Since the new Zoho UI came out, they have all disappeared. I have gone into
Streamlining E-commerce Photography with AI Background Tools
Hey Zoho Community, I’ve been messing around with ways to make product images less of a headache for fashion brands on Zoho Commerce. You know how boring generic backdrops can get, and how much time traditional photoshoots eat up, right? I tried out this
WhatsApp IM in Zoho Desk always routes to Admin instead of assigned agent
Hello Zoho Experts, I connected WhatsApp IM to my Zoho Desk account. I only assigned my Customer Service (CS) agent to the WhatsApp channel, and I did NOT include Admin in this channel. However, every new WhatsApp conversation automatically gets assigned
hide resolution from help centre
to my surprise, i just found out that the resolution text is public in the helpcenter, even if 'notify customer' is off. is there a workaround to that? how do others deal with this? How zoho support does this and I don't think its used by Zoho in the first place. the resolution is meant to be private, not public
Zoho Analytics + Facebook Ads: Performance Alerts for Active Campaigns
Is it possible with integration of Zoho Analytics with Facebook Ads and set up alerts or notifications for active campaigns when performance drops? For example, triggering a notification if CTR goes below a defined threshold or if other key metrics (like
Multiple upload field CRM
I desperately need the functionality to add more than one upload field to web to contacts form. How can I do this?
Sort by age
It would be very helpful if there was a way to sort by age in the Age column. Please add this function if possible. Thanks!
Lookup Field Option Not Available in Customization
Hello, I am trying to customize different modules (e.g., Work Orders, Systems, and others), but I am unable to find the Lookup field option in the layout customization. When I go to: Setup → Customization → Modules and Fields → Add Field The Lookup field
Scheduled sending of a poll and its results
Is there a way to schedule sending a poll to all my users and have the results sent separately to the team?
Canvas View bug
I would like to report a bug. When clone a canvas view from an existing canvas view, if the original canvas view have canvas button with client script. Then the new create canvas view will have canvas button, it is make sense. But when I try to delete
Integrating Zoho Suite and apps more with Linux
I just got introduced with Zoho just couple of months ago, and I've already planned to contribute to it, even though it's not an open-source software. Still I have found it's potential to beat the tech giants and still being respective towards data privacy
Store Submitted Forms as PDF
Hi there, Is there a method to store Form submissions as a PDF in workdrive for archival? I set the form to email the submission to the user and an internal inbox but I'd really love to store the final form as PDF in workdrive automatically. I can't seem
System Components menu not available for Tablet to select language
I have attached a screenshot of my desktop, mobile, and tablet menu builder options. I am using 2 languages in my application. Language Selection is an option under the System Components part of the menu, but only for my desktop and phone(mobile). My
Separate Items & Services
Hi, please separate items and services into different categories. Thank you
CRM->INVENTORY, sync products as composite items
We have a product team working in the CRM, as it’s more convenient than using Books or Inventory—especially with features like Blueprints being available. Once a product reaches a certain stage, it needs to become visible in Inventory. To achieve this,
Add an option to disable ZIA suggestions
Currently, ZIA in Zoho Inventory automatically provides suggestions, such as sending order confirmation emails. However, there is no way to disable this feature. In our case, orders are automatically created by customers, and we’ve built a custom workflow
What's new in Zoho Sheet: Simplify data entry and collaboration
Hello, Zoho Sheet community! Last year, our team was focused on research and development so we could deliver updates that enhance your spreadsheet experience. This year, we’re excited to deliver those enhancements—but we'll be rolling them out incrementally
Zoho Creator Developer Console | Improved Distribution and Lifecycle Management for apps
Hello everyone, We're excited to introduce new enhancements now in the Zoho Creator Developer Console. These updates strengthen private app distribution through licensing controls and extend environment support across all installed apps, helping teams
[Webinar] Solving business challenges- Handling the challenge of transitioning to Zoho Writer from legacy tools
Moving to Zoho Writer is a great way to consolidate your business tools and become more agile. With multiple accessibility modes, no-code automation, and extensive integration with business apps and content platforms, Zoho Writer helps solve your organization's
Feature Request - Gift Cards or Gift Voucher Capability in Zoho Commerce
Hi Zoho Commerce team, I'm comming accross more and more retail businesses who sell gift cards. As there is currently no way to manage this in Zoho Commerce, it is a blocker to addoption. This is particularly popular in Europe and North America. I recently
Highlight a candidate who is "off limits"
Hello: Is there a way to highlight a candidate who is "off limits"? I would like to have the ability to make certain candidate and / or Client records highlighted in RED or something like that. This would be used for example when we may have placed a candidate somewhere and we want everyone in our company to quickly and easily see that they are off limits. The same would apply when we want to put a client or former client off limits so no one recruits out of there. How can this be done? Cheers,
Closing off tasks automatically based on project status
Is there a way to close off all open tasks when a project is set as Cancelled?
[Free webinar] Understanding connections and datasources in Zoho Creator - Creator Tech Connect
Hello everyone, We’re excited to invite you to another edition of the Creator Tech Connect webinar. About Creator Tech Connect The Creator Tech Connect series is a free monthly webinar featuring in-depth technical sessions designed for developers, administrators,
Bridge the Gap Between your Service and Finance Teams
In field service, the most expensive distance isn’t the drive to a customer’s home—it’s the gap between a finished job and a paid invoice. Zoho FSM leverages the power of Zoho Invoice to handle and manage billing operations. It enables you to: Instantly
Direct URL to "View Record"
I would like to create a button (Deluge Script) to jump to the "view record" without passing by the record menu, but I can not aford to find the right url. I don't want the "view record" as a single page. I want the "view record" in the application like the picture below: Thanks in advance for your help
Live Chat for user
Hi everyone, I’m new to Zoho Creator and wanted to ask if it’s possible to add a live chat option for all logged-in portal users so they can chat internally. I’m trying to create a customer portal similar to a service desk, but for vehicle breakdowns,
SalesIQ Chat Owner to CRM Lead Owner Mapping
There is no proper mapping between the SalesIQ chat owner and the CRM lead owner. When a chat is assigned to an agent, the lead created in CRM is often assigned to a different user, forcing admins to manually change ownership every time. This creates
Product line search in quotes
Is there a way to change the search setting when you add a product line to a quote. We have created a field in products called 'Part Number' and I would like when I'm adding a product line to the quote that I can search on that field. At the moment it only searches on product description. In products I can search on the 'Part Number' field Any help welcome.
Next Page