COQL API in Zoho CRM - Part I

COQL API in Zoho CRM - Part I

Hi everyone! Welcome back to another week of Kaizen

This week, we will discuss the COQL Queries in detail.

COQL (CRM Object Query Language) is a powerful query language based on SQL syntax that allows users to write their own queries and fetch records using module API names and field API names. In this post, we will discuss the operators supported by COQL in detail and also provide examples to help you understand better.  Please note that the information in the article holds true for version 4 of Zoho CRM APIs.

When should you use the Query API?

Use Query API when you want to query for a module's data and/or it's look up related data using various comparators, or for records that fall into a custom view without actually creating one. For example, if you want to query for all products in a specific price range, with a 5 star rating and sort the results by price, use the Query API. Similarly you can use Query API to query for records from cross-modules (linked via lookup field), such as filtering products based on the vendor's details. 

What types of queries are supported by COQL?

COQL supports only the SELECT query, which is used to select data from the CRM, based on the conditions specified by the clauses. 

Here is a sample query:
SELECT {field_api_names} FROM {module_api_name} WHERE {field_api_name} {comparator} {logical_operator} {value} ORDER BY {field_api_name} ASC/DESC LIMIT {limit} OFFSET {offset}

What are the clauses & aggregate functions supported by COQL?

WHERE - used to select records based on specific conditions.
FROM - specifies the module from which to fetch the records.
ORDER BY - used to sort the results in ascending or descending order.
LIMIT - used to limit the number of records returned by the query.
OFFSET - used to skip a specified number of records while retrieving the records.


{
 "select_query" : "select Last_Name, First_Name, Mobile, Final_Score from Leads where (Lead_Status = 'Not Contacted') ORDER BY Final_Score DESC LIMIT 5 OFFSET 10"
}


For example, the above query retrieves the Last_Name, First_Name, Mobile and Final_score of all Leads whose status equals 'Not Contacted'. The results will be sorted in descending order based on the Final_Score field, and only the 5 records after skipping the first 10 will be returned.

NOTE : You can also use the syntax "LIMIT offset, limit" to achieve the same result. For example :


{
 "select_query" : "select Last_Name, First_Name, Mobile, Final_Score from Leads where (Lead_Status = 'Not Contacted') ORDER BY Final_Score DESC LIMIT 5, 10"
}


Aggregate functions can perform calculations on a set of values and return a single value. 
SUM() - to get the sum of the values of an aggregate field in a module.
MAX() - to get the maximum value of an aggregate field.
MIN() - to get the minimum value of an aggregate field.
AVG() - to get the average value of the values of a field.
COUNT() - to get the number of records that satisfy the criteria.

Wildcard Character Support in COQL

In COQL queries, the only supported wildcard character is %. This % wildcard can be used with the like operator to achieve functionality similar to the contains, starts_with and ends_with operators. For instance, '%tech" queries for field values ending with tech, 'C%' queries for the values starting with C, and '%tech%' translates to contains 'tech'.

Supported field types and Comparators

The following table gives a gist of the field types whose data you can query for, and the comparators for each field type.
Field TypeComparators
Text and Picklist=, !=, like, not like, in, not in, is null, is not null
Lookup=, !=, in, not in, is null, is not null
Date, DateTime, Number, Currency=, !=, >=, >, <=, <, between, not between, in, not in, is null, is not null
Boolean=

Supported field types and Comparators

1) Text and Picklist Fields

Supported comparators : =, !=, like, not like, in, not in, is null, is not null. Please note that the like operator is used for starts_with, ends_with, contains, and not like operator is used for not contains

Sample Query 1: (=, like, in)

{
    "select_query": "SELECT First_Name, Last_Name FROM Leads WHERE (((Lead_Status = 'Pre-Qualified') and (Company like '%zylker%')) and Industry in ('Technology', 'ERP'))"
}

This SELECT query retrieves the First_Name and Last_Name of all Leads whose Lead_Status is Pre-QualifiedCompany contains zylker, and Industry is either Technology or ERP

Sample Query 2:(not in, like, not null)

{
"select_query": "SELECT First_Name, Last_Name FROM Leads WHERE (((Lead_Status not in ('Closed-Won', 'Closed-Lost')) and (Lead_Source like '%Web%')) and (Skype_ID is not null)) LIMIT 2"
}

