Smart Document Automation:: From Zoho Projects to Zoho Writer – Merge, Edit, and Share

Smart Document Automation:: From Zoho Projects to Zoho Writer – Merge, Edit, and Share

Hello Everyone, 

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

In this post, I will present a specific use case that demonstrates the integration between Zoho Projects and Zoho Writer.


Use Case:

Merge data from Zoho Projects into a predefined template in Zoho Writer.
Automatically generate a fillable document.
Share the document link with a designated user, either specified within Zoho Writer or Zoho Projects.
Include fillable fields within the merge template, allowing the recipient to complete the necessary information.

This functionality has been successfully implemented using Custom Functions. The following steps outline the setup process. Refer to the attached screenshots for additional context.

Step 1: Navigate to Zoho Writer → Automate → Merge Template
Step 2: Click on 'Convert'
Step 3: Select a data source to start merging
Step 4: Select 'Custom Source'
Step 5: Click on 'Use' next to the Projects Fields
Step 6: Once done, enter the Zoho Org ID i.e., ZOID within the portalID.
Step 7: Click on 'Connections' within the same page → Create a Connection with the mentioned scopes.
Step 8: Click on 'Manage Fields' → Drag and Drop the required fields.
Step 9: You can setup the Merge options as per your concern as in this screen shot
Step 10: Click on 'Merge & Share Fillable Link'
Step 11: Select the required field from the 'Fields & Buttons'
Step 12: Configure the 'Merge & share fillable link'
Step 13: Click on 'Configure from submit actions' → Webhook & Custom Functions → Execute Custom Functions.

The following functionality can be achieved using the code provided below. Additionally, two connections must be created as outlined

  1. Zoho Projects Connection :: Create a connection for the Zoho Projects service with the following scopes 'ZohoProjects.projects.READZohoProjects.milestones.READZohoProjects.tasklists.READZohoProjects.tasks.READZohoProjects.users.READ, and ZohoProjects.clients.READ'.

    Update the placeholder 'xxxxxxxxx' with the actual connection name in ZPConnection.

  2. Zoho OAuth Connection :: Create a connection for the Zoho OAuth service with the following scopes 'ZohoWriter.documentEditor.ALL and ZohoWriter.Merge.ALL'.

    Replace 'yyyyyyyyy' with the actual connection name in ZWConnection.

For detailed guidance on creating a connection, please refer to this link. The required code is provided below.

