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

    • Zoho Desk: Q2 2025 | What's New

      Hello everyone, We are excited to announce Zoho Desk's 2025 Autumn updates. This release brings new features and enhancements that improve work management and enable businesses to provide a better overall support experience. Spanning from Zia Agents to
    • Checkboxes not adhering to any policy in mail merge - data from CRM

      I want checkboxes to appear depending on whether the checkbox in the CRM module is ticked or not. However, the tickboxes that appear are either ticked or not, but don't correlate to the actual selections in the CRM module. This is is despite updating
    • Items Landed Cost and Profit?

      Hello, we recently went live with Zoho Inventory, and I have a question about the Landed Cost feature. The FAQ reads: "Tracking the landed cost helps determine the overall cost incurred in procuring the product. This, in turn, helps you to decide the
    • CC and/or BCC users in email templates

      I would like the ability to automatically assign a CC and BCC "User (company employee)" into email templates. Specifically, I would like to be able to add the "User who owns the client" as a CC automatically on any interview scheduled or candidate submitted
    • Create Contract API Endpoint Unclear "inputfields" Requirements

      Hello, I'm trying to create a Deluge function that accepts inputs from a form in Zoho Creator and creates a barebones contract of a given type. See below for the current code, cleaned of authentication information. // Fetch form data // Hidden field client_name
    • Kaizen #46 - Handling Notes through Zoho CRM API (Part 1/2)

      Hello everyone! Welcome back to another week of Kaizen! This week, we will discuss Handling Notes through Zoho CRM API. What will you learn from this post? Notes in Zoho CRM Working with Notes through Notes APIs 1. Notes in Zoho CRM 1a. Why add Notes to records? Notes are a great way to summarize your observations on customer and prospect interactions and outcomes. By saving notes as CRM data, a sales rep will always be able to keep track of how a sale is progressing. To know more about notes in
    • Marketer's Space - Why email marketing matters in ecommerce (and how to get started with Zoho Campaigns)

      Hello Marketers, Welcome to this week's Marketer's space post. Today, we'll discus why email marketing matters in ecommerce businesses. Running an online store is exciting but challenging. If you're running an online store, you've probably experienced
    • Zoho Campaigns Event timestamps do not propagate to Zoho CRM

      We have integrated Zoho CRM and Zoho Campaigns. But when looking at Contact records, the Campaign event data is missing the actual timestamps: especially when a particular email was sent. They're not in the Campaigns related list, and the cannot be found
    • Kaizen #121 : Customize List Views using Client Script

      Hello everyone! Welcome back to another interesting Kaizen post. In this post, we can discuss how to customize List Views using Client Script. This post will answer the questions Ability to remove public views by the super admin in the Zoho CRM and Is
    • Setting default From address when replying to request

      At the moment, if I want to reply to a request, the From field has three options, company@zohosupport.com, support@company.zohosupport.com, and support@company.com.  The first two are really internal address that should never be seen by the customer and
    • Tip #45 - Explore Your Support Reach with Zoho Assist’s Geo Insights - 'Insider Insights'

      Understanding where your remote support sessions are happening can help you make smarter decisions, allocate resources effectively, and improve overall customer satisfaction. In this week's Zoho Assist's community post we will be exploring Geo Insights
    • Formatting of text pasted into Zoho documents

      Howdy, I'm a newbie and finding Zoho an improvement to MS Word. Consider yourself hugged. High on my wish list would be plain text cut-and-paste. When pasting text from the web to Zoho, presently Zoho imports the formatting along with the text. This means that every cut-and-paste operation brings in text in a different font, size, or style. Can we have at least the option of importing plain text without formatting (or better yet, is this option already out there?) ... Thanks Helen
    • Add additional features to Zoho Tables

      Zoho Tables is a really great tool, why not add features like diagramming capability into the tool from applications like Draw.io which I believe is open source, you should be able to do wireframes, process flow diagrams, network design, etc. Please note
    • The Social Wall: August 2025

      Hello everyone, As summer ends, Zoho Social is gearing up for some exciting, bigger updates lined up for the months ahead. While those are in the works, we rolled out a few handy feature updates in August to keep your social media management running smoothly.
    • The Social Wall: July 2025

      Hello everyone! July has brought some exciting new updates to Zoho Social. From powerful enhancements in the Social Toolkit to new capabilities in the mobile app, we’ve packed this month with features designed to help you level up your social media presence.
    • Use Zoho Creator as a source for merge templates in Zoho Writer

      Hello all! We're excited to share that we've enhanced Zoho Creator's integration with Zoho Writer to make this combination even more powerful. You can now use Zoho Creator as a data source for mail merge templates in Zoho Writer. Making more data from
    • Tagged problem !!!

      Damn it, we're one of dozens of construction companies in Africa, but we can't link purchasing invoices to projects. Why isn't this feature available?
    • Syntax for URLs in HTML Snippets

      What are some best practices for inserting a URL in an HTML snippet? I've looked at Zoho Help articles on navigation-based and functional-based URLs, but I'm still unclear on how to incorporate them in an HTML snippet. For example, 1. How do I link to
    • The Social Wall: June 2025

      Hello everyone, We’re back with June Zoho Social highlights. This month brought some exciting feature updates—especially within the Social Toolkit—to enhance your social media presence. We engaged with several MSME companies through community meet-ups
    • Tip 7: How to fetch data from another application?

      Hi everyone, Following our Zoho Creator - Tips and Tricks series every fortnight, we are back today with a tip based on one of the most popular questions asked in our forum. This tip would help you fetch data from another application(App B) and use it
    • The Social Wall: May 2025

      Hey everyone, We're excited to share some powerful updates for the month of May! Let's take a look! Reply to your Instagram and Facebook comments privately through direct messages Are you tired of cluttered comment threads or exposing customer queries
    • Sub-Form Fields as Filters for Reports

      Hi, I would like to use the Sub-Form Fields as Filters in Reports just like we do for Main Page Fields. Thanks Dan
    • Zoho CRM Formula - Current Time minus Date/Time field

      Hello, I am trying to prevent duplicate emails going to clients when more than 1 deal is being updated. To do this, I would like to create a formula to identify if a date/time field is >= 2 hours ago. Can someone please help me write this formula? Example:
    • Billing Management: #7 Usage Billing in Telecom & Internet Service Provider

      Telecom and Internet Service Providers operate in markets where usage varies drastically from one customer to another. While flexible, usage-based models align revenue directly with consumption, they also introduce operational challenges like real-time
    • Zoho Sprints - Q3 updates for 2025

      The updates for the third quarter of 2025 are out. A few significant features and enhancements have been rolled out to improve user experience and product capabilities. The following are the updates: Manage tags and cluster tags Record and maintain project
    • Kaizen #208 - Answering your Questions | Functions, AI and Extensions

      Hello Developers! Welcome back to a fresh week of Kaizen! We are grateful for your active participation in sharing feedback and queries for our 200th milestone. This week, we will answer the queries related to Functions and Extensions in Zoho CRM. 1.
    • Zoho CRM still doesn't let you manage timezones (yearly reminder)

      This is something I have asked repeatedly. I'll ask once again. Suppose that you work in France. Next month you have a trip to Guatemala. You call a contact there, close a meeting, record that meeting in CRM. On the phone, your contact said: "meet me
    • To Zoho customers and partners: how do you use Linked Workspaces?

      Hello, I'm exploring how we can set up and use Linked Workspaces and would like to hear from customers and partners about your use cases and experience with them. I have a Zoho ticket open, because my workspace creation fails. In the meantime, how is
    • Zoho Forms to Zoho CRM : First/Last Name to just Name ?

      When integrating a Zoho Form into the Accounts menu of the CRM I'm having trouble with how names are formatted ; In Forms the data is available as First Name or Last Name In the CRM there is only one field called Name How can I ensure that "John" "Smith"
    • This festive season, offer discounts with coupon code support in Stripe Checkout

      Hello form builders! It’s the festive season, the perfect time to spread joy and great deals! Now, with Zoho Forms’ latest enhancement for Stripe Checkout, you can do exactly that with coupon codes! Your payment forms integrated with Stripe Checkout can
    • Cómo creo una factura negativa o de abono?

      NEcesito anular una factura y crear una nueva igual pero en negativo. El sistema no me lo permite
    • Power of Automation::Streamline log hours to work hours upon task completion.

      Hello Everyone, A Custom Function is a user-written set of code to achieve a specific requirement. Set the required conditions needed as to when to trigger using the Workflow rules (be it Tasks / Project) and associate the custom function to it. Requirement:-
    • CRM : Function to add user name to text field

      I have a lookup field in a module that is linked to the CRM users so we can assign a Project Lead to the customer. Sadly Zoho Marketing Automation doesn't sync Lookup fields so I need to extract information from the lookup to text fields: Lookup field
    • Zoho CRM - Restrict Login based on work hours

      Hi there, I'm wondering if we can restrict users to login during works - For example the users would be able to login from 8am to 5pm. I have seen the IP address restriction - the only downfall is what if the customer has dynamic IP. thanks Jiri
    • Tips and Tricks #46: Customize themes and templates using Show's Master View

      Hi All!  Let's say you want to revamp your presentation and make changes to its visual design. You can do this easily using the Master Slide and its associated layouts. The Master Slide stores information about all the layouts used in the presentation.
    • Sheet View in CRM portal

      Hi, When will it be possible for my CRM portal users to edit/add records with Sheet View? George
    • What's New in Zoho Invoice | July - September 2025

      Hello everyone! We’re back with the latest updates and enhancements we’ve rolled out in Zoho Invoice from July to September 2025. Here’s what’s new this quarter: Introducing the Singapore Edition in Zoho Invoice Share Invoices through WhatsApp GST 2.0
    • Alert: Audio Call Support to be discontinued for Old Live Chat Widget from December 31, 2025

      Action Required: Upgrade to the New SalesIQ Live Chat Widget We're reaching out with an important update regarding the SalesIQ Live Chat Widget that requires your immediate attention. Effective December 31, 2025, audio call functionality will no longer
    • multiple contacts for one account

      We currently use Zoho CRM where each Account represents a club or organization, and each Contact represents a manager or owner. However, some of our managers own or manage multiple clubs, and Zoho only allows a contact to be linked to one account at a
    • Rich text Merge field - Not using font specified in HTML

      I have a rich text merge field in a writer template which is creating a table. I have chosen to use this method instead of a repeat region because I need to specify specific cell background colours which change every time the document is created. The
    • Next Page