Kaizen #12 - Bulk Read API

Kaizen #12 - Bulk Read API

Hello everyone!
We hope you all are having a wonderful start in the New Year!
Welcome back to another post in the Kaizen series!

In this post, we will discuss the Bulk Read API in detail.

What is the Bulk Read API?

The Bulk Read API allows you to export data from a module in Zoho CRM in bulk. The primary difference between the GET records API and the Bulk Read API is the number of records you can retrieve.
While you can get only 200 records per Get records API call, you can fetch 200,000 records per bulk read API call.

When should you use this API?

  • When you want to export more than 200 records through an API call.
  • When you want to perform background processes like migration, data backup, and initial data sync between Zoho CRM and external services.

What is the difference between GET Records API and Bulk Read API?

GET Records
Bulk Read API


You can fetch a maximum of 200 records per API call.


You can fetch a maximum of 200,000 records per API call.

The response is available instantly.

The response is not available instantly; the bulk read job is scheduled, and the status is available after job completion in the callback URL.

The records are available as JSON objects in the response.

The records are available in a downloadable CSV file or ICS file (for events).

What kind of export does the Bulk Read API support?

You can export 
  • Records available in a custom view. You can also apply the criteria on the records available in that custom view to filter the records further. Note that you cannot export records in the Co-owner, Shared by Me, and Shared to Me views.
  • Lookup fields of records in a module using the dot (.) operator.
  • Records in the events module as an ICS file.

How does the Bulk Read API work?

Scheduling a bulk read job encompasses the following steps.
  1. Creating a bulk read job.
  2. Getting the status of the scheduled job.
  3. Downloading the result.
We will now see each of these steps in detail.

Step-1: Creating a bulk read job

This involves making a POST API call to schedule a job to fetch records that match certain criteria, along with the required fields.
When this call is successful, the response returns an id. You can use this id to know the status of the job by polling, or check the job completion in the callback URL.

Request URL: {{api-domain}}/crm/bulk/v2/read
Request Method: POST

Consider an example where you want to export records from the Contacts module.
The below query fetches the records that matches one of the three criteria— 
  • The lead source is Advertisement (or)
  • The owner's last name is Boyle (or)
  • The phone number of the account associated with the contact contains the numbers 99807. 
The fields to be fetched are mentioned in the fields array. To fetch all fields in the module, do not input the fields key.

In this query, Account_Name is the default lookup field in the Contacts module. Owner.last_name returns the last name of the owner of the contact, Account_Name returns the ID and Account_Name.Account_Name returns the name of the account associated with the contact, and Account_Name.Phone returns the phone number of the account associated with the contact.

{
    "callback": {
        "url": "https://www.example.com/callback",
        "method": "post"
    },
    "query": {
        "module": "Contacts",
        "fields": [
            "Last_Name",
            "Owner",
            "Owner.last_name",
            "Account_Name.Account_Name",
            "Account_Name.Phone",
            "Lead_Source",
            "Created_Time"
        ],
        "criteria": {
            "group_operator": "or",
            "group": [
                {
                    "api_name": "Lead_Source",
                    "comparator": "equal",
                    "value": "Advertisement"
                },
                {
                    "api_name": "Owner.last_name",
                    "comparator": "equal",
                    "value": "Boyle"
                },
                {
                    "api_name": "Account_Name.Phone",
                    "comparator": "contains",
                    "value": "99807"
                }
            ]
        },
        "page": 1
    }
}

The below table gives the description of the keys in the sample input.

Key and Data Type
Mandatory
Description
callback
JSON Object
Yes
Contains a valid URL, which should allow the HTTP POST method. The Bulk Read Job's details are posted to this URL on successful completion or failure of the job.
query
JSON Object
Yes
Contains the module, fields that you want to export, criteria based on which you want to export the records, and the page. Refer to the query properties table below for more details.
file_type
String
Yes, when you want to export the events as an ICS file.
Specify the value of this key as "ics" to export all records in the Events module as an ICS file.

query properties

