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
Updating records through Zoho Sheets View doesn't update timeline or trigger workflow rules
I have noticed that when i update a series of record with the zoho sheets view (see here http://d.pr/i/ahnR) it doesn't update timeline history or trigger workflow rules. I am using it in the Deals module. Looking forward for some more info. Denis
Manage control over Microsoft Office 365 integrations with profile-based sync permissions
Greetings all, Previously, all users in Zoho CRM had access to enable Microsoft integrations (Calendar, Contacts, and Tasks) in their accounts, regardless of their profile type. Users with administrator profiles can now manage profile-based permissions
inability to use different primary address on invoice per location
my company operates in two different locations with different email address. The problems then is the inability to edit the primary to suite the invoice for the second location.
AI Search and Record Retrieval Inside Zoho Creator – Is This Possible?
Is it possible to integrate an AI assistant into Zoho Creator that can intelligently search, retrieve, and analyze records within the application’s forms and reports? Can AI access and query existing Creator data securely using Deluge or APIs to provide
Rename Service Report
Some of our customers are requesting the name of the service report PDF to be in a specific format, for example, instead of REP-001.PDF some are requesting to include their name like customername.pdf. is that possible?
Smarter holiday planning with yearly-specific Holiday Lists
Hello everyone! Managing holidays and business hours is now easier and more efficient. Holiday Lists now support holidays that fall on different dates every year, while business hours now supports more than one holiday list. This helps businesses manage
AI Search and Record Retrieval Inside Zoho Creator – Is This Possible?
Is it possible to integrate an AI assistant into Zoho Creator that can intelligently search, retrieve, and analyze records within the application’s forms and reports? Can AI access and query existing Creator data securely using Deluge or APIs to provide
Scheduled AU Data Center Database Version Upgrade for Zoho Forms
Dear Zoho Forms' users, We would like to update you on a scheduled AU Data Center database version upgrade for Zoho Forms. Find the schedule below: Migration window: Sunday, 22nd February 2026 12.00 AM to 12.30 AM AEDT This migration is a part of our
Cannot get code to work with v2.mergeAndStore!
Please can someone help me pass subform items into a repeating mail merge table row using v2.mergeAndStore? I have a mail merge template created in Writer and stored in Workdrive. This template is referenced by a custom CRM function which merges all of
Hotmail is blocking the zoho mail IP
Greetings, Since last Tuesday (5 days ago today) I wrote to Zoho support and I still haven't received a single response (Ticket ID: 2056917). Is this how you treat people who pay for your email service? I am making this public so that those who want to
Zoho Bookings and Survey Integration through Flow
I am trying to set up flows where once an appointment is marked as completed in Zoho Bookings, the applicable survey form would be sent to the customer. Problem is, I cannot customise flows wherein if Consultation A is completed, Survey Form A would be
Zoho CRM Community Digest - December 2025 | Part 2
Hello Everyone! During the final weeks of December, Zoho CRM introduced updates that not only enhanced product capabilities but also offered deeper guidance through Kaizen posts. This section highlights what was released and shared in the last two weeks
CRUD actions for Resources via API
Hello, is it possible to perform CRUD actions through the API for Resources? We want to create a sync from Zoho CRM Car record to Bookings resources to create availabilities for Car bookings. For Test drives, not only the sales person needs to be available,
Kaizen #186 : Client Script Support for Subforms
Hello everyone! Welcome back to another exciting Kaizen post on Client Script! In this edition, we’re taking a closer look at Client Script Support for Subforms with the help of the following scenario. " Zylker, a manufacturing company, uses the "Orders"
Unable to Assign Multiple Categories to a Single Product in Zoho Commerce
Hello Zoho Commerce Support Team, I am facing an issue while assigning categories to products in Zoho Commerce. I want to assign multiple categories to a single product, but in the Item edit page, the Category field allows selecting only one category
オンライン勉強会のお知らせ Zoho ワークアウト (2/19 参加無料)
ユーザーの皆さま、こんにちは。コミュニティチームの中野です。 2月開催のZoho ワークアウトについてお知らせします。 今回はZoomにて、オンライン開催します。 ▶︎参加登録はこちら(無料) https://us02web.zoom.us/meeting/register/6AyVUxp6QDmMQiDGXGkxPA ━━━━━━━━━━━━━━━━━━━━━━━━ Zoho ワークアウトとは? Zoho ユーザー同士で交流しながら、サービスに関する疑問や不明点の解消を目指すイベント「Zoho
doubts about customer happiness in zoho desk
Good afternoon, Desk community. The reason for my message is that I have a question regarding the customer satisfaction surveys we can ask our clients to rate our service. I know that in Desk, you can activate Customer Happiness to send a survey to the
COQL API in JS Widget only pulling 200 records
Hello! We've been building a custom homepage widget using the Zoho JS SDK, and it seems that this https://help.zwidgets.com/help/latest/ZOHO.CRM.API.html#.coql only allows 200 records. I thought the limit was 2000 for COQL queries, but am I mistaken?
Standard Description Field - Can I change label or add dd tooltip
Is there a way fo you guys to allow the customer to change the label name for the description field in the customer portal when submitting tickets. Or at least allow us to add a tooltip to clarify what description we need from them. I know I can create my own separate multi line description field but if I do that, it doesn't have the nice toolbar with Bold, Italic, Underline, color, font, indent, etc. Can you please allow us to add a tooltip to the zoho standard description field?
Introducing parent-child ticketing in Zoho Desk [Early access]
Hello Zoho Desk users! We have introduced the parent-child ticketing system to help customer service teams ensure efficient resolution of issues involving multiple, related tickets. You can now combine repetitive and interconnected tickets into parent-child
Ability to CC on a mass email
Ability to CC someone on a mass email.
Different Task Layouts for Subtasks
I was wondering how it would be possible for a subtask to have a different task layout to the parent task.
Compensation | Salary Packages - Hourly Wage Needed
The US Bureau of Labor Statistics says 55.7% of all workers in the US are paid by the hour. I don't know how that compares to the rest of the world, but I would think that this alone would justify the need for having an hourly-based salary package option.
Customizing Helpcenter texts
I’m customizing the Zoho Desk Help Center and I’d like to change the wording of the standard widgets – for example, the text in the “Submit Ticket” banner that appears in the footer, or other built-in widget labels and messages. So far, I haven’t found
Ability to Edit Ticket Subject when Splitting a Ticket
Often someone will make an additional or new request within an existing ticket that requires we split the ticket. The annoying part is that the new ticket maintains the subject of the original ticket after the split so when the new ticket email notification
Automatically Update Form Attachment Service with Newly added Fields
Hi, When I have a Form Setup and connected to a 3rd Party Service such as OneDrive for Form Attachments, when I later add a new Upload Field I have to remove and redo the entire 3rd Party Setup from scratch. This needs to be improved, such as when new
🚀 WorkDrive 6.0 (Phase 1): Empowering Teams with Content Intelligence, Automation, Accessibility, and Control
Hello, everyone! WorkDrive continues to evolve from a robust file management solution into an intelligent, secure, and connected content collaboration platform for modern businesses. Our goal remains unchanged: to simplify teamwork, strengthen data security,
Reopen ticket on specific date/time
Is there a way that we can close a ticket and setup a reopen of that ticket on a specific date and time? (without using the "on hold" ticket option)
[Important announcement] Zoho Writer will mandate DKIM configuration for automation users
Hi all, Effective Dec. 31, 2024, configuring DKIM for From addresses will be mandatory to send emails via Zoho Writer. DKIM configuration allows recipient email servers to identify your emails as valid and not spam. Emails sent from domains without DKIM
Column letter from number
Hello, I am trying to select a cell and i have the column number. How do i do this or is there a way of getting the letter from the number? Thank you
API credit COQL COUNT
The docs describe API credits in COQL from the LIMIT perspective: https://www.zoho.com/crm/developer/docs/api/v8/COQL-Overview.html When using aggregate functions such as `COUNT` or `SUM`, is that billed as 1 API credit?
Weekly Tips : Save Time with Saved Search
Let's assume your work requires you to regularly check emails from important clients that have attachments and were sent within a specific time period. Instead of entering the same conditions every time—like sender, date range, and attachments included—you
Remove 'This is an automated mail from Zoho Sign' in footer
Hi there, Is it possible to remove or change the text under the e-mail templates? I can't figure out how to do that: Would love to hear from you. Kind regards, Tristan
Organize and manage PDFs with Zoho PDF Editor's dashboard
Hello users, Zoho PDF Editor's dashboard is a one-stop place to upload, sort, share PDF files, and more. This article will explore the various capabilities that Zoho PDF Editor's dashboard offers. A few highlights of Zoho PDF Editor's dashboard: Upload
Custom function return type
Hi, How do I create a custom deluge function in Zoho CRM that returns a string? e.g. Setup->Workflow->Custom Functions->Configure->Write own During create or edit of the function I don't see a way to change the default 'void' to anything else. Adding
Passing Info from Function to Client Script
Hello, I have recently started making use of client script for buttons, allowing me to give the user information or warnings before they proceed. This is great. However, I have never quite managed to pass back any extra information from the function to
Drag 'n' Drop Fields to a Sub-Form and "Move Field To" Option
Hi, I would like to be able to move fields from the Main Page to a Sub-Form or from a Sub-Form to either the Main Page or another Sub-Form. Today if you change the design you have to delete and recreate every field, not just move them. Would be nice to
Zoho Payroll for Canada
Is anyone else having problems getting setup for Canada?
Passing the CRM
Hi, I am hoping someone can help. I have a zoho form that has a CRM lookup field. I was hoping to send this to my publicly to clients via a text message and the form then attaches the signed form back to the custom module. This work absolutely fine when
One Contact with Multiple Accounts with Portal enabled
I have a contact that manages different accounts, so he needs to see the invoices of all the companies he manage in Portal but I found it not possible.. any idea? I tried to set different customers with the same email contact with the portal enabled and
Next Page