Bulk user onboarding for Cliq Channels in a jiffy

Bulk user onboarding for Cliq Channels in a jiffy

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".

  1. inputs = List();
  2. 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"});
  3. 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"});
  4. 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"});
  5. 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.
  1. emailIdList = list();
  2. successlist = list();
  3. failedlist = list();
  4. try 
  5. {
  6. info form;
  7. formValues = form.get("values");
  8. columnName = formValues.get("headername");
  9. headerName = formValues.get("headername");
  10. if(formValues.get("import_Type").get("value") == "zohosheet")
  11. {
  12. url = formValues.get("url");
  13. spreadSheetId = url.getPrefix("?").getSuffix("open/");
  14. sheetName = url.getSuffix("?").getPrefix("&").getSuffix("=");
  15. worksheetname = sheetName.replaceAll(" ","%20");
  16. columnName = columnName.replaceAll(" ","%20");
  17. allDatas = list();
  18. params = Map();
  19. params.put("column_names",columnName);
  20. params.put("method","worksheet.records.fetch");
  21. params.put("worksheet_id",sheetName + "#");
  22. sheetDetails = invokeurl
  23. [
  24. url :"https://sheet.zoho"+environment.get("tld")+"/api/v2/" + spreadSheetId
  25. type :GET
  26. parameters:params
  27. connection:"addbulkusers"
  28. ];
  29. info sheetDetails;
  30. if(sheetDetails.get("status") == "success" && sheetDetails.get("records").size() <= 1000)
  31. {
  32. allDatas.addAll(sheetDetails.get("records"));
  33. }
  34. else if(sheetDetails.get("status") == "success" && sheetDetails.get("records").size() > 1000)
  35. {
  36. return {"type":"form_error","text":"I can only able to add 1000 user. Kindly try passing with 1000 records in the sheet!!!"};
  37. }
  38. else
  39. {
  40. return {"type":"form_error","text":"I can't find any email ids. Kindly re-check the column name and header row!!!"};
  41. }
  42. info "allData: " + allDatas.size();
  43. if(allDatas.size() > 1000)
  44. {
  45. return {"type":"form_error","text":"I can only able to add 1000 user. Kindly try passing with 1000 records in the sheet!!!"};
  46. }
  47. for each  data in allDatas
  48. {
  49. if(data.get(formValues.get("headername")) == null)
  50. {
  51. return {"type":"form_error","text":"I can't find any email ids. Kindly re-check the column name and header row!!!"};
  52. }
  53. emailIdList.add(data.get(formValues.get("headername")));
  54. if(emailIdList.size() == 100)
  55. {
  56. channelID = formValues.get("channels").get("id");
  57. params = {"email_ids":emailIdList};
  58. info "Params: " + params;
  59. addUsers = invokeurl
  60. [
  61. url :environment.get("base_url") + "/api/v2/channels/" + channelID + "/members"
  62. type :POST
  63. parameters:params.toString()
  64. detailed:true
  65. connection:"addbulkusers"
  66. ];
  67. info "Adduser: " + addUsers;
  68. if(addUsers.get("responseCode") == "204")
  69. {
  70. successlist.addAll(emailIdList);
  71. }
  72. else
  73. {
  74. failedlist.addAll(emailIdList);
  75. }
  76. info "100: " + emailIdList.size();
  77. emailIdList = list();
  78. }
  79. }
  80. if(emailIdList.size() > 0)
  81. {
  82. channelID = formValues.get("channels").get("id");
  83. params = {"email_ids":emailIdList};
  84. info "Params: " + params;
  85. addUsers = invokeurl
  86. [
  87. url :environment.get("base_url") + "/api/v2/channels/" + channelID + "/members"
  88. type :POST
  89. parameters:params.toString()
  90. detailed:true
  91. connection:"addbulkusers"
  92. ];
  93. info "Adduser: " + addUsers;
  94. if(addUsers.get("responseCode") == "204")
  95. {
  96. successlist.addAll(emailIdList);
  97. }
  98. else
  99. {
  100. failedlist.addAll(emailIdList);
  101. }
  102. info "Email id: " + emailIdList;
  103. }
  104. info "Successlist: " + successlist;
  105. info "Failedlist: " + failedlist;
  106. if(successlist.size() > 0 && failedlist.size() > 0)
  107. {
  108. postMessage = {"text":"Successfully added " + successlist.size() + " member(s) and failed for " + failedlist.size() + " Member(s)"};
  109. }
  110. else if(successlist.size() > 0 && !failedlist.size() > 0)
  111. {
  112. postMessage = {"text":"Successfully added " + successlist.size() + " member(s)"};
  113. }
  114. else if(!successlist.size() > 0 && failedlist.size() > 0)
  115. {
  116. postMessage = {"text":"Adding members in channel failed for " + failedlist.size() + " member(s)"};
  117. }
  118. info zoho.cliq.postToChat(chat.get("id"),postMessage);
  119. }
  120. else
  121. {
  122. csvFile = formValues.get("csvFile");
  123. csvFile = csvFile.getfilecontent();
  124. allDatas = csvFile.toList("\n");
  125. i = 0;
  126. indexValue = 0;
  127. indexBoolean = false;
  128. for each  data in allDatas
  129. {
  130. if(i == 0)
  131. {
  132. headers = data.toList(",");
  133. for each  header in headers
  134. {
  135. info header;
  136. if(headerName == header)
  137. {
  138. indexBoolean = true;
  139. indexValue = headers.indexOf(headerName);
  140. }
  141. }
  142. if(indexBoolean == false)
  143. {
  144. return {"type":"form_error","text":"I can't find any email ids. Kindly re-check the column name and header row!!!"};
  145. }
  146. }
  147. else 
  148.             {
  149. emailIdList.add(data.get(indexValue));
  150.             }
  151. i = i + 1;
  152. if(emailIdList.size() == 100)
  153. {
  154. channelID = formValues.get("channels").get("id");
  155. params = {"email_ids":emailIdList};
  156. info "Params: " + params;
  157. addUsers = invokeurl
  158. [
  159. url :environment.get("base_url") + "/api/v2/channels/" + channelID + "/members"
  160. type :POST
  161. parameters:params.toString()
  162. detailed:true
  163. connection:"addbulkusers"
  164. ];
  165. info "Adduser: " + addUsers;
  166. if(addUsers.get("responseCode") == "204")
  167. {
  168. successlist.addAll(emailIdList);
  169. }
  170. else
  171. {
  172. failedlist.addAll(emailIdList);
  173. }
  174. info "100: " + emailIdList.size();
  175. emailIdList = list();
  176. }
  177. }
  178. if(emailIdList.size() > 0)
  179. {
  180. channelID = formValues.get("channels").get("id");
  181. params = {"email_ids":emailIdList};
  182. info "Params: " + params;
  183. addUsers = invokeurl
  184. [
  185. url :environment.get("base_url") + "/api/v2/channels/" + channelID + "/members"
  186. type :POST
  187. parameters:params.toString()
  188. detailed:true
  189. connection:"addbulkusers"
  190. ];
  191. info "Adduser: " + addUsers;
  192. if(addUsers.get("responseCode") == "204")
  193. {
  194. successlist.addAll(emailIdList);
  195. }
  196. else
  197. {
  198. failedlist.addAll(emailIdList);
  199. }
  200. }
  201. info "Successlist: " + successlist;
  202. info "Failedlist: " + failedlist;
  203. if(successlist.size() > 0 && failedlist.size() > 0)
  204. {
  205. postMessage = {"text":"Successfully added " + successlist.size() + " member(s) and failed for " + failedlist.size() + " Member(s)"};
  206. }
  207. else if(successlist.size() > 0 && !failedlist.size() > 0)
  208. {
  209. postMessage = {"text":"Successfully added " + successlist.size() + " member(s)"};
  210. }
  211. else if(!successlist.size() > 0 && failedlist.size() > 0)
  212. {
  213. postMessage = {"text":"Adding members in channel failed for " + failedlist.size() + " member(s)"};
  214. }
  215. info zoho.cliq.postToChat(chat.get("id"),postMessage);
  216. }
  217. }
  218. catch (e)
  219. {
  220. info e;
  221. return {"type":"form_error","text":"I can't find any email ids. Kindly re-check the column name and header row!!!"};
  222. }
  223. 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. 
  1. targetName = target.get("name");
  2. info targetName;
  3. inputValues = form.get("values");
  4. info inputValues;
  5. actions = list();
  6. if(targetName.containsIgnoreCase("import_Type"))
  7. {
  8. fieldValue = inputValues.get("import_Type").get("value");
  9. info fieldValue;
  10. if(fieldValue == "csv")
  11. {
  12. actions.add({"type":"add_after","name":"import_Type","input":{"label":"CSV File","name":"csvFile","placeholder":"Please upload a zCSV File","mandatory":true,"type":"file"}});
  13. actions.add({"type":"remove","name":"url"});
  14. }
  15. else if(fieldValue == "zohosheet")
  16. {
  17. 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"}});
  18. actions.add({"type":"remove","name":"csvFile"});
  19. }
  20. }
  21. 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.

    • Sticky Posts

    • Cliq Bots - Post message to a bot using the command line!

      If you had read our post on how to post a message to a channel in a simple one-line command, then this sure is a piece of cake for you guys! For those of you, who are reading this for the first time, don't worry! Just read on. This post is all about how
    • Add Claude in Zoho Cliq

      Let’s add a real AI assistant powered by Claude to your workspace this week, that your team can chat with, ask questions, and act on conversations to run AI actions on. This guide walks you through exactly how to do it, step by step, with all the code
    • Automating Employee Birthday Notifications in Zoho Cliq

      Have you ever missed a birthday and felt like the office Grinch? Fear not, the Cliq Developer Platform has got your back! With Zoho Cliq's Schedulers, you can be the office party-cipant who never forgets a single cake, balloon, or awkward rendition of
    • Automate attendance tracking with Zoho Cliq Developer Platform

      I wish remote work were permanently mandated so we could join work calls from a movie theatre or even while skydiving! But wait, it's time to wake up! The alarm has snoozed twice, and your team has already logged on for the day. Keeping tabs on attendance
    • Customer payment alerts in Zoho Cliq

      For businesses that depend on cash flow, payment updates are essential for operational decision-making and go beyond simple accounting entries. The sales team needs to be notified when invoices are cleared so that upcoming orders can be released. In contrast,
    • Recent Topics

    • Transition from Sole Proprietorship to GmbH (Limited Liability Company) – Best Approach in Zoho Books / Zoho One

      Hello everyone, I am currently operating under a Zoho One plan with a sole proprietorship in Switzerland. As of January 1st, 2026, I will be incorporating a new legal entity – a GmbH (Swiss equivalent of a Limited Liability Company). While the business
    • Issue Connecting My Domain to Zoho Sites Despite Purchasing It from Zoho

      Hello, I am facing an issue connecting my domain to my website on Zoho Sites. Details of the issue: I purchased the domain directly from Zoho. I am already using the same domain successfully with Zoho Mail. However, when I try to assign this domain to
    • Insert auto number from main form into subform rows

      Hello. I'm trying to take from my main form "order number" which i have setup as an auto generated number into every line created in my subform. So when a row is created in my subform i want the "order number " from the main form to be inserted automatically.
    • Dark Mode - Font Colors Don't Work

      When editing a document in Dark Mode and selecting font colors, they don't show up on screen.  Viewing/editing the same document in Light Mode shows them just fine.
    • Integrate Bunq with ZOHO Bookes

      We are new users of ZOHO Books, and our bank (BUNQ, in the Netherlands) isn't listed on the bank integrations. Is there a way to handle this?
    • Access Denied

      I am iOS Developer and updating our clients project and shifted ZohoDeskPortalCore SDKs from cocoapods to SPM and changed few lines of code but now i am get access denied, the help center app is unavailable. please contact administrator.
    • Using Zoho Desk to support ISMS process

      Hi, I am evaluating using Zoho Desk for security incident management. This seems to be aligned with Zoho Desk purpose as its just another type of incident. However in security incident management, ideally I can link incidents (tickets) with a risk from
    • TaxJar vs Avalara

      Hi, I'm evaluating adoption of a sales-tax service for US based business. Anyone else have experience with TaxJar and Zoho Books? I am a Zoho One subscriber so anticipate needing to use Flow to make this work. It seems like Avalara are simply too expensive
    • How to check Leads with no Task (open activity)

      Hi everyone, I was wondering if there’s a way to view leads that don’t have any tasks assigned or open activities linked to them.
    • What can we do on our end to improve the Answer bot answers?

      Hi, I'm using the Answer bot card in the Codeless bot builder. I've input several questions and their answers in the FAQ section to feed the Answer bot. The text is all in French, as this is the language our customers communicate in. I've tried testing
    • Group Tax in Service Line Items

      Hi FSM Team! I noticed that when you update a tax in the service line item the group tax is not showing up as an option. Let me know what can be done thank you!
    • OAUTH_SCOPE_MISMATCH Error for Marketing Automation APIs with CRM Plus Account

      I'm trying to integrate Marketing Automation journey triggering via API but getting OAUTH_SCOPE_MISMATCH errors. I need clarification on API access for CRM Plus users.
    • Function #4: Schedule Customer Statements

      Regularly sending statements to customers is an imperative part of many business processes as it helps foster strong customer relationships and provides timely guidance on payments. While you can generate the statement of accounts and have it sent over
    • Limiting search or dependencies with an asterisk "*".

      I have a form with several dependency fields with options still developing for each field. Since these options were developing and not yet ready to be a selection in the field, I placed a filter for the dropdown field. In this filter, I selected fields
    • Cross Data Center Support for 1:1 Chats with External Users

      Hello Zoho Cliq Team, We hope you're doing well. We appreciate the recent enhancement that enables cross data center collaboration in external channels, which has already improved communication across distributed teams. However, we’ve noticed that this
    • Handling Greetings/Small Talk at the Beginning of a Zobot Conversation

      Hello everyone, I’m currently configuring a **Zobot** in Zoho SalesIQ and everything is working as expected, except for one specific scenario at the very beginning of the conversation. My target audience has the habit of starting with a **greeting or
    • Regex in Zoho Mail custom filters is not supported - but it works!

      I recently asked Zoho for help using regex in Zoho Mail custom filters and was told it was NOT supported. This was surprising (and frustrating) as regex in Zoho Mail certainly works, although it does have some quirks* To encourage others, here are 3 regex
    • Importing a new list into campaigns

      I'm in the middle of switching my email platform to campaigns. I have a list that I want to import, and it overlaps with my existing Zoho CRM list. The fields in my Zoho CTM are more robust. Will this new list that I upload into my campaigns overwrite
    • when I email a invoice how can i see it was sent and also were i can go to see all emails sent

      when I email a invoice how can i see it was sent and also were i can go to see all emails sent?
    • How can I see content of system generated mails from zBooks?

      System generated mails for offers or invices appear in the mail tab of the designated customer. How can I view the content? It also doesn't appear in zMail sent folder.
    • CRM Blueprint Notification by Cliq

      Dear Zoho team, In Workflow, there is nofication by cliq, but in blueprint, there is no option as cliq notification. I think it is very convenient to get notified by Cliq , as there are multi modules in apps, but we will always check Cliqs
    • Sync Contacts in iOS

      What does the "Sync Contacts" feature in the iOS Zoho Mail app do?
    • Live webinar: Craft the ideal sales pitch deck with Show

      Every great sale starts with a great story. And your pitch deck? That’s where the story takes shape. But too often, these presentations end up looking generic, overloaded with text, or lacking structure. The good news is, it's easier to fix than you think!
    • Project Statuses

      Hi All, We have projects that sometimes may not make it through to completion. As such, they were being marked as "Cancelled". I noticed that these projects still show as "Active" though which seems counter intuitive. In fact, the only way I can get them
    • 👋 Welcome to the Zoho MCP Community

      Hello all, glad to have you here! This is your space for everything AI agents, MCP tools, and intelligent business apps. This community is for you — developers, partners, creators, and businesses exploring how agents can transform work. Whether you’re
    • DNS Manager

      Where Can I find my DNS manager so I can link this to click funnels or AWEBER
    • Need to extract date from datetime field

      I have a datetime field and need only the date part from it. I am unable to find a built-in function that would be <DateTime>.Date(). I don't think I want to go the string conversion route of converting the datetime to string and then parsing out values and create a date out of it. Any one out there has a better solution to this? Thanks in adavnce. Regards Moiz Tankiwala Smart Training & IT Solutions
    • New in Cadences: WhatsApp follow-ups, upgraded limits, and options for add-ons

      Hello everyone, We're rolling out two key updates to help you engage better and scale smarter with Cadences in Zoho CRM. Reach customers on WhatsApp, directly from Cadences Previously, Cadences have enabled you to automate follow-ups through emails, calls,
    • additional accounts

      If I brought 5 emails to my account. Can I later buy additional emails.
    • Why I am unable to configure Zoho Voice with my Zoho CRM account?

      I have installed Zoho Voice in my Zoho CRM, but as per the message there is some config needed in Zoho Voice interface. But when I click on the link given in the above message, I get an access denied page.
    • Cliq Meeting Calls No Audio and Screen Share

      When in a Cliq channel meeting, the audio does not work at all on pc. When i use my phone as audio source, screen share on pc does not work. I have updated audio drivers but the strangest thing is that during a 1 on 1 call, it works well. Therefore the
    • Work anniversary and birthdays on connect

      Hello, I like the idea of having employee's work anniversary and birthdays on the dashbaord. Do you have to have the employee complete this information themselves in connect settings, or does it pull from their directory settings? (ie. we use Zoho one
    • Alias Email Id already exists

      Hi I'm trying to create an alias : contact @ yoavarielevy.co.il but i get the message  Alias Email Id already exists I had an account with the same name but I deleted it. Can you help? Thanx Yoav
    • Feature Request: Ability to Set a Custom List View as Default for All Users

      Dear Zoho CRM Support Team, We would like to request a new feature in Zoho CRM regarding List Views. Currently, each user has to manually select or favorite a custom list view in order to make it their default. However, as administrators, we would like
    • Adding Multiple Products (Package) to a Quote

      I've searched the forums and found several people asking this question, but never found an answer. Is ti possible to add multiple products to a quote at once, like a package deal? This seems like a very basic function of a CRM that does quotes but I can't
    • webinar registration confirmation are landing in SPMA folders

      I am trialing zoho webinar and do not have access to custom domains. When I test user registrations, they are working but the resulting confirmation email is landing in a spam folder. How can I avoid this?
    • Multiple organizations under Zoho One

      Hello. I have a long and complicated question. I have a Zoho One account and want to set it up to serve the needs of 6 organizations under the same company. Some of the Zoho One users need to be able to work in more than 1 organization’s CRM and other
    • Unbundle feature for composite items

      We receive composite items from our vendors and sell them either individually or create other composite items out of them. So, there is a lot of bundling and unbundling involved with our composite items. Previously, this feature was supported in form
    • workflow not working in subform

      I have the following code in a subform which works perfectly when i use the form alone but when i use the form as a subform within another main form it does not work. I have read something about using row but i just cant seem to figure out what to change
    • Fetch data from another table into a form field

      I have spent the day trying to work this out so i thought i would use the forum for the first time. I have two forms in the same application and when a user selects a customer name from a drop down field and would like the customer number field in the
    • Next Page