Kaizen 235 - Restore deleted records from the Recycle Bin using Zoho CRM APIs

Kaizen 235 - Restore deleted records from the Recycle Bin using Zoho CRM APIs


Welcome to another Kaizen week.

Here's a question that came up in our developer forum:

"I'm working on a piece of software to automate conversion of Leads into Deals based on order status from my company's website. There are some cases where a previously deleted Deal needs to be restored, such as when a failed order is manually corrected. Recovering a record from the recycle bin manually is trivial, but obviously I'm trying to automate the whole process. Is it possible to recover a record from the recycle bin using the API?"

This is a problem that many developers may have run into when building integrations.

Consider Zylker, a company that syncs orders from their e-commerce platform directly into Zoho CRM as Deals. Their workflow is straightforward: a new order comes in, a Deal is created. An order fails, the Deal gets deleted. Clean and simple.

But real-world workflows rarely stay that simple. Sometimes a failed order gets manually corrected on the e-commerce side. The customer fixes their payment, the warehouse confirms stock, the ops team overrides the rejection. When that happens, Zylker needs to bring that Deal back to life in CRM, complete with all its history, notes, activities, and associations.

The naive solution is to create a new Deal. But that means losing everything that was attached to the original record like call logs, emails, notes, contact role associations. For a sales team, that history is valuable. Creating a duplicate isn't a restore, it's a data integrity problem waiting to happen.

The right solution is to restore the original Deal from the Recycle Bin programmatically. This is the problem we’ll address in this post.

 What the Recycle Bin API offers 

To implement this workflow, we’ll rely on the Recycle Bin APIs available in Zoho CRM.  There are six key endpoints:

 1. Get Recycle Bin records 

Endpoint: GET {api-domain}/crm/v8/settings/recycle_bin

This endpoint fetches all deleted records across modules. In Zylker's case, this is how we search for a deleted Deal before restoring it. The API supports a filters parameter to narrow results based on module, display name, deletion time, or user.

Other supported parameters are:

  • ids - retrieve specific records by their unique IDs. Takes precedence over filters if both are provided

  • sort_by - sort by display_name, deleted_time (default), or deleted_by

  • sort_order - asc or desc

  • page / per_page - paginate through results. Maximum 200 records per page. Check "more_records": true in the response to know if more pages exist

 2. Get a single Recycle Bin record 

Endpoint: GET {api-domain}/crm/v8/settings/recycle_bin/{record_id}

This API fetches details of a specific deleted record by its ID.

This is most useful in integrations where the external system stores the CRM record ID at the time of creation.


NotesThe Recycle Bin API only returns metadata about deleted records, not the full record details. The response contains the record's id, display_name, module, owner, deleted_by, and deleted_time. If you need the full record details, you should restore the record first and then fetch it via the get records API.

 3. Restore Recycle Bin records 

Endpoint: POST {api-domain}/crm/v8/settings/recycle_bin/{record_id}/actions/restore

This API restores a specific deleted record by its ID. When a record is restored, any associated records that are also in the Recycle Bin, such as Notes, Attachments, or Activities, are restored automatically along with it. This is a key advantage over recreating the record from scratch, where all that history would be permanently lost.

Note: Records are only available in the Recycle Bin for 60 days after deletion. After that they are permanently deleted and cannot be restored via API or manually.

 4. Get Recycle Bin record count 

Endpoint : GET {api-domain}/crm/v8/settings/recycle_bin/actions/count

This API returns the total number of records currently present in the Recycle Bin.

For example, Zylker could run a nightly process that checks this endpoint first. If the count is zero, the job exits without making additional API calls.

Monitoring this count can also help detect unexpected spikes in deleted records, which may indicate faulty automation or synchronization issues.

 5. Delete Recycle Bin records 

Endpoints:

DELETE {api-domain}/crm/v8/settings/recycle_bin/{record_ID}

DELETE {api-domain}/crm/v8/settings/recycle_bin?ids={id1,id2,...}

DELETE {api-domain}/crm/v8/settings/recycle_bin?filters={filter_value}

This endpoint permanently deletes one or more records from the Recycle Bin. Unlike a regular delete that moves records to the Recycle Bin, this removes them with no possibility of recovery.