Key and Data Type
Mandatory
Description
module
String
Yes
The API name of the module from which you want to export the records. Specify the module name as "Events" if you want to export the records in the Events module as an ics file.
cvid
String
Yes, when you want to export records in a custom view
The unique ID of the custom view whose records you want to export. You can obtain the cvid from the Custom View Metadata API.
fields
JSON Array
No
The API Name of the fields you want to export from the module. Example: First_Name, Last_Name, Email, Owner.last_name. Do not input this key when you want to export the records in the Events module as an ICS file. The system throws FIELDS_NOT_SUPPORTED error, otherwise.
page
Integer
No
Default value for page is 1. The page value '1' means that the first 200,000 records matching your query will be exported. If you want to fetch the records from the range of 200,001 to 400,000, then you should mention the page as '2'. The maximum value for this key is 500.
criteria
JSON Object
No
To filter the records you want to export. This JSON object contains the API name of the field, comparator, and a group. Refer to the criteria properties table below for more details.

criteria properties

Key and Data Type
Mandatory
Description
api_name
String
Yes, if group and group_operator are not specified.
API name of the field you want to compare. Example: First_Name, Last_Name, Owner.last_name etc,. Example:
"criteria": {
        "api_name": "Lead_Source",
        "comparator": "equal",
        "value": "Advertisement"
    }
value
String or JSON array
Yes, if group and group_operator are not specified.
Positive integer values only.
group_operator
String
Yes, if api_name, comparator & value are not specified.
Logical operators. Supported values are and, or.
group
JSON array
Yes, if api_name, comparator & value are not specified.
Array of criteria objects.
comparator
String
Yes, if group and group_operator are not specified.
Specifies the comparator. Example: equal, greater_than. Refer to the comparators table for more details.

comparators

Data Type
Comparator
Value and Limits
Number (Integer),
Decimal/BigInteger/
Currency/Percent)
equal, not_equal, in, not_in, less_than, less_equal, greater_than, greater_equal
Any number values or ${EMPTY} for empty value. 
Not more than 19 digits for big integer, allows decimal values for decimal and currency fields. In multi-currency enabled accounts, only home currency value is supported.
Text (Email, Phone, URL, Picklist, Multi-select, etc)
equal, not_equal, in, not_in, contains, not_contains, starts_with, ends_with
Any text or ${EMPTY} for empty value.
Not more than 255 characters.
Date
equal, not_equal, in, not_in, between, not_between
Any date value in ISO 8601 format or ${EMPTY} for empty value.
DateTime
equal, not_equal, in, not_in, between, not_between
Any date time value in ISO 8601 format or ${EMPTY} for empty value. Example: 2019-04-01T14:24:04+05:30.
Milliseconds are not supported.
Boolean
equal
true or false.
Lookup
equal, not_equal, in, not_in
Biginteger value of the lookup, ${EMPTY} for empty value, or use the .(dot) operator to establish a relation between two modules.
Example: In the Contacts module, Owner fetches the ID of the Owner, whereas Owner.last_name fetches the last name of the owner. Account_Name fetches the ID of the Account associated with the base module, whereas Account_Name.Phone fetches the phone number of the account associated with the base module.
Text Area (Multi-line)
Not supported
Not supported

The response to the sample query is as follows. You can use the id in the details key to check the job status periodically as explained in step-2.

{
    "data": [
        {
            "status": "success",
            "code": "ADDED_SUCCESSFULLY",
            "message": "Added successfully.",
            "details": {
                "id": "3652397000000646004",
                "operation": "read",
                "state": "ADDED",
                "created_by": {
                    "id": "3652397000000186017",
                    "name": "Patricia Boyle"
                },
                "created_time": "2019-04-01T14:24:04+05:30"
            }
        }
    ],
    "info": {}
}

For more details and examples, refer to the Create Bulk Read Job page of our API guide.


Step-2: Getting the status of the scheduled bulk read job 


The bulk read API supports polling and callback.

Polling 
You can poll (check the status of the scheduled bulk read job) with the job ID you received in the previous step.
If you do not want to poll for the status of the job, you can wait for the system to notify you of job completion on the callback URL provided in the POST request.

