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

    • Creator Simplified #11: Create a custom button to download files

      Hey there! This time, let's see how to create custom buttons to download the files uploaded in the file upload field. Sample use-case A training app has a module that provides the materials for all the available courses. Students can click on the corresponding
    • Zoho vault uses only password to unlock not a TouchID

      TouchID works when normally openning app but when called from keyboard while browsing or trying to log to another app it shows only password option to unlock. This behaviour is only on iPad Mini witch latest 18.2OS
    • Batch Tracking Enhancements In Zoho Inventory

      Hello users, We’re excited to announce that we’ve taken batch tracking to a whole new level in Zoho Inventory! We’ve made it more accessible and easier to use than ever. Here’s a quick look at the improvements: 1) A New Way To Create or Modify Batches
    • Zoho Desk Mobile App Year-End Roundup - 2024

      Hello Everyone, Greetings! As you gear up for the festive season, we are excited to share a quick journey into all that is released in 2024! Availability of each feature in iOS and Android released in 2024 are as follows: For more information on the above
    • Task Completion vs Estimated Time

      I need to represent the Estimated Date vs Actual Completion Date for multiple Tasks. How Can I Do this in Zoho Analytics.
    • Upload Field - cannot be checked in rules configuration.

      We wanted to create a process to verify whether the upload fields are empty or not. If empty, then it should deny during submission. We don't want to use the mandatory field setting because in a 10 pager form, some upload field located in page 1 will
    • Is it possible to hide Developer Space for all user in Zoho Projects

      Hello! I am Zoho admin in a company and we want to use Zoho Project to manage projects, but after a few days of testing we are not able to "hide" the Developer Space from all kind of users except the admin. To sum up, I want to hide this for all users.
    • Chat function not working properly

      Ever since upgrading to plus, the chat is all messed up. it is coming up behind the web page so that I cannot see what I'm typing and cannot read replies. I can only see the bottom of the text box at the bottom of the page, and then it is blocked. I've
    • Wrong Time on Exported Records

      Hello, All records in my exported Notes .csv file have the incorrect time for Created Time. They are all 8 hours ahead. I've already verified that my time zone is correct in both Personal Settings and Company Settings. Is there any way to fix this?
    • Sync workspace - table

      I have connected two workspaces and I have imported two different query tables from one workspace to the other one, that was a succes. But now I want to import another query table from the same workspace to the other but I get an error. Why is that? (there
    • Subir o Preço Unitário já acrescido de um valor

      To com um desafio grande, e se alguém conseguir me ajudar, seria ótimo! O que eu preciso é que o na hora de adicionar um item no subformulário dos itens cotados do módulo Orçamentos, o preço de lista do item venha acrescido de 20% automaticamente e de
    • Ring in the New Year with Guided Conversations for Smooth Offline Support

      As we step into the new year, it’s time to refocus, re-energize, and gear up for fresh opportunities. But what about your customers as they begin the year with their own set of challenges or queries to resolve? With Zoho Desk’s Guided Conversations (GC),
    • 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
    • updateTask Zoho Connect API

      When I do POST request by https://connect.zoho.com/pulse/api/updateTask with parameters scopeID, taskId, title, status and with header Zoho-oauthtoken, I got next response: {'updateTask': {'reason': 'You are not authorized to do this action.', 'result':
    • Alert for Back Navigation in Zoho Creator Widgets on Mobile Apps

      In Zoho Creator widgets, when a user navigates back on mobile devices, the data within the widget is reset. This leads to a loss of any unsaved changes or inputs, causing frustration for users. To enhance user experience, we need to implement a confirmation
    • Can Creator integrate with a CRM Sandbox

      zoho & Creator Noob -  I would like to build a Creator App and integrate it to the CRM Sandbox.  Then, when I have the bugs worked out integrate it to the production CRM account.  Can Creator do this ?  I built a test Creator App and integrated it to the CRM in a test zoho account fairly easily.  
    • Allow Multiple Scheduled Appointments with Zoho Support

      Dear Zoho Team, I hope you're doing well. First, thank you for introducing the option to schedule support calls via the Zoho CRM booking link. This has been a fantastic enhancement, eliminating the need for back-and-forth coordination when scheduling
    • Zia Call Intelligence only up 10 License

      I have been trying to install Call Intelligence for two days now, but strangely, the button is missing at this point. The documentation could be better, but most importantly, someone should inform small businesses like us that they don’t even bother enabling
    • Accrue Leave by Hours Worked?

      My locality (Michigan, US) has enacted a law that requires that 1 hour of sick leave be accrued for every 30 hours worked. I cannot see how to implement this policy in Zoho People. There does not appear to be a mechanism for accruing leave proportional
    • Fixed assets recording

      Hello there, I recorded a bill for a vendor contain (Computer) so the PC is a fixed assets, do I need to do a manual journal to include this PC under the fixed assets category (furniture & equipment)? If yes, please take me through the manual journal
    • error in importing customers

      get this error message while importing customers, there is no column for COUNTRY CODE in sample excel file
    • Workflow Based on Manual Journal

      Manual journal entries are one of the few areas that cannot kick off a workflow automation in Zoho Books currently. I would propose considering adding that. My use case is that the payroll provider I use (a flavor of SurePayroll) has a Zoho Books automation
    • Digest Décembre - Un résumé de ce qui s'est passé le mois dernier sur Community

      Bonjour chers utilisateurs, Toute l'équipe Zoho france vous souhaite une année remplie de joie, de réussite et de prospérité. Alors que nous débutons cette nouvelle année avec des projets innovants, des astuces, des produits et bien d'autres choses encore,
    • New Year Wishes to the Zoho Finance Developer Community!

      Hello developers, Happy New Year! As we step into 2025, we wish you a journey filled with growth, success, and exciting opportunities ahead. We’re thrilled to announce that we have something exciting in store for you. Welcome to the Zoho Finance Developer
    • Button Display Conditions

      Hi Guys, Is it at all possible to have extra button conditions? Context: We have data in our deals module which has a custom button which converts the deal into contacts + set up relationships between them. At the end of the conversion we set a field
    • Ayuda con zoho creator x zoho Crm

      Hola a todos, Estoy teniendo dificultades al sincronizar datos entre Zoho Creator y Zoho CRM. Mi objetivo es lo siguiente: Busque un registro en el módulo Contactsde Zoho CRM utilizando el correo electrónico del registro de Zoho Creator. Si se encuentra
    • How to Replace an Assessment in a Job Opening on Zoho Recruit

      Hi everyone, I’m currently using Zoho Recruit and would like to replace the assessment linked to a specific job opening. I want to remove the existing assessment and add a new one. What is the best way to do this without losing any important data or affecting
    • Fixed asset management

      I want to know if there is any individual module for fixed assets management
    • Input GST Reversal for damaged goods

      In our line of business, some items are damaged and we are doing inventory adjustments to remove them from stock. However, as per GST guidelines, there is a specific rule that we have to reverse Input GST availed for such items and needs to be reported
    • Introducing Record Summary: smarter insights at your fingertips

      Hello everyone, Building on the recent launch of Zoho's in-house Zia Large Language Model (Zia LLM)—a major milestone in Zoho CRM’s AI capabilities—we’re excited to introduce the Record Summary feature. This powerful addition makes use of Zia LLM to simplify
    • No longer get Cliq notifications on phone if app not started

      On Android, I used to get notifications on my phone whether I was in the app, or it was started. Then about a month ago, I stopped seeing notifications on my phone UNLESS I had already started the app. So if I reboot my phone, and never start the app,
    • Error AS101 when adding new email alias

      Hi, I am trying to add apple@(mydomain).com The error AS101 is shown while I try to add the alias.
    • Deluge script to add Mail Task

      Has anyone out there created a custom function to create a Zoho Mail task? I'd be interested in hearing how you accomplished it. Sample code is appreciated!
    • Tags with Zapier

      Maybe I'm missing something....I hope so... Using tags for triggers is a key need.  This prevents us from having a ton of different lists. I am trying to find out how to add a tag using zapier when someone makes a purchase....but it doesn't seem to be
    • Send Supervisor Rule Emails Within Ticket Context in Zoho Desk

      Dear Zoho Desk Team, I hope this message finds you well. Currently, emails sent via Supervisor Rules in Zoho Desk are sent outside of the ticket context. As a result, if a client replies to such emails, their response creates a new ticket instead of appending
    • How to apply blueprint on tickets that created from IM module

      Hello, I have an issue applying blueprint on tickets that created from WhatsApp conversation, the tickets matches with the blueprint criteria but still we are not able to put these tickets into the blueprint. I've tried with deferent type of tickets and
    • Function #4: Schedule Customer Statements

      Regularly sending statements to customers is an imperative part of many business processes as it helps foster strong customer relationships and provides timely guidance on payments. While you can generate the statement of accounts and have it sent over
    • Zoho Mail POP & IMAP Server Details

      Hello all! We have been receiving a number of requests regarding the errors while configuring or using Zoho Mail account in POP/ IMAP clients. The server details vary based on your account type and the Datacenter in which your account is setup. Ensure
    • Remove 30-Day Client Reply Restriction on Supervisor Rules in Zoho Desk

      Dear Zoho Desk Team, I hope you're doing well. Currently, Supervisor Rules in Zoho Desk run once every hour but only apply to tickets that have received a customer response within the past 30 days. This restriction creates challenges for us, as we have
    • Paid Support Plans with Automated Billing

      We (like many others, I'm sure) are designing or have paid support plans. Our design involves a given number of support hours in each plan. Here are my questions: 1) Are there any plans to add time-based plans in the Zoho Desk Support Plans feature? The
    • Next Page