A common use case is compliance-driven data erasure. For example, when a customer requests permanent deletion of their data under regulations like GDPR, the record can first be deleted from its module and then permanently removed from the Recycle Bin.


Notes
When a record is deleted from the Recycle Bin, all its associated records like Notes, Attachments, Activities are also permanently deleted. If the total number of records exceeds 1000, the deletion is scheduled as a background job.

 6. Empty the Recycle Bin   

Endpoint: POST {api-domain}/crm/v8/settings/recycle_bin/actions/empty

This API permanently deletes all records currently present in the Recycle Bin.

This is useful at the end of a bulk data migration or a testing cycle, where large numbers of records have been deleted and need to be permanently purged without going through them individually.

Automating Deal recovery from the Recycle Bin  

Now that we've covered the available Recycle Bin APIs, let's put them to work by building a recovery workflow for Zylker's integration.

Recall that Zylker’s integration creates Deals in CRM whenever a new order is placed. If an order fails, the corresponding Deal may be deleted. Later, if the order is corrected, the integration needs to restore the original Deal so that the sales team can continue working with the same record and retain its associated history.

To automate this process, we can implement a recovery workflow that performs the following steps:

  1. Identify the deleted Deal that needs to be restored.

  2. Retrieve the corresponding record from the Recycle Bin.

  3. Restore the record programmatically.

  4. Perform post-restore updates so the sales team knows the record was recovered.

The function below demonstrates how this can be implemented using Deluge.

The function supports two recovery paths:

  • Direct restoration using a record ID when the integration already knows the Deal ID in CRM.

  • Search-based restoration using the Deal name and a time window, which helps locate the correct record when the ID is not available.

Once the Deal is restored, the function also performs a few post-restore actions:

  • Updates the Deal stage to Needs Analysis

  • Adds a note indicating that the Deal was restored and why

This keeps the sales team informed and preserves a clear activity history.

The function has three parameters:

  1. deal_name (string) - The name or partial name of the Deal to search for

  2. days (integer) - The number of days to look back from the current day

  3. record_id (string) - The CRM record ID of the deleted Deal, if known. 

The record_id parameter is optional. If provided, the function skips the search and restores the record directly. If not, it falls back to searching by deal_name and days. This makes the function flexible enough to handle both scenarios: integrations that track CRM record IDs externally, and those that don't.

Before you begin:

This function uses a Zoho OAuth connection named crm_oauth_connection to make authenticated API calls to the Recycle Bin endpoints internally. Before running the function, set it up as follows:

  1. Go to Setup > Developer Hub > Connections

  2. Click Create Connection

  3. Choose Zoho CRM as the service

  4. Set the connection name to crm_oauth_connection (this must match exactly what is used in the code)

  5. Add the following scopes:

    • ZohoCRM.modules.ALL

    • ZohoCRM.settings.recycle_bin.READ

    • ZohoCRM.settings.recycle_bin.UPDATE

  1. Click Create and Connect and complete the authorization

 

Note: If this connection expires at any point, the function will return an UnAuthenticated Connection error. Go back to the Connections page and reauthorize it to resolve this.


The full implementation of the recovery function is available for download here : restoreDeletedDeal

Let's briefly walk through the logic implemented in the function.

1. The recovery path

The function first determines which recovery path to follow based on whether a record_id is provided.

if(record_id != null && record_id.trim() != "")

If record_id is a non-empty string, the function restores the Deal directly using that ID. This is the most reliable approach because it avoids ambiguity and ensures that the correct record is restored.

If the ID is not provided, the function falls back to searching the Recycle Bin using the Deal name and a configurable time window.

2. Searching the Recycle Bin

When the record ID is unavailable, the function retrieves deleted records and filters them to locate the correct Deal.

The filtering logic ensures that:

  • Only records from the Deals module are considered

  • The Deal name matches the input

  • The record was deleted within the specified time window.

This helps narrow down the correct record and avoid restoring unrelated Deals.

if(moduleApiName == "Deals"

    && displayName.trim().toLowerCase().contains(trimmedName)

&& deletedDate >= lookbackDate)

3. Handling search results

If no matching records are found, the function returns a not found message. If exactly one match is found, its ID and name are stored and the function proceeds to the restore step. If multiple matches are found, the function returns a structured list instead of guessing which one to restore:

if(matchedRecords.size() > 1)

