Kaizen 223 - File Manager in CRM Widget Using ZRC Methods

Kaizen 223 - File Manager in CRM Widget Using ZRC Methods

Hello, CRM Wizards!



Here is what we are improving this week with Kaizen. 

we will explore the new ZRC (Zoho Request Client) introduced in Widget SDK v1.5, and learn how to use it to build a Related List Widget that integrates with Zoho WorkDrive. It helps users to preview and upload files directly from the record’s detail page.

Why ZRC?

ZRC is a unified client for making REST calls across all developer-facing components in Zoho CRM. It is currently supported in Widgets and CScript, and will soon be available for other features within the Developer Hub as well.

It simplifies external API usage with:
  1. async/await support
  2. Auto JSON parsing
  3. Unified API client for Zoho CRM developer tools (currently supported for CScript and widgets)
  4. Stronger error handling

Business Problem

Zylker, a real-estate company, stores documents, images, and property videos for each lead in a third-party cloud storage platform. 

However, some of these files exceed 20 MB, making the CRM’s built-in file upload field unsuitable. Their team also needs the ability to preview and upload files directly from the Lead detail page.

Solution Overview

Zylker can build a Related List Widget integrated with their third-party cloud storage platform using ZRC methods.

This widget will allow users to:
  1. Fetch and display files inside the folder linked to the Lead.
  2. Preview files (images, PDFs, videos) inside the widget.
  3. Upload new documents to the same folder.
  4. Create new subfolders to keep the data organized. 
  5. Navigate subfolders using breadcrumbs. 
To keep the demo simple, let us walk you through on building this widget for listing, previewing and uploading files using Zoho WorkDrive

Prerequisites

1. Create a Custom Field

Create a Single Line field named WorkDrive Folder ID in the Leads module. Check out the Working with Custom Fields document for guidance.

This stores the folder ID created for each lead through workflow rule that we build in the next steps.

2. Create WorkDrive and CRM Connection

  1. Go to Setup > Developer Hub > Connections and click Create Connection
  2. Choose Zoho WorkDrive with the scopes WorkDrive.files.CREATE and WorkDrive.files.READ
  3. Click the Create and Connect button and proceed to authorize the connection.

  1. Similarly, choose Zoho CRM with the ZohoCRM.modules.ALL scope and create the connection.
Refer to the Connections help doc for more information. Store the Connection Link Name to use while making API calls. 

3. Automate WorkDrive Folder Creation

  1. Go to Automation > Workflow Rules in the Setup page and click Create Rule
  2. Create a Workflow Rule with the following details:
Module: Leads
Trigger: On Record Creation
Condition: All Records
Action: Custom Action (Deluge Function)


Function Logic:

1. Create a new folder in the WorkDrive combining the lead's record ID and First Name as the folder's name. Use the Invoke URL task to make the Create Folder API call. 

responseMap = Map();
attributeInfo = Map();
dataInfo = Map();
headerMap = Map();
headerMap.put("Accept","application/vnd.api+json");

// First Name and Record ID from the argument

AttributeInfo.put("name",Name + recordId);

// Parent folder ID under which you want to maintain the lead folders

attributeInfo.put("parent_id","e8gn06f2d7b3a48044090b7217524be95c9ac");
dataInfo.put("attributes",attributeInfo);
dataInfo.put("type","files");
responseMap.put("data",dataInfo);
folderCreateResponse = invokeurl
[
url :"https://zohoapis.in/workdrive/api/v1/files"
type :POST
parameters:responseMap.toString()
headers:headerMap
        connection:"workdrive_oauth_connection" // Connection Link Name created in the prerequisites  
];
info folderCreateResponse;

2. Retrieve the folder ID from the API response.

3. Update the Lead’s WorkDrive Folder ID field with this folder ID using Update Records API call. 

requestBody = Map();
dataList = List();
record = Map();

// Set field values

record.put("WorkDrive_Folder_ID",driveId);

// Add record to list

dataList.add(record);

// Wrap data

requestBody.put("data",dataList);
updateLead = invokeurl
[
url :"https://zohoapis.in/crm/v8/Leads/" + recordId
type :PUT
parameters:requestBody.toString()
connection:"crm_oauth_connection"
];
info updateLead;

Assign values to the arguments using merge fields while associating the function with Workflow Rule.