This query will return the first name and last name of all leads whose lead status is not Closed-Won or Closed-Lost, whose Lead Source fields contains web, and whose Skype ID field is not empty.

Sample Query 3:( !=, not like, null)

{
    "select_query": "SELECT First_Name, Last_Name, Mobile FROM Leads WHERE (((Lead_Source != 'Webinar') and (City not like '%New York%')) and (Skype_ID is null))"
}

This query retrieves the first name, last name and mobile of leads where the lead source is not a webinar, the city is not New York, and the Skype ID field is empty or null.

2. Lookup Fields

=, !=, in, not in, is null, is not null are the supported comparators for lookup fields. If you want to get the name of the lookup field in the response, you must include the field API name in the query. Otherwise, the system will return only the ID of the field.

Sample Query 1: (=, not in, !=)

{
 "select_query": "select Last_Name, First_Name, Full_Name, Account_Name, Owner from Contacts where (((Account_Name.Account_Name != 'Zylker') and (Owner = 4876876000000327001)) and Vendor_Name.Vendor_Name not in ('Skytech','SR')) LIMIT 2"
}

This query retrieves the last name, first name, full name, account name, and owner of two contacts whose account name is not Zylker, whose owner ID is 4876876000000327001, and whose vendor name does not contain Skytech or SR.
Sample Response:
{
    "data": [
        {
            "First_Name": "John",
            "Full_Name": "John Wilson  ",
            "Owner": {
                "id": "4876876000000327001"
            },
            "Last_Name": "Wilson  ",
            "Account_Name": {
                "id": "4876876000000333089"
            },
            "id": "4876876000000333182"
        },
        {
            "First_Name": "Josephine",
            "Full_Name": "Josephine Darakjy",
            "Owner": {
                "id": "4876876000000327001"
            },
            "Last_Name": "Darakjy",
            "Account_Name": {
                "id": "4876876000000333090"
            },
            "id": "4876876000000333183"
        }
    ],
    "info": {
        "count": 2,
        "more_records": true
    }
}

In this query, the id of the account is returned but not the name since we have not specified the field API name in the query. To fetch the field name, specify the field API name in the query. Refer to the following sample query to know how.

Sample Query 2:  (in, is null, is not null)

{
    "select_query": "SELECT Deal_Name, Account_Name.Account_Name, Created_Time FROM Deals WHERE (((Account_Name.Account_Name in ('Grayson','Zylker')) and (Owner is not null)) and (Contact_Name is null)) ORDER BY Created_Time DESC LIMIT 2"
}

This query retrieves the Deal Name, Account Name, and Created Time of the 2 most recently created Deals whose Account Name contains Zylker or Grayson, and do not have a Contact Name associated with them but have a Deal Owner associated with them. The results will be ordered in descending order by the Created Time.
 
Sample Response:
{
    "data": [
        {
            "Deal_Name": "Westborne Deal",
            "Created_Time": "2023-04-06T10:04:02+05:30",
            "Account_Name.Account_Name": "Grayson",
            "id": "4876876000003548001"
        },
        {
            "Deal_Name": "Eastwing Deal",
            "Created_Time": "2023-04-05T19:10:55+05:30",
            "Account_Name.Account_Name": "Grayson",
            "id": "4876876000003526011"
        }
    ],
    "info": {
        "count": 2,
        "more_records": true
    }
}