{

    resultMsg = "Multiple Deals found matching '" + deal_name + "'. Please call this function again with the correct record_id:\n";

    for each match in matchedRecords

    {

        resultMsg = resultMsg + "- ID: " + match.get("id")

            + " | Name: " + match.get("deal_name")

            + " | Deleted On: " + match.get("deleted_time")

            + " | Deleted By: " + match.get("deleted_by") + "\n";

    }

    return resultMsg;

}

The caller must review the list, identify the correct record, and call the function again with the record_id directly.

4. Restoring the Record

Once the correct record ID is confirmed, the function calls the Restore endpoint.

restoreResponse = invokeurl

[

    url: "https://www.zohoapis.com/crm/v8/settings/recycle_bin/" + matchedRecordId + "/actions/restore"

    type: POST

    connection: "crm_oauth_connection"

];

The response is checked for two possible success codes - SUCCESS for an immediate restore, and SCHEDULED when the record has more than 1000 associated records and the restore runs as a background job. Both are handled as successful outcomes with different return messages.

5. Post-restore updates

After a successful restore, the function updates the Deal stage and adds a Note:

dealUpdate.put("Stage", "Needs Analysis");

zoho.crm.updateRecord("Deals", matchedRecordId.toLong(), dealUpdate);

noteContent = "Deal restored by " + currentUserName + " on " + currentDate + ". Reason: Order corrected.";

zoho.crm.createRecord("Notes", note);

Both updates are placed after the restore call. If the restore fails, neither runs, keeping the CRM data consistent.

Calling the function via REST API  

One of the powerful capabilities of Zoho CRM is that standalone Deluge functions can be exposed as REST API endpoints and called from any external system. This is what allows Zylker's e-commerce backend to trigger the recovery workflow directly whenever an order is corrected.

Enabling the Function as a REST API  

Once the function is saved, follow these steps to expose it as a REST API:

  1. Go to Setup > Developer Hub > Functions

  2. Click the (three dots) next to the corresponding function (restoreDeletedDeal)

  3. Click REST API

  4. Enable the OAuth2 slider

  5. Copy the endpoint URL shown

  6. Click Save.

The endpoint will be in the following format:

POST https://www.zohoapis.com/crm/v7/functions/{function-name}/actions/execute?auth_type=oauth

While calling the function, arguments must be passed in the request body as a form-data parameter named arguments, with the values as a JSON string.

Sample: {"deal_name":"Zylker","days":10,"record_id":""}

Required scope: ZohoCRM.functions.execute.CREATE

Conclusion  

The Recycle Bin API is a powerful but often overlooked capability in Zoho CRM. As we've seen in Zylker's scenario, restoring deleted records programmatically isn't just a convenience. It is a data integrity requirement for integrations that need to maintain a consistent, unbroken history of records across systems.