//connections for authentication
tomailaddress = "a@b.com";
ZPConnection = "xxxxxxxxx";
ZWConnection = "yyyyyyyyy";
projectsDomain = "https://projectsapi.zoho.com/";
writerDomain = "https://zohoapis.com/";
headers = Map();
// Mandatory header - Do not remove
headers.put("x-zoho-service","ZohoWriter");
//Domain url for Projects and Writer
projectsDetailsUrl = projectsDomain + "restapi/portal/" + portalId + "/projects/" + projectId + "/";
milestoneDetailsUrl = projectsDomain + "restapi/portal/" + portalId + "/projects/" + projectId + "/milestones/";
taskListDetailsUrl = projectsDomain + "restapi/portal/" + portalId + "/projects/" + projectId + "/tasklists/";
taskDetailsUrl = projectsDomain + "restapi/portal/" + portalId + "/projects/" + projectId + "/tasks/";
projectsUsersUrl = projectsDomain + "/api/v3/portal/" + portalId + "/projects/" + projectId + "/users";
clientUsersUrl = projectsDomain + "api/v3/portal/" + portalId + "/projects/" + projectId + "/clients/users";
mergeFieldsUrl = writerDomain + "/writer/api/v1/documents/" + templateId + "/fields";
mergeAndStoreUrl = writerDomain + "/writer/api/v1/documents/" + templateId + "/merge/sharetofill";
projectsCommentUrl = projectsDomain + "api/v3/portal/" + portalId + "/projects/" + projectId + "/comments";
getAllFields = invokeurl
[
url :mergeFieldsUrl
type :GET
connection:"writer"
];
if(!getAllFields.contains("error") && getAllFields.getJSON("merge").size() > 0)
{
values_map = Map();
projectDetails = invokeurl
[
url :projectsDetailsUrl
type :GET
headers:headers
connection:"connectionprojects"
];
if(!projectDetails.contains("error"))
{
projectFieldValues = projectDetails.getJson("projects").get(0);
projectCF = false;
if(projectFieldValues.contains("custom_fields"))
{
projectCF = true;
projectCustomfields = projectFieldValues.getJSON("custom_fields");
}
for each  mergeField in getAllFields.getJson("merge")
{
if(projectFieldValues.containsKey(mergeField.getJSON("id")))
{
if(mergeField.getJSON("id") == "TAGS")
{
tagList = List();
for each  tag in projectFieldValues.getJSON("TAGS")
{
tagList.add(tag.getJSON("name"));
}
values_map.put(mergeField.get("id"),tagList);
continue;
}
else
{
values_map.put(mergeField.get("id"),projectFieldValues.getJSON(mergeField.getJSON("id")));
continue;
}
}
// merge project customfields
if(projectCF == true)
{
for each  field in projectCustomfields
{
if(field.containsKey(mergeField.getJSON("id")))
{
values_map.put(mergeField.get("id"),field.getJSON(mergeField.getJSON("id")));
break;
}
}
}
// merge milestone details
if(mergeField.get("id") == "milestone_details")
{
milestoneDetilList = List();
MilestoneDetails = invokeurl
[
url :milestoneDetailsUrl
type :GET
headers:headers
connection:"connectionprojects"
];
if(!MilestoneDetails.contains("error"))
{
allMilestonedetails = MilestoneDetails.getJson("milestones");
for each  milestone in allMilestonedetails
{
milestoneDetilMap = Map();
for each  milestoneField in mergeField.getJSON("fields")
{
mergeFieldId = milestoneField.get("id");
mergeFieldName = mergeFieldId.subString("milestone_details.".length(),mergeFieldId.length());
//merge milestone fields
if(milestone.containsKey(mergeFieldName))
{
if(mergeFieldName == "tags")
{
tagList = List();
for each  tag in milestone.getJSON(mergeFieldName)
{
tagList.add(tag.getJSON("name"));
}
milestoneDetilMap.put(mergeFieldId,tagList);
continue;
}
else if(mergeFieldName == "status")
{
milestoneDetilMap.put(mergeFieldId,milestone.getJson("status_det").getJson("name"));
continue;
}
else
{
milestoneDetilMap.put(mergeFieldId,milestone.getJson(mergeFieldName));
continue;
}
}
}
milestoneDetilList.add(milestoneDetilMap);
}
values_map.put("milestone_details",milestoneDetilList);
}
}
// merge tasklist details
if(mergeField.get("id") == "tasklist_details")
{
taskListDetilList = List();
getTasklistDetails = invokeurl
[
url :taskListDetailsUrl
type :GET
headers:headers
connection:"connectionprojects"
];
if(!getTasklistDetails.contains("error"))
{
taskListdetails = getTasklistDetails.getJson("tasklists");
for each  tasklist in taskListdetails
{
taskListDetilMap = Map();
for each  taskListField in mergeField.getJSON("fields")
{
mergeFieldId = taskListField.get("id");
mergeFieldName = mergeFieldId.subString("tasklist_details.".length(),mergeFieldId.length());
//merge tasklist fields
if(tasklist.containsKey(mergeFieldName))
{
if(mergeFieldName == "tags")
{
tagDetails = List();
for each  tag in tasklist.getJson(mergeFieldName)
{
tagDetails.add(tag.getJSON("name"));
}
taskListDetilMap.put(mergeFieldId,tagDetails);
continue;
}
else
{
taskListDetilMap.put(mergeFieldId,tasklist.getJson(mergeFieldName));
continue;
}
}
}
taskListDetilList.add(taskListDetilMap);
}
values_map.put("tasklist_details",taskListDetilList);
}
}
// merge task details
if(mergeField.get("id") == "task_details")
{
taskDetilList = List();
getTaskDetails = invokeurl
[
url :taskDetailsUrl
type :GET
headers:headers
connection:"connectionprojects"
];
if(!getTaskDetails.contains("error"))
{
taskdetails = getTaskDetails.getJson("tasks");
for each  taskdetail in taskdetails
{
taskDetilMap = Map();
taskCFs = false;
if(taskdetail.contains("custom_fields"))
{
taskCFs = true;
taskCustomfields = taskdetail.getJSON("custom_fields");
}
for each  taskField in mergeField.getJSON("fields")
{
mergeFieldId = taskField.get("id");
mergeFieldName = mergeFieldId.subString("task_details.".length(),mergeFieldId.length());
//merge task fields
if(taskdetail.containsKey(mergeFieldName))
{
if(mergeFieldName == "tasklist" || mergeFieldName == "status")
{
taskDetilMap.put(mergeFieldId,taskdetail.getJson(mergeFieldName).getJson("name"));
continue;
}
else if(mergeFieldName == "tags")
{
tagDetails = List();
for each  tag in taskdetail.getJson(mergeFieldName)
{
tagDetails.add(tag.getJSON("name"));
}
taskDetilMap.put(mergeFieldId,tagDetails);
continue;
}
else
{
taskDetilMap.put(mergeFieldId,taskdetail.getJson(mergeFieldName));
continue;
}
}
else if(taskdetail.containsKey("details"))
{
if(mergeFieldName == "owners")
{
ownerDetail = List();
ownerList = taskdetail.getJson("details").getJSON("owners");
for each  owner in ownerList
{
ownerDetail.add(owner.getJson("name"));
}
taskDetilMap.put(mergeFieldId,ownerDetail);
continue;
}
}
else if(taskdetail.containsKey("log_hours"))
{
if(mergeFieldName == "billable_hours" || mergeFieldName == "non_billable_hours")
{
taskDetilMap.put(mergeFieldId,taskdetail.getJson("log_hours").getJSON(mergeFieldName));
continue;
}
}
//merge task customfields
if(taskCFs == true)
{
for each  taskCF in taskCustomfields
{
if(taskCF.containsKey(mergeFieldName))
{
taskDetilMap.put(mergeFieldId,taskCF.getJson(mergeFieldName));
break;
}
}
}
}
taskDetilList.add(taskDetilMap);
}
values_map.put("task_details",taskDetilList);
}
}
// merge projectUsers
if(mergeField.get("id") == "project_users")
{
projectUserList = List();
getProjectUsers = invokeurl
[
url :projectsUsersUrl
type :GET
connection:"connectionprojects"
];
if(!getProjectUsers.contains("error"))
{
projectUserdetails = getProjectUsers.getJson("users");
for each  userDetails in projectUserdetails
{
projectUsersMap = Map();
for each  userField in mergeField.getJSON("fields")
{
mergeFieldId = userField.get("id");
mergeFieldName = mergeFieldId.subString("project_users.".length(),mergeFieldId.length());
//merge projectusers fields
if(mergeFieldName == "role")
{
if(userDetails.get(mergeFieldName).size() > 0)
{
projectUsersMap.put(mergeFieldId,userDetails.getJSON(mergeFieldName).getJSON("name"));
continue;
}
}
else if(mergeFieldName == "profile")
{
if(userDetails.get(mergeFieldName).size() > 0)
{
projectUsersMap.put(mergeFieldId,userDetails.getJSON(mergeFieldName).getJSON("name"));
continue;
}
}
else
{
projectUsersMap.put(mergeFieldId,userDetails.getJSON(mergeFieldName));
continue;
}
}
projectUserList.add(projectUsersMap);
}
values_map.put("project_users",projectUserList);
}
}
// merge clients users
if(mergeField.get("id") == "client_users")
{
clientUserList = List();
getProjectClientUser = invokeurl
[
url :clientUsersUrl
type :GET
connection:"connectionprojects"
];
if(!getProjectClientUser.contains("error"))
{
clientUserdetails = getProjectClientUser.getJson("clients").getJSON("users");
for each  userDetails in clientUserdetails
{
clientUsersMap = Map();
for each  userField in mergeField.getJSON("fields")
{
mergeFieldId = userField.get("id");
mergeFieldName = mergeFieldId.subString("client_users.".length(),mergeFieldId.length());
// merge clientsUsers
if(!mergeFieldName == "profile")
{
clientUsersMap.put(mergeFieldId,userDetails.getJSON(mergeFieldName));
continue;
}
else
{
clientUsersMap.put(mergeFieldId,userDetails.getJSON("profile").getJson("name"));
continue;
}
}
clientUserList.add(clientUsersMap);
}
values_map.put("client_users",clientUserList);
}
}
}
mergeDataParams = Map();
mergeDataParams.put("merge_data",{"data":values_map});
mergeAndStore = invokeurl
[
url :mergeAndStoreUrl
type :POST
parameters:mergeDataParams
connection:"writer"
];
if(!mergeAndStore.containsKey("error") && mergeAndStore.containsKey("merge_report_url"))
{
   mailMessage =  "Fill in the document " + mergeAndStore.get("records").get(0).get("fillable_link");
sendmail
[
from :zoho.loginuserid
to :tomailaddress
subject :"Fillable document link"
message :mailMessage
]
}
return mergeAndStore;
}
else
{
return projectDetails;
}
}
else
{
return getAllFields;
}