Now every Lead has its own WorkDrive folder before the widget loads. 

Notes
Note:

The complete code snippet for the deluge function is attached to the post for your reference. 

Building the Related List Widget

Step 1: Initialize the Widget Project

Review the basics from our earlier Kaizen on CLI Installation, Creating a Widget Project, and Internal hosting of the same.

Step 2: Develop your Widget

After setting up the widget project using CLI, implement the following code logic for the case we are discussing:
  1. Get the current record's ID from the PageLoad event. 
  2. With the record ID, fetch the lead details using the GET Records API call using the GET ZRC method as shown here. 
// data.Entity and data.EntitiyId are the module and record ID from PageLoad
const response = await zrc.get(
      "/crm/v8/" + data.Entity + "/" + data.EntityId
    );
 var workdriveFolderId = response.data.data[0].WorkDrive_Folder_ID;
  1. Extract the WorkDrive Folder ID from the response to get the list of files from the folder. 
  2. Since we'll be using WorkDrive APIs multiple times, let’s create a reusable instance with the Connection Link Name and API's base URL. This way, we avoid repeating the same setup for every API call.
Following is sample of how to create a custom instance:

workDriveZrc = zrc.createInstance({
    baseUrl: "https://www.zohoapis.in/workdrive/api/v1",
    connection: "workdrive_oauth_connection",
 });

You can also check out the Create Instance in the requestConfig help section to learn more. 
  1. Now, let us make the GET List of Files/Folder API call using the newly created ZRC instance.  
let apiResponse = await workDriveZrc.get(
        "/files/" + workdriveFolderId + "/files",
        {
          headers: {
            Accept: "application/vnd.api+json",
          },
        }
 );
  1. Display the file details like File Name, Type and Modified Time in a table from the API response. Save the File ID in a variable for displaying preview. 
  2. When user clicks a particular file, use the file ID to fetch the preview URL using the GET Preview Meta Data API. Then load the preview URL in an iframe to display the file. 
try {
      const previewResponse = await workDriveZrc.get(
        "/files/" + resourceId + "/previewinfo",
        {
          headers: {
            Accept: "application/vnd.api+json",
          },
        }
      );
      parsed = JSON.parse(previewResponse.data);
      console.log("Preview Data:", parsed);

      // Extract the preview_url from the expected location

      previewUrl = parsed && parsed.data && parsed.data.attributes && parsed.data.attributes.preview_url || null;

      // Remove surrounding quotes if server wrapped the url in quotes

      if (typeof previewUrl === "string") {
        previewUrl = previewUrl.replace(/^"(.*)"$/, "$1").trim();
      }
    } catch (err) {
      console.error("Error fetching preview info for resource:", resourceId, err);
 }
function showPreview(previewUrl, fileName, permalink) {
  var modal = document.getElementById("modal-container");
  var thumbnailFrame = document.getElementById("thumbnail-img");
  var caption = document.getElementById("caption");
  var workdriveLink = document.querySelector(".redirect-workdrive");

  // Load the preview URL into the iframe

  thumbnailFrame.src = previewUrl;

  // Set the file name in caption and workdrive link

  caption.textContent = fileName;
  workdriveLink.setAttribute("data-link", permalink);

  // Show the modal

  modal.style.display = "block";
}
  1. Create an Upload button for users to select files from their local. Convert the streamed files to blob and execute Upload API call using the custom ZRC instance. 
async function workdriveUpload(file, fileType, fileName, folderId) {
  const fileBlob = new Blob([file], { type: fileType });
  try {
    const formData = new FormData();
    formData.append("filename", fileName);
    formData.append("parent_id", String(folderId).trim());
    formData.append("content", fileBlob);
    const uploadResponse = await workDriveZrc.post(
      "/upload", formData,
      {
        headers: {
          "Content-Type": "multipart/form-data",
        },
      }
    );
    console.log("Upload response:", uploadResponse.data);
    return uploadResponse;
  }
  catch (error) {
    console.error("Error uploading file:", error);
    throw error; 
  }
}

Step 3: Validate and Pack

Follow the steps given in the Widget help page to validate and package the widget.

Step 4: Upload to Zoho CRM

  1. Go to Zoho CRM > Setup > Developer Hub > Widgets and click Create New Widget.
  1. Fill in the required details such as:
Name: Zoho WorkDrive
Type: Related List 
Hosting: Zoho 
File Upload: Upload the ZIP created in the dist folder within the widget project directory after packaging in the Step 3. 
Index page: /widget.html
  1. Create a related list in the Leads module and associate this widget. Refer to the Customize Related Lists help page for more information on creating a related list.

Try it Out!

A complete working code sample of this widget is attached at the bottom of this post for reference. 

Now let us see how this works from the Lead's detail page:

1. Listing the available files from Zoho WorkDrive on page load. 


2. Uploading new files to the folder.


3. Previewing all the listed files.


We hope this Kaizen helps you explore the new ZRC capabilities and build seamless file-management experiences in Zoho CRM.

Have questions or suggestions? Drop them in the comments or write to us at  support@zohocrm.com

We will circle back to you next Friday with another interesting topic. 

On to Better Building!

------------------------------------------------------------------------------------------------------

Related Reading

2. Connections - An Overview
4. CRM APIs - GET Records and Update Records 
6. CRM Customizations - Related Lists and Custom Fields.
------------------------------------------------------------------------------------------------------

Idea
Previous Kaizen: Client Script Support for Notes Related List | Kaizen Collection: Home


    • Sticky Posts

    • Kaizen #198: Using Client Script for Custom Validation in Blueprint

      Nearing 200th Kaizen Post – 1 More to the Big Two-Oh-Oh! Do you have any questions, suggestions, or topics you would like us to cover in future posts? Your insights and suggestions help us shape future content and make this series better for everyone.
    • Kaizen #226: Using ZRC in Client Script

      Hello everyone! Welcome to another week of Kaizen. In today's post, lets see what is ZRC (Zoho Request Client) and how we can use ZRC methods in Client Script to get inputs from a Salesperson and update the Lead status with a single button click. In this
    • Kaizen #222 - Client Script Support for Notes Related List

      Hello everyone! Welcome to another week of Kaizen. The final Kaizen post of the year 2025 is here! With the new Client Script support for the Notes Related List, you can validate, enrich, and manage notes across modules. In this post, we’ll explore how
    • Kaizen #217 - Actions APIs : Tasks

      Welcome to another week of Kaizen! In last week's post we discussed Email Notifications APIs which act as the link between your Workflow automations and you. We have discussed how Zylker Cloud Services uses Email Notifications API in their custom dashboard.
    • Kaizen #216 - Actions APIs : Email Notifications

      Welcome to another week of Kaizen! For the last three weeks, we have been discussing Zylker's workflows. We successfully updated a dormant workflow, built a new one from the ground up and more. But our work is not finished—these automated processes are
      • Recent Topics

      • Sync Attachments in Comments from Zoho Desk to Zoho Projects

        Hello Zoho Desk Team, We hope you're doing well. We are actively using the Zoho Desk–Zoho Projects integration, especially for reporting and managing bugs/issues between support and development teams. Current Limitation: After creating a bugs/issues via
      • Use arbitrary images in deluge

        I am sending emails from my deluge code and I would like to be able to include a few images in the email template. While I know that I could put the on a website somewhere and link to them in the HTML, that is not what I want due to email client security
      • Add a way to connect Log360 Cloud logs with Zoho analytics

        Hi, Several month ago Log360 Cloud was added to zoho one - and this is great. But as far as I see there is no prebuilt way to connect Zoho analytics to the logs we have in Log360 Cloud. Please add a prebuilt connection like we have for so many other zoho
      • Funcionalidades y configuration ZohoDesk

        Creo que no estoy sacando el provecho adecuado a la application quisiera solicitar una capacitación al respecto
      • How to call Functions and perform Write Operations using Page Scripts?

        Hi everyone, How to call a function from a Zoho Creator application within a Page Script, also how to perform write operations (adding or updating records) using page scripts?
      • Connecting Airwallex in Zoho Books

        I have a question. I’m trying to connect our Airwallex account to Zoho Books, but the integration does not seem to work. Could you please guide me on how to properly connect Airwallex? I need to see the expenses also, since it only shows the profits now
      • Questions Regarding Helpdesk & SalesIQ Customization and Email Setup

        Hello, I hope you’re doing well. I have a few questions regarding Helpdesk and SalesIQ: Can the emails sent to customers via helpdesk tickets be fully customized — including signature, subject line, and other elements? Also, is it possible to send these
      • Button Duplication when emails forwarded or replied

        When I create a new email template in campaigns and send it out it looks fine to all the users, however if that email is then on forwarded or replied to then all buttons within the email duplicate.  See below The one on the left is the original one.
      • Workdrive backup and default storage selection

        Hi community, I have been informed by Zoho that workdrive will be the default storage mechanism for crm and projects. These 2 Apps seem to have different design on how they interact with workdrive for storage. 1. Crm: seems to have files saves at the
      • Cliq iOS can't see shared screen

        Hello, I had this morning a video call with a colleague. She is using Cliq Desktop MacOS and wanted to share her screen with me. I'm on iPad. I noticed, while she shared her screen, I could only see her video, but not the shared screen... Does Cliq iOS is able to display shared screen, or is it somewhere else to be found ? Regards
      • Ask the Experts 27: Onboarding and managing support reps

        Hello everyone, We are back with our Ask the Experts (ATE) series for 2026. This year, we bring experts to help you address customer support challenges using Zoho Desk. For our first ATE, we are getting into the human side of customer support. "Every
      • CRM x WorkDrive: File storage for new CRM signups is now powered by WorkDrive

        Availability Editions: All DCs: All Release plan: Released for new signups in all DCs. It will be enabled for existing users in a phased manner in the upcoming months. Help documentation: Documents in Zoho CRM Manage folders in Documents tab Manage files
      • Assign emails to lead

        I have some contacts who refers leads but there is no away to manually assign emails to lead.   
      • sync two zoho crm

        Hello everyone. Is it possible to sync 2 zoho crm? what would be the easiest way? I am thinking of Flow. I have a Custom Module that I would like to share with my client. We both use zoho crm. Regards.
      • Built-in Date Functions in Zoho Analytics Query Tables

        I have a doubt about whether Zoho Analytics Query Tables provide built-in functions for start date, end date, and the current month
      • Introducing Rollup summary in Zoho CRM

        ------------------------------------------Moderated on 5th July'23---------------------------------------------- Rollup summary is now available for all organizations in all the DCs. Hello All, We hope you're well! We're here with an exciting update that
      • Enhancements for Currencies in Zoho CRM: Automatic exchange rate updates, options to update record exchange rates, and more

        The multi-currency feature helps you track currencies region-wise. This can apply to Sales, CTC, or any other currency-related data. You can record amounts in a customer’s local currency, while the CRM automatically converts them to your home currency
      • Marketer's Space: Why your open rates suddenly drop to zero?

        Hey everyone—welcome back to another post in Marketer's Space! If you regularly track the performance of your campaigns, open rates are probably one of the first numbers you check after sending an email. So it can be quite alarming when a campaign suddenly
      • CRM x WorkDrive: We're rolling out the WorkDrive-powered file storage experience for existing users

        Release plan: Gradual rollout to customers without file storage add-ons, in this order: 1. Standalone CRM 2. CRM Plus and Zoho One DCs: All | Editions: All Available now for: - Standalone CRM accounts in Free and Standard editions without file storage
      • Bulk upload images and specifications to products

        Hi, Many users have asked this over the years and I am also asking the same. Is there any way in which we can bulk upload product (variant) images and product specifications. The current way to upload/select image for every variant is too cumbersome.
      • Introducing Workqueue: your all-in-one view to manage daily work

        Hello all, We’re excited to introduce a major productivity boost to your CRM experience: Workqueue, a dynamic, all-in-one workspace that brings every important sales activity, approval, and follow-up right to your fingertips. What is Workqueue? Sales
      • Import Quote from CRM into document in Writer?

        Hi, I created a quote for a proposal in the Zoho CRM and was wondering if there is a way to embed the quote into a document in Zoho Writer so I can make our sales proposals look a little nicer. Is that possible?
      • Private email threads

        When sending a Private email or receiving a response once the email thread has been marked as 'Private'- is there a way to trigger the system to "restart the clock"? I am finding that when someone responds to a 'Private' thread that it is opening the
      • SLA Notification

        Team members have been receiving this notification and feel as though it is as random. Explanation on this notification is appreciated! Also, is there a way to disable this notification?
      • I'd like to Import Contacts for an SMS Campaign, but they don't have email addresses.

        I've got a contact list of about 4000 contacts. Some only have mobile phone and not email. Can I still import the contacts?
      • Incoming email replies not automatically associating with Deals/Opportunities - Is this possible in Zoho CRM?

        Hello Zoho Community, I'm running a travel agency (B2B and B2C) and we've been struggling with what seems like a basic functionality that we cannot get to work properly. Our use case: We send emails to suppliers (hotels, transportation companies) and
      • Transaction Rule Matching

        Q1. Is there a method to have the Transaction Rules applied across multiple Bank Accounts? Q2. To match "contains" text in Transaction Rules, is a wildcard or regular expression required? Is it case sensitive? Would searching for "issue" in the following
      • Newby Questions - Vendors, Customers, and Income vs. Other Income Clarifications

        Q1. For Deposits, there does not seem to be an option for "Income". "Other Income" is an option however. What is the process to add the option to assign a deposit to type "Income"? Q2. In many cases Vendors and Customer are the same. Vendors may purchase
      • Newby Questions

        Q1. The top bar of Zoho Books has a "Search in Banking (/) " field. What is the proper use of this text box? - Searching for Amazon for example has no results but there are transactions. - Is the search case sensitive? - Are regular expressions allowed?
      • Duplicate Leads Notification Help!

        Hello! I have several web forms that have a duplicate lead notification that are being sent to the creator of the web form. I understand how to change the form entry notification, but I am specifically looking to change the recipient of the "Duplicate Lead" notification. Any help you can offer is greatly appreciated! TIA, ~ Jenn
      • Bulk Associate Tasks/Task Lists to Milestones (Similar to Issues)

        Hello Zoho Projects Team, We hope you are doing well. We would like to request an enhancement regarding Milestone management for Tasks in Zoho Projects. Current Behavior: In the Issues module, it is possible to select multiple issues and easily associate
      • How to see Statement Details Shown in Unclassified Transactions in All Transactions?

        All, The list of Unclassified Transactions show the Statement Details and Descriptions. What is the method to see that column in the All Transactions list? -Thanks!
      • Zoho CRM - Feature Request - Analytics Components Group By Week Alternative Formats

        On the Zoho CRM Analytics Components, please consider adding an option to allow group by week format to be changed to other formats such as Week Commencing or Week Ending dates, rather than the current Week Number. This would provide improved usability
      • Is Zoho Sites still actively being developed?

        Hello, Is Zoho Sites still actively being developed as part of the Zoho ecosystem? I noticed that the What's New page (https://www.zoho.com/sites/whats-new.html) does not show any updates since Q1 2025. We were considering migrating our website from Squarespace
      • Adding new data to the sheet with most recent data being added to top row.

        I am using a form that I built from within sheets.  When the form is submitted, is it possible to have the data entered in (for example) row 2 (since row 1 is the heading) instead of being added into the next available row which should be hundreds of
      • Duplicate Leads Concerns with Round Robin and Lead Approval Process

        It is great to have the Duplicate Lead Approval Process, there are a few issues with the process that I would greatly appreciate taken consideration in enhancing. It appears that A Lead comes in Lead owner assigned by the Round Robin Check for Duplicate,
      • need a packing list feature

        In our business, goods listed on an invoice are packed in separate boxes and shipped off. for e.g. an invoice may have 10 items. each item could then be packed in different boxes depending on qty of each item. this packing list is as important as the invoice for purposes of shipping documents.  Request you to add this feature asap.
      • Editing Item Group to add Image

        I did not have the image of the product when the Item Group was created. Now I have the product image, and would like to associate/add to the Item Group. However the Item Group Edit functionality does not show/allow adding/changing image. Please hel
      • Zoho CRM Queries Now Support Databases and Cloud Data Sources

        Hello everyone! We're thrilled to announce a major enhancement to the Queries feature in Zoho CRM! Queries now support a broader range of external data sources, allowing you to fetch live data and combine it with CRM records, all using a unified query
      • Map: Output None

        Hi, Checking if you help me inspect this block The code below triggers during Successful form Submission from another Form. // rec_a = formA[ID!=0]; rec_b = formB[ID!=0]; ListA = List(); //subformA for each recA in rec_a.ItemSubform { for each recB in
      • Next Page