We hope this post helps you build more resilient and data-safe integrations on Zoho CRM. If you have questions or want to share how you've used the Recycle Bin API in your own integrations, drop a comment below!

 

 


    • 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

    • Issue updating Multi-Select Picklist via API (saves as string instead of checking boxes)

      Hi everyone, I'm hoping someone can point out what I'm doing wrong here. I'm stuck trying to update a custom multi-select field via the Desk API and it's driving me a bit crazy. I have a multi-select picklist called "Buy years" with options like 2023,
    • Page variable not receiving URL parameter in Creator 6 HTML snippet Deluge — Canada DC

      I have a Creator 6 app on Canada DC. I'm trying to pass a URL parameter to an HTML snippet page via Deluge but the variable always returns empty. Setup: Page: MYC_Meeting_Tool Page variable declared: submission_id, type Text Page Script tab contains:
    • Zoho Campaigns API endpoint for contact details

      there is some REST API support for Zoho Campaigns, however, I am not able to find an endpoint for "get contact details".  in particular, I'd like to access contact's subscription status and also their topic. ideally there is all profile available including
    • Migrating Documentation from Notion to Zoho Help Centre

      Hi there, We have a large chunk of documentation that currently sits on Notion. However, we are eager to move this into our Zoho Help Centre/Knowledge Base. What is the most efficient way of achieving this?
    • Can't add attachment on email template

      The attachment does show up. This is my template. Hi ${Cases.Assigned Programmers}, Please be reminded about the following task that has been assigned to you. Subject : ${Cases.Subject} Description : ${Cases.Description} Ticket # : ${Cases.Request Id}
    • Edit a previous reconciliation

      I realized that during my March bank reconciliation, I chose the wrong check to reconcile (they were for the same amount on the same date, I just chose the wrong check to reconcile). So now, the incorrect check is showing as un-reconciled. Is there any way I can edit a previous reconciliation (this is 7 months ago) so I can adjust the check that was reconciled? The amounts are exactly the same and it won't change my ending balance.
    • Custom CSS for Zoho CRM Team Bookings embeded widget

      Hello, we are adding Zoho CRM Team Bookings (crm.zoho.com) in our public website. We know that we can change Theme Color, Font Color and Background Color: Zoho CRM Booking Styling But is it possible to change other CSS attributes e.g. Font Family, like
    • Standard practice rerun updated deluge function over existing recordes

      Hi folks, we have a function which is triggered via webhook from a third-party solution which then calls another api with a contact-id and gets a json payload back and then parses that data to custom fields in our CRM to the record id. As requirements
    • Specifying time increments on a Date/Time field

      Hi all, Im using a Date/Time field in my CRM module. At the moment the increments are 30 minutes. How can I change these to be 15 minutes? Thanks
    • Sort by Project Name?

      How the heck do you sort by project name in the task list views??? Seems like this should be a no-brainer?
    • Maximum limit of bank accounts

      I'm currently setting up Zoho Books in order to migrate at the start of our next financial year (April) and while adding bank accounts I've tried to add a second account from the same bank and receive an error about the maximum limit of bank accounts.
    • Account and Email and Password

      I'm signing up as a Partner so I can move my website clients across to a separate email server from their current cPanel one.. So I have a Zoho account and then I moved one of my emails across to that account to test the import process... So the question
    • Zoho Sprints iOS and Android app update: Global view. Screen capture control, file encryption, tags enhancement(iOS)

      Hello everyone! We are excited to introduce new features in the latest version(v2.1) of the Zoho Sprints iOS app update. Let’s take a quick look at what’s new. 1. Global view Global view brings all your project items into one centralised space. You can
    • Creating Restaurant Inventory Management on Zoho

      Hi,  We run a small cloud kitchen and are interested to use Zoho for Inventory and Composite Item tracking for our food served and supplied procured to make food items.  Our model is basically like subway where the customer can choose breads, veggies,
    • Price Managment

      I have been in discussions with Zoho for some time and not getting what I need. Maybe someone can help explain the logic behind this for me as I fail to understand. When creating an item, you input a sales rate and purchase rate. These rates are just
    • How do I create an update to the Cost Price from landed costs?

      Hi fellow Zoho Inventory battlers, I am new to Zoho inventory and was completely baffled to find that the cost price of products does not update when a new purchase order is received. The cost price is just made up numbers I start with when the product
    • only 100 entry download entries in Zoho Form

      Is there a way to download more than 100 entries in a form at a time? It is capped (unless I am not doing the export correctly). This is very frustrating as I want to make sure I don't miss a record when downloading data. Thanks!
    • Zoho FSM Premium Edition is Here

      As your field service operations grow, so do the complexities — managing large distributed teams, keeping sensitive data secure, generating the right reports at the right time, and ensuring every technician dispatched is the right fit for the job. The
    • Seeking a WhatsApp Business App (not API) Zoho CRM integration

      We have a business need to integrated WhatsApp Business App (not API) into Zoho CRM to centrally manage communications between our Sales team and Leads & Contact. Is there a reputable integration available for this scenario of ours? Core features we would
    • Auto-sync field of lookup value

      This feature has been requested many times in the discussion Field of Lookup Announcement and this post aims to track it separately. At the moment the value of a 'field of lookup' is a snapshot but once the parent lookup field is updated the values diverge.
    • How are other Books users integrating crypto and digital assets into Books?

      If my company owns some digital assets I would want those to exist in Books as assets, and also be able to change the value as needed when generating reports. My company would also be receiving payment in cryptocurrencies and may sell at the time of payment
    • Lets Talk Recruit: Key takeaways from our India community meetups

      Welcome back to Let's Talk Recruit — the series where we bring you real stories, product insights, and community highlights from the world of recruitment. Our last post covered how Resume Harvester can take the follow-up out of hiring. This edition is
    • Unable to create new finance account in Zoho Books Android app due to missing account number field.

      Free plan I have enabled a setting via the website requiring unique account codes to be specified for all accounts. When using the android app, go to expenses, new expense, select account, new account. Promoted to enter the Account name and description.
    • How to Fetch data from Sales Order and Insert into Purchase Order with Deluge

      Hello, I am wanting to write a Deluge script that would take the shipping address on a Sales Order and upon conversion to a Sales Order automatically insert it into that corresponding PO. I am new to Deluge but understand that it has great capabilities.
    • Google Drive shared folder

      My deluge script has stopped working, no longer collecting files from Google Drive - have these connections finally been deprecated ?? They seem to be active but errors occur when updating them ?
    • Zoho Desk: Mobile Updates | Q1 2026

      Hello everyone, Greetings! As we gear up for the end of Q1, we are excited to share a quick journey into all that released in the first quarter of 2026. We have brought in a few enhancements in the mobile apps that improve overall user experience and
    • 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
    • Additional Address - Company Name

      It would be very helpful to have a "Company Name" field in the Additional Address shipping section.  In a situation where you drop-ship orders to a different address or different company entirely, it may be necessary to list the company name of the receiver. I understand that the Attention field can be used for that purpose, but that's not really the intended purpose of that field.
    • Zoho Payroll's Kuwait, Oman, Qatar, Bahrain and Canada edition is available in Zoho One

      Great news for Zoho One users! Zoho Payroll has expanded to five new regions: Kuwait, Oman, Qatar, Bahrain, and Canada. And the best part? These new editions are fully integrated with Zoho One, just like our existing editions in India, the UAE, Saudi
    • Does Zoho Creator support multilingual translation for user-entered data?

      I understand that Zoho Creator provides localization support for UI elements such as field labels and static text. I would like to know: Does Zoho Creator support automatic translation of user-entered data (for example, form inputs or stored records)
    • Upload field on tasks module

      Hello, Why I cannot add an upload field to a Task? Or maybe when creating the task make attachements visible, so you can add an attachement while creating the task? Looking forward to your response! Moderation Update: The Canvas detail view for the Tasks
    • WhatsApp phone number migration

      Hi @Gowri V and @Pheranda Nongpiur, Thanks for implementing the promised enhancements to the integration between Zoho CRM and WhatsApp. The previous discussion has been locked, so I'm opening this new one. I am copying below a specific
    • How to let club members update their own profile data

      Our club has about 200 members. We keep names, addresses, phones, emails, payment records, etc. for each, recently migrated to Creator. Once a year I send email to each member to confirm or correct their info on file with us, as well as ask for payment
    • Document retention in Zoho Sign

      Document management doesn’t end at signing. It extends to how long you retain agreements—and how securely you dispose of them. With the document retention option in Zoho Sign, you can define structured, policy-driven timelines for managing completed documents.
    • Sales Allowed Beyond Available Stock and Payment Recorded Without Restriction

      Hi, While testing in Zoho Inventory, I noticed that a sales order can be created with a quantity exceeding the available stock in the selected warehouse. In my case: Available stock: 5 units Ordered quantity: 6 units Despite this: I was able to convert
    • Deleting, Adding and Changing a Zoho Books Entry

      Zoho Books Community & Support, If a bulk upload of entries were added to an account, what is the process to: - Delete an entry - Change the amount of an entry - Is there a means to manually add an entry other than upload?
    • 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
    • The Social Playbook March edition: Myth vs Facts

      We’ve all heard a lot of myths growing up. Some sound convincing, some feel believable, and over time they start to feel like facts. But the truth is, a myth is still a myth until it’s backed by real facts. Marketing is no different. Over time, many ideas
    • Updating Analytical Fields Data

      Dear Zoho team, I'm having an issue with the recently added fields in both Analytical Desk and Analytical. How can I generate the data in Analytical when new fields are added? https://analytics.zoho.com/workspace/2436819000000007005/edit/24368190000
    • Marketing Tip #26: Optimize product images for SEO

      Product images can do more than make your store look good. They can also help customers discover your products through search. Since search engines can’t "see" images, they rely on text signals to understand what an image is about. Two small actions make
    • Next Page