Creating custom functions in Zoho Projects is a straightforward process, supported by comprehensive documentation. Zoho offers a variety of built-in functions that serve as useful starting points, and you can also define your own functions using Zoho’s scripting language, Deluge. Implementing these functions can significantly enhance efficiency and improve productivity.

Stay tuned for additional examples and custom function scripts.


      • Sticky Posts

      • Accessibility Spotlight Series - 1

        Every user interacts with products differently, what feels intuitive to one may be challenging for another. Addressing this, accessibility is built into Zoho Project's design philosophy. This helps users navigate and perform actions with ease irrespective
      • Customize User Invites with Invitation Templates

        Invitation Templates help streamline the invitation process by allowing users to create customized email formats instead of sending a one-size-fits-all email. Different invitation templates can be created for portal users and client users to align with
      • Zoho Projects - Q3 Updates | 2025

        Hello Users, The final quarter of the year 2025 has begun, and we at Zoho Projects are all set with a plan. New targets to achieve and new milestones to reach, influenced by the lasting imprint of the past quarter. 2025's Q3 saw some new features and
      • Introducing Version-3 APIs - Explore New APIs & Enhancements

        Happy to announce the release of Version 3 (V3) APIs with an easy to use interface, new APIs, and more examples to help you understand and access the APIs better. V3 APIs can be accessed through our new link, where you can explore our complete documentation,
      • Schedule Exports for Regular Project Updates

        Tracking project data often means exporting data at regular intervals. Instead of manually exporting data every time, users can schedule exports for Phases, Tasks, and Tasks in Zoho Projects. These exports can be set to run once, daily, weekly, or monthly

        • Recent Topics

        • Send Automated WhatsApp Messages and Leverage the Improved WhatsApp Templates

          Greetings, I hope all of you are doing well. We're excited to announce a major upgrade to Bigin's WhatsApp integration that brings more flexibility, interactivity, and automation to your customer messaging. WhatsApp message automation You can now use
        • Weekly Tips: Manage External Images in Zoho Mail

          When you receive emails every day, whether from clients, newsletters, or services, many of them contain external images that automatically load when you open the message. While this can make emails look more engaging, it can also impact your privacy and
        • Implementing a Self-Invoicing/Vendor Portal in Zoho Creator

          Hello Zoho Community / Creator Experts, We would like to build a Self-Invoicing Portal (Vendor Portal) in Zoho Creator for our external contractors. Our goal is to allow approved contractors to log in, submit their invoice details (hours worked, project
        • Resizing a Record Template Background Inage

          Hi everyone, I have an issue which I can't seem to resolve: Basically, I'm designing a record template in certificate form. I've specified A5 landscape. I've set my background image the same dimensions with total pixels at 443,520. Whatever I try, when
        • Function #32: Schedule low stock notifications on a timely basis to specific users of the organization

          Hello everyone and welcome back to our series! For a business that heavily relies on inventory, monitoring the stock levels and getting timely notifications of low stock items will ensure a smooth sail. Zoho Books allows you to always keep a check on
        • Desk Field Not Showing in Analytics

          Hi there, I recently added a field to our Zoho Desk Ticket Information. I went and added the data retrospectively to the tickets. It is also marked as required, so all new tickets cannot be closed off without it being filled in. When I try to run a report
        • Is it really true that I can't set the default 'deposit to' account in 2025?

          I've been using Books for 7 years and the default account has never been a problem. I usually manually reconcile invoices and have never had a thought about which account. It has always been my account. However, I recently noticed that for the past 4
        • SINCH HUB MESSAGEMEDIA with ZOHO DESK

          1) what I need from MessageMedia, 2) what I want to confirm on the Zoho Desk Dev Forum. MessageMedia – needs and requirements Goal: Send SMS from a Zoho Desk widget for EU users. Auth: HTTP Basic (API Key + Secret). Keys must not live in the browser.
        • Function #46: Auto-Calculate Sales Margin on a Quote

          Welcome back everyone! Last week's function was about displaying the discount amount in words. This week, it's going to be about automatically calculating the sales margin for a particular quote, sales order or an invoice. Business scenario Where there is sales, there's also evaluation and competition between sales reps. A healthy rivalry helps to better motivate your employees to do smart work and close deals faster and more efficiently. But how does a sales rep get evaluated? 90% of the time, it's
        • Invalid URL error when embedded sending url into iframe for my website when using in another region

          Hi team, My site is currently working on integrating your signature feature as part of the system functionality, it's working great but recently there's been a problem like this: After successfully creating the document, i will embed a sending url into
        • 2024 Email Authentication Standards: Elevating Security with Google and Yahoo

          In contemporary email communication, email authentication plays a pivotal role in mitigating email fraud, spam, and phishing attacks. Brace yourself for a new level of security. Starting February 2024, Gmail and Yahoo will be implementing robust email
        • New features released: Data from Picture for Web, Pattern Fill, and Translation in Zoho Sheet!

          Hello Sheet users, In 2024, the Zoho Sheet team focused on research and development to bring new features that add to functionalities like productivity, data management, collaboration, and more. This year, we're all set to roll them out incrementally
        • Add Custom Field Inside Parts Section

          How to Add Custom Field Inside Parts Section in Workorder like Category and Sub- Category
        • Kaizen #59 - Creating alerts and custom messages using Client Script

          Hello everyone! We are happy to resume our Zoho CRM Developer Community series - The Kaizen series! Welcome back to the new start of Kaizen! This post is about Client Script and its simple use cases involving ZDK Client functions. What is Client Script?
        • [Webinar] Zoho Writer for content creators and publishing houses

          Managing multiple drafts, edits, and client reviews doesn't have to slow you down. Join our upcoming webinar to see how Zoho Writer helps content creators and publishing houses create, edit, and publish seamlessly—all in one place. You'll learn how to:
        • Universal search

          Hi, it would be useful if the search bar was universal-so if you entered a term, it would bring up results from contacts, candidates, clients etc all at the same time (but broken down under the relevant headings)
        • Attachment reminder?

          My team and I often need to attach files to our messages, e.g. an explanatory screenshot or a shipping label. More often that I want to admit I mention the attachment but forget to actually attach it. Some email clients have a check-for-missing-attachments
        • New Customization options in the module builder: Quick Create and Detail view

          Hello everyone, We have introduced two new components to the module builder: Quick create and Detail view. The Quick Create Component It is a mini form used to create a record and associate it to the parent record from a lookup field. For example, if you have a Deals lookup in the Contacts module, then you can associate existing deals or create a deal and associate it with the contact. You can customize this Quick Create form by adding standard as well as custom fields. There is no limit to the number
        • Calendar not working

          Are we the only ones. On any browser we cannot click on any of our calendar appointments and get them to open. They just make the browser loop. WE have reached out and have been told they are working on it. The office staff are really stuck. The point
        • ZIA in Zoho Cliq

          Is It possible to use the ZIA feature from Zoho Analytics in the Zoho Cliq?
        • Automating CRM backup storage?

          Hi there, We've recently set up automatic backups for our Zoho CRM account. We were hoping that the backup functionality would not require any manual work on our end, but it seems that we are always required to download the backups ourselves, store them,
        • Multiple upload field CRM

          I desperately need the functionality to add more than one upload field to web to contacts form. How can I do this?
        • Good news! Calendar in Zoho CRM gets a face lift

          Dear Customers, We are delighted to unveil the revamped calendar UI in Zoho CRM. With a complete visual overhaul aligned with CRM for Everyone, the calendar now offers a more intuitive and flexible scheduling experience. What’s new? Distinguish activities
        • Critical Need for Global Search in Zoho FSM

          Hello Zoho FSM Team, We are currently in the process of deciding whether to fully transition to Zoho FSM for managing our field service operations. At present, our team actively uses Zoho Desk (with over 50 users) and Service Fusion, which we are considering
        • Collections Management: # 1 Payment Collection is All About Convenience

          "Sir, can you come tomorrow? My manager wasn't available for the cheque sign-off", the customer said, avoiding eye contact. Ravi forced a polite smile, but inside, he felt a sense of defeat. He had already visited the customer's office twice in the last
        • Can the Product Image on the Quote Template be enlarged

          Hello, I am editing the Quote Template and added ${Products.Product Image} to the line item and the image comes up but it is very tiny. Is there anyway that you can resize this to be larger? Any help would be great! Thanks
        • Deleting Fields in CRM Deletes Views in Analytics

          Hey friends! I'm having some issues when we modify some fields within ZohoCRM. There are times where we need to sunset a field and eventually completely remove it. In these instances, it seems like a lot of views are removed in Analytics. This ranges
        • Updating custom fields in Zoho Projects

          Hi I am wondering if anyone has experience with custom fields in Zoho Projects. I am struggling to update the field using either deluge or the api endpoint. My code is: //custom_Map = map(); custom_Map = {"UDF_DOUBLE_1":"0.27"}; update_Map = map(); update_Map.put("custom_fields",custom_Map.toList());
        • Audio/video quality issues with Zoho Meeting – Any roadmap for improvement?

          Hi Zoho Team, We’ve been using Zoho Meeting for both internal and external meetings, and unfortunately, the experience has been consistently poor. The video and audio quality are so unreliable that it often renders meetings ineffective—especially with
        • Pin multiple columns and adjust column widths in CRM subforms

          Hello all, Subforms act as secondary forms or tables in which you can associate multiple line items to a primary record and thereby ensure more structured and comprehensive data organization. We've made some recent enhancements to subforms. Here's what's
        • Paste issues in ZOHO crm notes

          Hi, since a week or so I have issues with the paste function in ZOHO CRM. I use "notes" to copy paste texts from Outlook emails and since a week or so, the pasting doesnt function as it should: some text just disappears and it gives a lot of empty lines/enters.....
        • Cash based businesses cannot use the new fixed asset module

          Hello all, If your bookkeeping is reporting in cash, you cannot use the new fixed acid module, as it does all the depreciation bookings accrual and not cash. This is definitive and you can't turn them into a cash booking. They will never appear in your
        • Zoho Learn & Zoho Connect

          Hi, Is there a way to sync the knowledge base we have in Zoho Learn with the manuals section is Zoho Connect? Thanks,
        • Modifying iframe data of Zoho booking iframe

          Hello, I have integrated a Zoho Bookings embedded iframe into my website. Currently, I am pre-filling the booking form with default values as part of our process flow. However, I want to ensure that if an input field is already populated with a default
        • Apply Payment Received Amount Zoho Books Invoice

          Hello team here is the sample code How can apply the payment received record over a unpaid zoho books invoice. //......................... paymentID = customer_payment.get("payment_id"); organizationID = organization.get("organization_id"); paymentmaplist
        • Enhance Sign CRM integration

          Hello all, I'm working on a custom Deluge script to enhance the integration between Zoho CRM and Sign by using a writer merge template for additional flexibility. I want to replicate the post-sign document integration that exists between CRM and Sign
        • Zoho Books Finance Modules Not Accessible in Zoho CRM Mobile App

          We have integrated Zoho CRM with Zoho Books using the Zoho Finance Suite integration. In the CRM web version, we can see the Finance modules (Estimates/Quotes, Invoices, Sales Orders, Items, Payments) and are able to create invoices and quotes directly
        • Does Zoho offer a full WhatsApp Marketing Platform (like WATI / GallaBox)?

          lm exploring WhatsApp marketing and I’d like to understand what options are available within the Zoho ecosystem. Currently, I see: Zoho SalesIQ has a broadcast option, but it seems very limited — for example, it doesn’t support uploading contacts via
        • 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
        • [Live Webinar] New in Zoho WorkDrive: AI enhancements, Data Loss Prevention, Version Controls, and more

          Hello everyone, We're excited to bring you another round of powerful updates in Zoho WorkDrive! Join us on May 15 for an exclusive live webinar where we’ll unveil the latest features designed to enhance your team’s productivity, collaboration, and data
        • Next Page