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
Embedding in Desk articles
We would like to embed documents in our Desk articles. When we use an iframe for the embed, we get scrollbars and a frame border. Neither of those is acceptable. I've spoken with the Desk Support team about what we want and they tell me that it cannot
Zoho CRM button to download images from image upload field
Hello, I am trying to create a button in Zoho CRM that I can place in my record details view for each record and use it to download all images in the image upload fields. I tried deluge, client scripts and even with a widget, but feel lost, could not
Mass Update Contacts In Zoho Campaigns
Is there a way to mass update contacts in zoho campaigns? I want to be able to change the content of a field for a few hundred contacts, and can't go through all of them individually.
report showing assignment type
Hi, We've created a number of workflows to allow us to auto assign tickets to agents based on keywords and other criteria. I'm struggling to create a report that would show me what is the percentage of tickets that are assigned automatically via workflows
Option to Disable Knowledge Base Section in Feedback Widget Popup Hello Zoho Desk Team
Hello Zoho Desk Team, How are you? We are actively using Zoho Desk and would like to make more use of the Feedback Widget. One of the ways we implement it is through the popup option. At the moment, the popup always displays the Knowledge Base section,
Placeholders in Ticket Templates
We should be able to use placeholders in ticket templates. When we create a new ticket, our description field is shown to the client in the email they receive. It would be very handy to be able to personalize that description field in our ticket templates to pull in the name of the client that the ticket is for. Using them in the subject field as well, so we can auto populate Account Names, etc.
when the record is created the tag want to Show as Opportunity how i achive this using Deluge Script
In the quotation i have the work flow schedule for create opportunity record in the module , on that time the quotation tag select as opportunity created. How i achive this using Deluge Script . this like i want to Do tag1 = Map(); tag1.put("name","Nurturing
Delete a channel
I need delete a channel in tickets.
Copy / Duplicate Workflow
I have workflows setup that are very similar to each other. We have a monitoring system watching servers, and all notifications - no matter what client it is about - will come from a noreply@ address which is not very helpful in having it auto assigned to the right account. I have setup a workflow that will change the contact name of the ticket (currently it would say noreply@) to the correct customer which is based on the subject line, as that mentions which server the alert it is about. I need
Subtasks don't update parent task's times
Hi there: I've recently upgraded to premium and check that subtasks completion % don't update the proportional completion of the parent tasks related to it. We've been challenging with the problem of having to update twice or sometimes 3 times the completion of the related tasks. I've seen posts similar to this, of 3 years old. Is there any roadmap for making this happen in a future release? Thanx César Ratto Lima, Perú.
Should I Use DMARC?
When I configure Zoho Mail's DMARC settings, it's mandatory to fill in the RUA and RUF (Aggregate notification email address*, Forensic notification email address*) addresses. When we enter an email address in these fields, we receive reports from the
Mail ToDo & Tasks Webhooks
Our company uses Zoho ToDo inside Mail to manage our tasks. When I create a task and assign it to a team member it does not notify them unless I add a reminder via mail. I'm trying to create a webhook for when a task is created to send a cliq message
Can't upload attachments.
I can't upload attachment in Zoho Mail.
Tip #44 – Get Deeper Insights with Zoho Assist’s Custom Reports – ‘Insider Insights’
In today’s fast-paced IT environment, having a clear view of your remote support activities is more important than ever. Zoho Assist’s Custom Reports feature gives IT teams the ability to generate tailored reports that provide actionable insights and
Message "...does not support more than 100 distinct values..." WHY????
I get this message on one of my reports: Sorry, Zoho Reports currently does not support more than 100 distinct values in columns. 'Account Name * Sum(Amount),Count(Amount Tier)' contains more than 100 distinct values. Possibly, you can apply filter to reduce the number of distinct values in 'Account Name' or drop the 'Account Name' field in Rows. I want to list all ACCOUNT NAMES (about 500) with SALES BY ACCOUNT. What is blocking this?
Need Easy Way to Update Item Prices in Bulk
Hello Everyone, In Zoho Books, updating selling prices is taking too much time. Right now we have to either edit items one by one or do Excel export/import. It will be very useful if Zoho gives a simple option to: Select multiple items and update prices
Let's Talk Recruit: Super-charge hiring with Zoho Recruit add-ons
Welcome back to our Let’s Talk Recruit series! This time, we’re diving into something that might seem like a small upgrade but has a huge impact on recruiter productivity: Zoho Recruit add-ons. Think about how much of your day is spent in your inbox or
Vendor Signatures Needed for Purchase Orders
Hello everyone, We have a unique requirement that necessitates that Vendors & Suppliers formally acknowledge our Purchase Orders upon receipt. I was hoping that there would be an option to do so in Zoho Books, but that does not appear to be the case.
Is there an API to "File a Ticket" in Desk
Hi, Is there an API to "File a Ticket" in Desk to zoho projects?
Store "Sign in with Google/Microsoft/GitHub etc." details
Quite often now, users are using a sign-in provider like Google or Microsoft to sign into various apps and services. It would be great if Vault could remember which providers you use for each website and sign you in with that provider instead of a username
Critical Issue: Tickets Opened for Zoho Support via the Zoho Help Portal Were Not Processed
Hi everyone, We want to bring to your attention a serious issue we’ve experienced with the Zoho support Help Portal. For more than a week, tickets submitted directly via the Help Portal were not being handled at all. At the same time no alert was posted
Tip of the Week #72– Assign thread ownership to avoid confusion.
When teams handle a large volume of emails, managing threads becomes important to stay organized. Without a clear system, duplicate replies, missed follow-ups, or confusion over responsibilities can happen. Thread assignment solves this by designating
Migrate Your Notes from OneNote to Zoho Notebook Today
Greetings Notebook Users, We’re excited to introduce a powerful new feature that lets you migrate your notes from Microsoft OneNote to Zoho Notebook—making your transition faster and more seamless than ever. ✨ What’s New One-click migration: Easily import
Unarchive tickets
How can I manually unarchive tickets?
Optimize your Knowledge Base for enhanced accessibility by adding alt tags for images
Let's learn why alt tags are crucial for your articles. You can add alternative tags (alt tags) and alternative text (alt text) to the images you share on your community forums or when embedding them in articles. Alt tags refer to the HTML attribute,
FSM trying again
have not linked FSM yet to the rest of out Zoho suit. It certainly looks like the apointment and service part is more manageable for our staff. The question is that our engineers multi task examples 1. deliver products to customers not fitted 2. Service
Feature Request: Conditional Field Mandatoriness Based on Display Status
Hello Zoho Creator Team, I would like to suggest an enhancement to improve the flexibility of form validations. Currently, when we need a field to be mandatory only if it's displayed on the form, the only option is to: Set the field as not mandatory in
Data Migration Strategies for Moving to a Cloud Solution
Hi everyone, I’ve been working on moving some of our critical systems, including CRM and project data, to a Zoho cloud solution, and one of the biggest challenges I’ve encountered is data migration. Transferring large volumes of data while keeping it
Commerce Order as Invoice instead of Sales Order?
I need a purchase made on my Commerce Site to result in an Invoice for services instead of a Sales Order that will be pushed to Books. My customers don't pay until I after I add some details to their transaction. Can I change the settings to make this
How to set different item selling prices for Zoho Commerce and Zoho Books
Item selling prices for Zoho Commerce and Zoho Books are in sync. If we update the Item selling price in Books, the same will happen in commerce and vice versa. I need a separate commerce selling price for online users and a separate books selling price
Time Entry Notifications
Hi All - I have support staff who place notes of their work in the time entry section of Zoho Desk. Is there a specific workflow or setting I need to enable to have the ticket holder updated via email when an entry is saved?
Zoho CRMの流入元について
Zoho CRMとZoho formsを連携し、 formsで作成したフォームをサイトに埋め込み運用中です。 UTMパラメータの取得をformsを行い、Zoho CRMの見込み客タブにカスタム項目で反映される状況になっています。 広告に関してはUTMパラメータで取得できているため問題ないのですが、オーガニック流入でフォーム送信の場合も計測したいです。メールやGoogle、Yahoo、directなどの流入元のチャネルが反映されるようにしたいのですが、どのように設定したら良いでしょうか。 また、
How to report 'Response violation' OR 'Resolution violation'
Hi, I want to report on SLA Violation Type. I grouped my tickets on this column. It seems I only get 'Response and Resolution Violation' or 'Not Violated'. The former seems to be given to a ticket if only the Response Time was violated. I would expect
[Webinar] Automate sales and presales workflows with Writer
Sales involves sharing a wide range of documents with customers across the presales, sales, and post-sales stages: NDAs, quotes, invoices, sales orders, and delivery paperwork. Generating and managing these documents manually slows down the overall sales
Power of Automation :: Quick way to associate your Projects with Zoho CRM
A custom function is a software code that can be used to automate a process and this allows you to automate a notification, call a webhook, or perform logic immediately after a workflow rule is triggered. This feature helps to automate complex tasks and
Date triggering Workflow rule
I have a function triggered by a workflow rule. The function takes a date and creates a task for that date and fills in a field with the name of the day for that date. It also updates the status field of the record. The workflow rule is set to run whenever
Restricting contact creation
Hi all! I am looking to use Zoho Desk in a part of the business that takes end user enquiries. These are generally single interactions, and not linked to an account name. As Desk is Account centric, has anyone designed a way to manage these incoming emails
Import Holiday Calendars
HI Zoho Is there anyway of importing an online calendar like https://www.calendarlabs.com into the business hours calendars, to speed up setup of holiday calendars. Also could we also request a feature where you can specify a Holiday as hours, i.e it could be that the company is on a 1/2 day due to a holiday or when it is Eid in the UAE and they are only allowed to work restricted hours so we need the calendar to be flexible to allow for this. Regards Jamie
Filtering Tickets based on Email headers
We're starting to get a lot more junk coming into our Zoho Desk, which is then triggering unnecessary email alerts to agents. Once thing we could do to cut this junk in half, is to filter tickets based on email headers. Any email containing the `List-Unsubscribe`
Error 550 5.4.1
I’ve tried sending an email to someone but keep receiving this back. Any help would be greatly appreciated
Next Page