Request URL: {{api-domain}}/crm/bulk/v2/read/{job_id}
Request Method: GET

The response contains the status of the scheduled job as either ADDED, IN PROGRESS, or COMPLETED.
When the job is complete, the response contains the result JSON object with the keys page, count, more_records, and download_url.
You can also find the download_url in the callback response from which you can download the zip file containing the CSV or ICS file.
If the more_records key is true, there are more records you need to export. Simply change the value of the key page in the POST request, and schedule another bulk read job to fetch the next set of records.
The download_url contains the URL to download the CSV file. Follow the instructions in step-3 to download the CSV file.
Here's a sample response to the above query when the job is completed.

{
    "data": [
        {
            "id": "3652397000000646004",
            "operation": "read",
            "state": "COMPLETED",
            "result": {
                "page": 1,
                "count": 3,
                "download_url": "/crm/bulk/v2/read/3652397000000646004/result",
                "per_page": 200000,
                "more_records": false
            },
            "query": {
                "fields": [
                    "Last_Name",
                    "Owner",
                    "Owner.last_name",
                    "Account_Name.Account_Name",
                    "Account_Name.Phone",
                    "Lead_Source",
                    "Created_Time"
                ],
                "module": "Contacts",
                "criteria": {
                    "group_operator": "or",
                    "group": [
                        {
                            "api_name": "Lead_Source",
                            "comparator": "equal",
                            "value": "Advertisement"
                        },
                        {
                            "api_name": "Owner.last_name",
                            "comparator": "equal",
                            "value": "Boyle"
                        },
                        {
                            "api_name": "Account_Name.Phone",
                            "comparator": "contains",
                            "value": "99807"
                        }
                    ]
                },
                "page": 1,
                "cvid": "554023000000093005"
            },
            "created_by": {
                "id": "554023000000235011",
                "name": "Patricia Boyle"
            },
            "created_time": "2019-05-09T14:01:24+05:30"
        }
    ]
}
The other possible values for the key state are 
  • ADDED - Indicates that the job is scheduled.
  • IN PROGRESS - Indicates that the job is under processing.
Note that only a completed job will have the download URL in its response.

Callback
If you do not want to poll for the status of the job, you can wait for the system to notify you of job completion on the callback URL provided in the POST request.
  • The state indicates the successful completion ("state":"COMPLETED") or failure ("state":"FAILED") of the job.
  • The callback response will also contain the download URL if the job was completed successfully.
Below is a sample callback response for a completed job.

{
    "job_id": "554023000000568002",
    "operation": "read",
    "state": "COMPLETED",
    "query": {
        "module": "Contacts",
        "criteria": {
            "group": [
                {
                    "api_name": "Lead_Source",
                    "comparator": "equal",
                    "value": "Advertisement"
                },
                {
                    "api_name": "Owner.last_name",
                    "comparator": "equal",
                    "value": "Boyle"
                },
                {
                    "api_name": "Account_Name.Phone",
                    "comparator": "contains",
                    "value": "99807"
                }
            ],
            "group_operator": "or"
        },
        "page": 1,
        "fields": [
            "Last_Name",
            "Owner",
            "Owner.last_name",
            "Account_Name.Account_Name",
            "Account_Name.Phone",
            "Lead_Source",
            "Created_Time"
        ],
        "cvid": "554023000000093005"
    },
    "result": {
        "page": 1,
        "count": 1588,
        "download_url": "/crm/bulk/v2/read/554023000000568002/result",
        "per_page": 200000,
        "more_records": false
    }
}

For more details, refer to the Get Bulk Read Job Details page of our API guide.

This is the final step to complete exporting records from a module in Zoho CRM.
Make a GET request to the download_url you received in the response of step-2.

Step-3: Downloading the CSV file
Request URL: {{api-domain}}/crm/bulk/v2/read/{job_id}/result
Request Method: GET
This request downloads the zip file. Extract it to get the CSV or ICS file.