In the same query, if you want to use the Account ID instead of the name, replace ((Account_Name.Account_Name in ('Grayson','Zylker')) with ((Account_Name in (4876876000001236083, 4876876000002799001)) to include the IDs instead of the field API names and the account names.
{
    "select_query": "SELECT Deal_Name, Account_Name.Account_Name, Created_Time FROM Deals WHERE (((Account_Name in (4876876000001236083, 4876876000002799001)) and (Owner is not null)) and (Contact_Name is null)) ORDER BY Created_Time DESC LIMIT 2"
}

3. Date, DateTime, Number, Currency Fields

=, !=, >=, >, <=, <, between, not between, in, not in, is null, is not null are the supported comparators for these fields.

Sample Query 1: (between, <, >)

{

    "select_query": "SELECT Deal_Name, Amount, Stage, Probability FROM Deals WHERE (((Closing_Date between '2023-01-01' and '2023-03-31') and (Probability < 99)) and (Amount > 10000))"

}

This query retrieves the deal name, amount, stage, and probability of all deals whose closing date is between January 1, 2023 and March 31, 2023, and whose probability is less than 99 and amount is greater than 10000.

Sample Response:
{
    "data": [
        {
            "Deal_Name": "Chapman Deal",
            "Amount": 2500000,
            "Probability": 97,
            "Stage": "Closed Won",
            "id": "4876876000003550011"
        }
    ],
    "info": {
        "count": 1,
        "more_records": false
    }
}

Sample Query 2: (<=, !=, >=)

{
    "select_query": "SELECT Product_Name, Qty_in_Stock, Vendor_Name, Cost_Price FROM Products WHERE (((Sales_End_Date <= '2023-04-30') and (Qty_in_Stock != 0)) and (Cost_Price >= 500))"
}

This query retrieves the product name, quantity in stock, vendor name, and cost price for all products whose sales end date is on or before April 30, 2023, whose quantity in stock is not zero, and whose cost price is greater than or equal to 500. Since Vendor_Name is a lookup field, only the ID will be returned in the response.
Sample Response
{
    "data": [
        {
            "Cost_Price": 2000,
            "Vendor_Name": {
                "id": "4876876000001039017"
            },
            "Product_Name": "Sigma",
            "Qty_in_Stock": 30,
            "id": "4876876000001036109"
        }
    ],
    "info": {
        "count": 1,
        "more_records": false
    }
}

Sample Query 3: (not between, is not, >)

{
    "select_query": "SELECT Last_Name, First_Name, Referred_By.Full_Name FROM Leads WHERE (((Final_Score not between 10 and 20) and (Annual_Revenue is not null)) and (No_of_Employees > 200)) LIMIT 1"
}

This COQL query selects the last name, first name, and the full name of the lead's referred by field, for one lead whose final score is not between 10 and 20annual revenue is not null and whose number of employees is greater than 200
Sample Response
{
    "data": [
        {
            "First_Name": "Chau",
            "Last_Name": "Kitzman",
            "id": "4876876000000333403",
            "Referred_By.Full_Name": "Simmons Truhlar"
        }
    ],
    "info": {
        "count": 1,
        "more_records": true
    }
}

Sample Query 4: (>, not in, =, is null)

{
   "select_query":"SELECT PO_Number, PO_Date, Status, Discount FROM Purchase_Orders WHERE (((PO_Date = '2023-04-06') and (Due_Date not in ('2023-04-10','2023-04-11', '2023-04-12'))) or ((Discount > 10) and (Requisition_No is null)))"
}

This query selects the PO_Number, PO_Date, Status, and Discount from the Purchase_Orders module where the PO_Date is equal to '2023-04-06' and Due_Date is not any of '2023-04-10', '2023-04-11', or '2023-04-12'; OR Discount is greater than 10 and Requisition_No is null. In this query, we have used both AND and OR operators to combine the clauses.
Sample Response
{
    "data": [
        {
            "Status": "Created",
            "PO_Date": "2022-05-10",
            "Discount": 9990,
            "PO_Number": "PO-JL-3876",
            "id": "4876876000001125176"
        },
        {
            "Status": "Created",
            "PO_Date": "2023-04-06",
            "Discount": 370.37,
            "PO_Number": "PO-DA-1932",
            "id": "4876876000003561019"
        }
    ],
    "info": {
        "count": 2,
        "more_records": false
    }
}

We hope you found this post useful and that it has given you a better understanding of COQL queries. In our next post, we will discuss the rest of the field types, aggregate functions with more examples, and provide more queries to help you get started.

If you have any questions or feedback, please let us know in the comments below, or write to us at support@zohocrm.com. We would love to hear from you! 

Additionally, if you have any questions about the COQL API or how to construct a query, kindly let us know in the comments.

Additional Reading:


    • Recent Topics

    • Import from GoHighLevel to Zoho CRM

      Has anyone been successful with this? I don't want to integrate with GoHighLevel just import/migrate everything over to Zoho
    • booking link that expires

      I have a suggestion that is  crucial. When i send booking URL to clients they keep the link and they book appointment whenever they want multiple times. You should give us the Booking URL feature. We should be able to send it and the user can use it only
    • Accessing Subform Data using getRecordByID

      I am getting data from Zoho Creator using deluge zoho.creator.getRecordByID task, from another application. The report contains a subform, and that subform is in the detail view of the report. I do not appear to have any subform data in the JSON response,
    • Track Contact's Employment/Account History

      Thank you in advance for all of your help! Is there a way, within Zoho, to keep track of a contact's employment history? For example, if John Doe is my contact at Account 1, but leaves the company and is hired by Account 2, can I... ...maintain John Doe as a former employee under Account 1, while simultaneously listing him as a current employee of Account 2? ...view John Doe's employment history on his contact page in addition to the account he is currently associated with? I'm sure there is a way
    • Pre-fill TO and CC fields for Email Templates

      This would be a game changer to be able to set either specific email addresses or merge fields based on deal role titles into email templates. Please pass this along to *hopefully* add to future features of Zoho CRM.
    • Leads and Deals Issue

      Hi! Is Zoho having trouble today? I've been experiencing issues today. When I move a deal to closed/won, it previously would require a closing date but today the screen just went blur and the closing date did not pop up. And then under leads, I was trying
    • QR codes in templates

      I'm excited about the new QR code generator. I have included a QR code that contains the record ID setting "${ID}" as input data. In the report detail it works perfectly but when printing it in a template the code is not shown.
    • How do I hide all leads from Standard users in my CRM ZOHO

      I want to configure my crm zoho in such a way that standard users will only see leads owned or assigned to them. How do I go about doing this? I have tried all i could, but nothing...can anyone help me?
    • Custom view for Milestones

      Hi, Just an idea for the future... would it be possible to create custom views for the Milestones view under Work Overview ? I usually need to look at this view filtered by project group but the filter doesn't remain when navigating away. A custom view
    • How to Implement Time-Based Filters in Zoho Workflows?

      Hi everyone, I’m looking for a workaround to implement time-based filters in Zoho workflows. Specifically, I need a workflow to trigger only within certain hours (e.g., between 10:00 AM and 8:00 PM, Sunday to Friday). Currently, Zoho workflows execute
    • is there a better way to routinely export my project timesheets?

      Hi there, I am somewhat happy with how Zoho books handles time.  One thing that is missing is more user driven control over my data.  I have a workflow where I constantly need to give customers feeds of work done.  So I pick a project, and would ideally
    • Portal Default View

      Hello! My company is about roll out portals for some users, but we were wondering if it was possible to set the Record Detail Page View to default to a custom view that we made. That way the information they need would be streamlined and easier to see.
    • Unlocking New Horizons: A Year in Review

      As we bid farewell to 2024, let's celebrate and revisit the key highlights of the year. From adding a new edition to cross-platform enhancements, here’s a roundup of all the feature updates designed to simplify accounting, optimize financial management,
    • Does zoho rest api support token exchange from microsoft entra id token

      i want to get access token from the Microsoft user token in rest api. so it is possible to exchange microsoft user access token to zoho's access token or auth token ( token should be user specific not super admin).
    • Important: DKIM verification needed for unauthenticated email domains

      Hi all, This post is to inform users who are currently using unauthenticated email domains as their sender email for their notifications. We have mandated DKIM verification for all domains used as sender email addresses for the outgoing emails by 01-Jan-2025.
    • How do I define a weekend

      I noticed the default for weekends does not seem to include Saturdays. How can i define weekends to include both Saturdays and Sundays? Thank you.
    • Assistance Required: Custom Model Record Not Visible in Zoho CRM Sandbox

      Dear Team, I hope this message finds you well. I have created a custom model in the Zoho CRM Sandbox account and am currently adding records to it using Python. While I am able to fetch the module data programmatically through Python, I am unable to see
    • Zoho Sign Product updates - H2 2024

      Hello! We have almost come to the end of 2024! Here's a list of features and enhancements that went live in the later half of the year. NOM 151 certification Witness signing Formula, conditional, and custom fields Zoho Sign's extension for Bigin by Zoho
    • Custom Status for Purchase Orders

      Currently Zoho books has functionality to create custom statuses for Sales Orders. Can this be extended to include custom status for purchase orders as well? It was a great decision to add this functionality to sales orders. Our use case is for tracking
    • Remove Address from credit card payment

      I would like to remove the need to add address when paying by credit card. I only want the customer to have to add their credit card details.
    • Top Menu Disappeared from Blog Page

      Hi, Our top menu disappeared at Blog Posts page. However, it's still visible any other page on the website. I attached two screenshots, so it can be understood clearly. How can we bring back top menu? Thanks, K.
    • Subforms and automation

      If a user updates a field how do we create an automation etc. We have a field for returned parts and i want to get an email when that field is ticked. How please as Zoho tells me no automation on subforms. The Reason- Why having waited for ever for FSM
    • My Zoho mail has been blocked for suspicious activity. cannot unblock it! need urgent help!

      Hi, I was accessing my email on an airplane which for some reason resulted in my mail being blocked. I have managed to unblock my incoming however outgoing is still blocked. I have contacted all your support emails but it still says contact support when I try to unblock outgoing emails. Its now been over 8 days with the same issue which is really serious as I'm not able to send several business emails during this period. I have followed all your steps to unblock this and contacted your support 5
    • Copy Widget to another Dashboard

      I can see the option to clone a widget to the same dashboard but is it possible to copy it to another dashboard?
    • Error while importing products Purchase Price: Value in the field does not match with the data type supported by us.

      I am trying to import items into zoho inventory using an excel spreadsheet. I keep getting this error Purchase Price: Value in the field does not match with the data type supported by us. no matter how i format the cells this comes up and will not import
    • Quotes Module - import data

      Hello Zoho, is it possible to import Quotes records? I was trying and i have no results. Raport shows no data imported. Could you help me please how to do it?
    • Year-End Wrap: Disconnect now; Reconnect later with Offline Mode

      🎄Happy Holidays🎄 Let's say you are travelling home to spend the holiday season with your loved ones. Before you even board the train, you check your phone only to find your inbox rapidly filling with urgent emails that need your attention. There’s no
    • Exploring SalesIQ's Top Features of 2024: An Insider's Look 🔍

      As we wrap up another year at Zoho SalesIQ, it's time to reflect on how far we've come. This year has been incredible for us in our journey to build a more powerful, flexible, and customer-centric engagement platform. We've introduced several features
    • Resource booking functionality questions

      I'm exploring the resource booking functionality in Zoho Bookings for my organisation's needs. I have a few questions about the available Zoho Bookings functionalities. Is it possible to force all users to sign up for an account before they book a resource?
    • How to create a Field with answers as Yes, No> Further if no is selected a new field to be visible to give details

      Dear All, I am creating a feedback form in HR Letter. The question is were you satisfied with the work allotted. Expected answer to this is Yes, No. Further if the response is no, then a field to be give to fill more details as to why no was selected.
    • Modify the way a phone number is shown in footer on ZOHO Booking Page

      The default display of the phone number field in the footer is not customer friendly - See image below. We would like it to use the accepted standards of phone number display: +61 (0)2 88545440, or allow us to choose. At the moment ZOHO Booking sets how
    • Zoho Bookings Multilingual ?

      Hello, Not sure if there is a way to do it currently, but it would be very helpful if Zoho bookings allowed multilingual translations so we could have our booking pages and notifications setup in multiple languages. Thanks,
    • Allow customers to choose meeting venue and meeting duration on booking page

      My business primarily involves one-to-one meetings with my clients. Given the hybrid-work world we now find ourselves in, these meetings can take several forms (which I think of as the meeting "venue"): In-person Zoom Phone call I currently handle these
    • Problem viewing document imported from google drive.

      Hello, When I add a document via my google drive, it is impossible to preview it. I get the error “Files without extensions cannot be previewed. Download to view this file”. Could you please help me? Also, and this is more of a question: is there a way
    • Two way sync Zoho Mail and Bookings

      Hi, I know it’s possible to view Bookings appointments in Zoho Mail, but is there a way to see my Zoho Mail meetings in the Bookings calendar?
    • 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
    • Sending my emails to Spam Folder

      I am loosing my business because of this issue, many of my customers are receiving their email in the spam sometimes no one checks them
    • Why can't I sync my Zoho Mail tasks and notes with my mobile device, and is there a way to fix this issue?

      I'm having trouble syncing my Zoho Mail tasks and notes with my mobile device. Despite following the usual steps, the tasks and notes don't appear on my phone. Is there a way to fix this issue? Regards, Adamjes, Tekskills India Pvt Limited, India.
    • Re: constant rejected email form and to my account

      Hi, have had several rejection when I sent an email to Zoho account as well as other people have sent emails to my as your health Centre they have account and all aspects have been ejected. i wonder why the email are rejecting to and from. If you see
    • How do I redeem credits?

      How do I redeem credits that are shown in billing section?
    • Next Page