Limitations

  • Only 10 requests for download are allowed for a one-minute interval. Crossing the limit throws the error with the HTTP code 429. All subsequent downloads will be unsuccessful.
  • After completing the bulk read job, you can access the downloadable file only for a period of one day. After that, you cannot access the file via the endpoints.
  • You can specify a maximum of 200 select fields via an endpoint. If you specify more than that, the system exports all fields available in that module.
  • The maximum value of the page key in the export request body is 500.
  • You can specify a maximum of 25 criteria in a query. This also includes the number of criteria in a custom view or a standard view. For example, if you specify the ID of the standard view "My converted Leads", which uses two criteria, the remaining criteria that you can use in the query will be 23.
  • in and not_in comparators can accept up to 20 values. For example: 'Lead Status' - 'in' - 'Cold,Warm,Hot,Junk,Contacted,Not Contacted,....(20 values)'.
  • You cannot retrieve multi-line, multi-select lookup fields.
  • Custom views in the Activities module, Co-Owner view in the Contacts module, the standard views Shared By Me and Shared To Me are not supported in this API.

For more details, refer to the Limitations page of our API guide.

We hope you found this post useful. Let us know your thoughts in the comment section, or reach out to us at support@zohocrm.com if you have any questions.

Cheers!


    • Sticky Posts

    • Kaizen #197: Frequently Asked Questions on GraphQL APIs

      🎊 Nearing 200th Kaizen Post – We want to hear from you! 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 #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.
    • Celebrating 200 posts of Kaizen! Share your ideas for the milestone post

      Hello Developers, We launched the Kaizen series in 2019 to share helpful content to support your Zoho CRM development journey. Staying true to its spirit—Kaizen Series: Continuous Improvement for Developer Experience—we've shared everything from FAQs
    • Kaizen #193: Creating different fields in Zoho CRM through API

      🎊 Nearing 200th Kaizen Post – We want to hear from you! 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.
    • Client Script | Update - Introducing Commands in Client Script!

      Have you ever wished you could trigger Client Script from contexts other than just the supported pages and events? Have you ever wanted to leverage the advantage of Client Script at your finger tip? Discover the power of Client Script - Commands! Commands
    • Recent Topics

    • Addin Support in Zoho Sheet

      Is there any addin support available in zoho sheet as like google marketplace to enhance productivity by connecting with other apps, providing AI data analysis, streamlining business processes, and more?
    • Changing Corporate Structure - How Best to Adapt Current and Future Zoho Instances

      My current company is Company A LLC with a dba ("doing business as" - essentially an alias) Product Name B. Basically, Company A is the legal entity and Product Name B is what customers see, but it's all one business right now. We currently have a Zoho
    • how to add subform over sigma in the CRM

      my new module don't have any subform available any way to add this from sigma or from the crm
    • {"errors":[{"id":"500","title":"Servlet execution threw an exception"}]}

      Here's the call to move a file to trash. The resource_id is accurate and the file is present. header = Map(); header.put("Accept","application/vnd.api+json"); data = Map(); data_param1 = Map(); att_param1 = Map(); att_param1.put("status",51); data_param1.put("attributes",att_param1);
    • How to Install Zoho Workdrive Desktop Sync for Ubuntu?

      Hi. I am newbie to Linux / Ubuntu. I downloaded a tar.gz file from Workdrive for installing the Workdrive Desktop Sync tool. Can someone give me step by step guide on how to install this on Ubuntu? I am using Ubuntu 19.04. Regards Senthil
    • Integración Books para cumplir la ley Crea y Crece y Ley Antifraude (VeriFactu)

      Hola: En principio, en julio de 2025, entra en vigor la ley Crea y Crece y Ley Antifraude (VeriFactu). ¿Sabéis si Zoho va a cumplir con la ley para cumplir con la facturación electrónica conectada a Hacienda? Gracias
    • How to upload own video?

      How can you upload your own video on your zoho website? I do not want to use another host, but i want to insert my own files. how can i do this?
    • Support new line in CRM Multiline text field display in Zoho Deluge

      Hi brainstrust, We have a Zoho CRM field which is a Muti Line (Small) field. It has data in it that has a carriage return after each line: When I pull that data in via Deluge, it displays as: I'm hoping a way I can change it from: Freehand : ENABLED Chenille
    • A couple of minor enhancements to Workflows

      Last updated on September 17, 2024: These enhancements were initially available for early access, and we've now enabled them for all users. We are elated to announce a couple of enhancements to custom functions in our Workflows! Say hello to: "Source"
    • Announcing new features in Trident for Windows (v.1.32.5.0)

      Hello Community! Trident for Windows just got better! This update includes new features designed to improve and simplify email and calendar management—and it includes a feature you’ve been waiting for. Let’s dive into what’s new! Save emails in EML or
    • How to render either thumbnail_url or preview_url or preview_data_url

      I get 401 Unauthorised when using these urls in the <img> tag src attribute. Guide me on how to use them!
    • Zoho CRM Calendar | Custom Buttons

      I'm working with my sales team to make our scheduling process easier for our team. We primary rely on Zoho CRM calendar to organize our events for our sales team. I was wondering if there is a way to add custom button in the Calendar view on events/meeting
    • Option to Empty Entire Mailbox or Folder in Zoho Mail

      Hello Zoho Mail Team, How are you? We would like to request an enhancement to Zoho Mail that would allow administrators and users to quickly clear out entire folders or mailboxes, including shared mailboxes. Current Limitation: At present, Zoho Mail only
    • Default Sorting on Related Lists

      Is it possible to set the default sorting options on the related lists. For example on the Contact Details view I have related lists for activities, emails, products cases, notes etc... currently: Activities 'created date' newest first Emails - 'created
    • Directly Edit, Filter, and Sort Subforms on the Details Page

      Hello everyone, As you know, subforms allow you to associate multiple line items with a single record, greatly enhancing your data organization. For example, a sales order subform neatly lists all products, their quantities, amounts, and other relevant
    • Create custom rollup summary fields in Zoho CRM

      Hello everyone, In Zoho CRM, rollup summary fields have been essential tools for summarizing data across related records and enabling users to gain quick insights without having to jump across modules. Previously, only predefined summary functions were
    • Create static subforms in Zoho CRM: streamline data entry with pre-defined values

      Last modified on (9 July, 2025): This feature was available in early access and is currently being rolled out to customers in phases. Currently available for users in the the AU, CA, and SA DCs. It will be enabled for the remaining DCs in the next couple
    • Create Lead Button in Zoho CRM Dashboard

      Right now to create Leads in the CRM our team is going into the Lead module, selecting the "Create Lead" button, then building out the lead. Is there anyway to add the "Create Lead" button or some sort of short cut to the Zoho CRM Dashboard to cut out
    • Searching customer field

      Hello, When entering a receipt, we select customer information. The customer information is synced with Zoho CRM. However, we can't find the customer information because it searches for words that begin with the entered value. It needs to search for words
    • 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,
    • stock

      bom/bse : stock details or price =STOCK(C14;"price") not showing issue is #N/A! kindly resolve this problem
    • Rotate an Image in Workdrive Image Editor

      I don't know if I'm just missing something, but my team needs a way to rotate images in Workdrive and save them at that new orientation. For example one of our ground crew members will take photos of job sites vertically (9:16) on his phone and upload
    • Improved RingCentral Integration

      We’d like to request an enhancement to the current RingCentral integration with Zoho. RingCentral now automatically generates call transcripts and AI-based call summaries (AI Notes) for each call, which are extremely helpful for support and sales teams.
    • Resume Harvester: New Enhancements for Faster Sourcing

      We’re excited to share a set of enhancements to Resume Harvester that make sourcing faster and more flexible. These updates help you cut down on repetitive steps, manage auto searches more efficiently, and review candidate profiles with ease. Why we built
    • Using Zoho Flow to create sales orders from won deal in Zoho CRM

      Hi there, We are using Zoho Flow to create sales orders automatically when a deal is won in Zoho CRM. However, the sales order requires "Product Details" to be passed in "jsonobject", and is resulting in this error: Zoho CRM says "Invalid input for invalid
    • WIDGET in related record list ZOHO CRM; how to get and put data to subform custom fields?

      he need: Read and write two custom subform line-item fields on Quotes: Segment_wyceny (picklist/text) and W_pakiecie (number). Write works; read does not return these fields via SDK. Environment Zoho CRM Widget Zoho Embedded App SDK v1.2 Module: Quotes
    • 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
    • Zoho CRM Tracking Google Enhanced Conversions

      Can anyone @Zoho, consultants, or users help me understand if Zoho CRM is going to support Google's Enhanced Conversions? I included some information from Google below about it. We use Google Adwords for our pay per click advertising for lead generation,
    • zoho click, and nord VPN

      Unfortunately, we've been having problems with Zoho Click, where essentially the line cuts off after about a minute's worth of conversation every time we are on VPN. Is there a way we can change this within the settings so it does not cut the line off
    • Recurring Supervisor Rule Reminders for Open/In-Progress Tickets

      Hello Zoho Support Team, I would like to suggest a potential improvement regarding reminders for tickets and activities in Zoho Desk. Currently, it is possible to set reminders only once. In the Supervisor Rules section, it is possible to configure reminders
    • Connecting Portals from different Zoho apps

      Hi, I note that Zoho has functionality for customer portals for several of the Zoho apps, like CRM, Projects, Desk etc. Is there any way to connect these portals?  It would be great if we could give our customers access to a portal in which they could
    • Billing Management: #5 Usage Billing

      After understanding the nuances of Advance Billing and Retainers, we will explore one of the booming billing models. Long ago, villagers drew water from a shared well in a small village. The well was a lifeline for the entire community. Ravi, the well
    • Function #10: Update item prices automatically based on the last transaction created

      In businesses, item prices are not always fixed and can fluctuate due to various factors. If you find yourself manually adjusting the item rates every time they change, we have the ideal time-saving solution for you. In today's post, we bring you custom
    • Inventory Adjustments

      Hi, How to transfer the material from one head to another ? Like materials purchased for manufacturing the laptop need to transfer from consumption inventory (Quantity of raw materials reduced) to destination inventory ( Quantity of Laptop increased)
    • Zoho CRM Community Digest - Aug 2025 | Part 1

      Hey everyone! The first half of August went by, and we have a few announcements and some good noteworthy discussions. So, let's take a look at them! Product Updates: Introducing Connected Records feature: Zoho CRM’s Next-Gen UI now includes Connected
    • Problems with email templates (HTML - Outlook)

      Hi there, I've been trying to create a newsletter from the template "Business 4". Everything looks great in the preview, but when I send it to my Outlook inbox, the layout doesn't seems to stick. More particularly: - The line-height is way more reduced, even though I used the line-height tool from the template - Columns but they are sometimes misaligned - Font size is not always the one I've selected. Could you help? Thanks!
    • Please make it easier to Pause syncing

      right now it takes 3 clicks to get there. sounds silly, but can you make it just 2 clicks to get it done instead? thats how dropbox does it, 2 clicks to pause instead of 3.
    • How to create a Zoho CRM report with 2 child modules

      Hi all, Is it possible to create a Zoho CRM report or chart with 2 child modules? After I add the first child module, the + button only adds another parent module. It won't let me add multiple child modules at once. We don't have Zoho Analytics and would
    • SalesIQとPageSenseの利用について

      初めての投稿で場違いだったらすいません。 弊社ではSalesIQを運用しているのですが、追加でPageSenseの導入もしたいと現場からの声があります。 両サービスともクッキー同意バナーが必要なサービスなのですが 弊社では同意無しに情報はとりませんという方針なので 2つ入れると2つバナーを出す必要がでてきます・・・ 両サービスを運用されてる方があれば運用状況とか教えてほしいです。 PageSenseについては詳細まで機能を理解してないなかでの質問です。
    • How to integrate Zoho Forms with Zoho CRM on Standard Plan

      Hello Zoho Support Team, I am using the Standard Zoho Forms plan (USD 30/user) and I would like to integrate Zoho Forms with Zoho CRM so that certain fields in my forms can be automatically prefilled using data from Deals in CRM. Specifically, I want
    • Next Page