Kaizen #80 - COQL API - Part I

Kaizen #80 - COQL API - 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:


    • 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

    • Let's Talk Recruit: Super-charge hiring with Zoho Recruit add-ons

      Welcome back to our Let’s Talk Recruit series! This time, we’re diving into something that might seem like a small upgrade but has a huge impact on recruiter productivity: Zoho Recruit add-ons. Think about how much of your day is spent in your inbox or
    • Vendor Signatures Needed for Purchase Orders

      Hello everyone, We have a unique requirement that necessitates that Vendors & Suppliers formally acknowledge our Purchase Orders upon receipt. I was hoping that there would be an option to do so in Zoho Books, but that does not appear to be the case.
    • Is there an API to "File a Ticket" in Desk

      Hi, Is there an API to "File a Ticket" in Desk to zoho projects?
    • Store "Sign in with Google/Microsoft/GitHub etc." details

      Quite often now, users are using a sign-in provider like Google or Microsoft to sign into various apps and services. It would be great if Vault could remember which providers you use for each website and sign you in with that provider instead of a username
    • Critical Issue: Tickets Opened for Zoho Support via the Zoho Help Portal Were Not Processed

      Hi everyone, We want to bring to your attention a serious issue we’ve experienced with the Zoho support Help Portal. For more than a week, tickets submitted directly via the Help Portal were not being handled at all. At the same time no alert was posted
    • Tip of the Week #72– Assign thread ownership to avoid confusion.

      When teams handle a large volume of emails, managing threads becomes important to stay organized. Without a clear system, duplicate replies, missed follow-ups, or confusion over responsibilities can happen. Thread assignment solves this by designating
    • Unarchive tickets

      How can I manually unarchive tickets?
    • Optimize your Knowledge Base for enhanced accessibility by adding alt tags for images

      Let's learn why alt tags are crucial for your articles. You can add alternative tags (alt tags) and alternative text (alt text) to the images you share on your community forums or when embedding them in articles. Alt tags refer to the HTML attribute,
    • FSM trying again

      have not linked FSM yet to the rest of out Zoho suit. It certainly looks like the apointment and service part is more manageable for our staff. The question is that our engineers multi task examples 1. deliver products to customers not fitted 2. Service
    • Feature Request: Conditional Field Mandatoriness Based on Display Status

      Hello Zoho Creator Team, I would like to suggest an enhancement to improve the flexibility of form validations. Currently, when we need a field to be mandatory only if it's displayed on the form, the only option is to: Set the field as not mandatory in
    • Data Migration Strategies for Moving to a Cloud Solution

      Hi everyone, I’ve been working on moving some of our critical systems, including CRM and project data, to a Zoho cloud solution, and one of the biggest challenges I’ve encountered is data migration. Transferring large volumes of data while keeping it
    • Commerce Order as Invoice instead of Sales Order?

      I need a purchase made on my Commerce Site to result in an Invoice for services instead of a Sales Order that will be pushed to Books. My customers don't pay until I after I add some details to their transaction. Can I change the settings to make this
    • How to set different item selling prices for Zoho Commerce and Zoho Books

      Item selling prices for Zoho Commerce and Zoho Books are in sync. If we update the Item selling price in Books, the same will happen in commerce and vice versa. I need a separate commerce selling price for online users and a separate books selling price
    • Time Entry Notifications

      Hi All - I have support staff who place notes of their work in the time entry section of Zoho Desk. Is there a specific workflow or setting I need to enable to have the ticket holder updated via email when an entry is saved?
    • How to report 'Response violation' OR 'Resolution violation'

      Hi, I want to report on SLA Violation Type. I grouped my tickets on this column. It seems I only get 'Response and Resolution Violation' or 'Not Violated'. The former seems to be given to a ticket if only the Response Time was violated. I would expect
    • [Webinar] Automate sales and presales workflows with Writer

      Sales involves sharing a wide range of documents with customers across the presales, sales, and post-sales stages: NDAs, quotes, invoices, sales orders, and delivery paperwork. Generating and managing these documents manually slows down the overall sales
    • Power of Automation :: Quick way to associate your Projects with Zoho CRM

      A custom function is a software code that can be used to automate a process and this allows you to automate a notification, call a webhook, or perform logic immediately after a workflow rule is triggered. This feature helps to automate complex tasks and
    • Date triggering Workflow rule

      I have a function triggered by a workflow rule. The function takes a date and creates a task for that date and fills in a field with the name of the day for that date. It also updates the status field of the record. The workflow rule is set to run whenever
    • Restricting contact creation

      Hi all! I am looking to use Zoho Desk in a part of the business that takes end user enquiries. These are generally single interactions, and not linked to an account name. As Desk is Account centric, has anyone designed a way to manage these incoming emails
    • Import Holiday Calendars

      HI Zoho Is there anyway of importing an online calendar like https://www.calendarlabs.com into the business hours calendars, to speed up setup of holiday calendars. Also could we also request a feature where you can specify a Holiday as hours, i.e it could be that the company is on a 1/2 day due to a holiday or when it is Eid in the UAE and they are only allowed to work restricted hours so we need the calendar to be flexible to allow for this. Regards Jamie
    • Filtering Tickets based on Email headers

      We're starting to get a lot more junk coming into our Zoho Desk, which is then triggering unnecessary email alerts to agents. Once thing we could do to cut this junk in half, is to filter tickets based on email headers. Any email containing the `List-Unsubscribe`
    • Error 550 5.4.1

      I’ve tried sending an email to someone but keep receiving this back. Any help would be greatly appreciated 
    • Billing Management: #2 Fair way of Billing- Prorated Billing

      Hello, From speaking about the traditional ways of billing in the previous post, we are moving into the deep sea of billing. We are now in a zone to break out the most complex yet, I would call it the fairest way of billing, the Prorated Billing. Prorated
    • Has Anyone successfully integrated Zoho and Sage Intact?

      Hey all, We’re evaluating Zoho One + Sage Intacct and I’m trying to connect with anyone who has actually implemented the two together.Specifically, I’d love to know: -- Which functions you kept in Zoho vs. Intacct (e.g., Product Catalog, AR/AP, invoicing,
    • How can I filter a field integration?

      Hi,  I have a field integration from CRM "Products" in a form, and I have three product Categories in CRM. I only need to see Products of a category. Thanks for you answers.
    • Adding image in HTML report page

      Hi, I want to know two things: 1. Can anyone advise how to add an image in HTML report. The tagged used is <img> but what path do I mention for the image to be added in the HTML report. 2. Also, I want to know if I am creating an application for the market
    • How to change view of HTML report based on device but always print in A4

      Hello everyone, I am aware that HTML report view can be configured to adjust according to the screen size like Laptop, Tablet and mobile using media queries. But my concern is no matter on which device the reports is opened when printed should always
    • Age Calculation

      I've attempted to calculate the age of someone based on their birthday input by using the formula field. It works but I don't want all those decimals on there. I then tried to use "set variable" after birthday input but I get a field type mismatch, long vs. floating. Any ideas would be wonderful.
    • Search on Custom Field

      We're working on an integration with the Zoho FSM API and are trying to retrieve companies based on a custom field we added to the Companies module. However, we can't find a way to filter or query records using custom fields through the API. We have a
    • Sendmail function / custom action?

      I've setup a function hoping to email various business departments the details of a record once all work in that record is complete so gone about setting up a custom action in such way that each record line on the report has a button to click. Question is how do I actually include data from that record in the email that is sent when the button is clicked? I had thought that since this were being sent per record the email would include the data which had been entered
    • API to post drafts for social media

      I we want to post draft posts to our zoho social account and then approve and schedule them within Zoho social. is this possible with for example: https://apis.zoho.com/social/v2/post TIA Jon
    • Canvas View in Zoho Recruit

      Is it possible or would it be possible to have the new 'Canvas View' in Zoho Recruit?
    • What impactful sales coaching techniques have you used to boost your team's performance?

      I'm curious about the real-world impact of sales coaching on team performance. What specific techniques or strategies have you found most effective in driving consistent improvement and growth in your sales team? Any success stories or lessons learned
    • Adding Taxes to paid consultations in Zoho Bookings

      I created a 'paid' consultation under Zoho Booking and integrated it with payment gateways for online/instant payment before a booking is done. How can I add 'taxes' to the price of consultation? I can add taxes to other Zoho apps (liks Books, Checkout,
    • Zoho Finance Suite - Customer Custom Tabs - Dynamic Link

      Hi Finance Suite team, When creating a Custom Tab for a Client Portal, there is no option to add dynamic parameters. This would be very helpful for adding Zoho Analytics dashboards which can be dynamically filtered through the URL to only show information
    • Possible to bold or indent text in the description field?

      As part of one item, I often have a detailed description that would be much easier to read if there was the ability to have a bulleted list or bold text and the like. Is this possible? My last invoicing software allowed markup in the field so, for example, an asterisk meant a bullet. I haven't been able to find any documentation related to this.  Any information would be appreciated. Thank you.
    • How can I setup Zoho MCP with Chat GPT

      I can set up custom connections with Chat GPT but I cat an error when I try to set it up. The error is: "This MCP server can't be used by ChatGPT to search information because it doesn't implement our specification: search action not found" Thoughts?
    • Formatting of Balance Sheet and Profit & Loss Reports

      The default format of the Balance Sheet and P&L Reports are based on the Account Types and then the individual accounts within the Chart of Accounts. These are then ordered alphabetically under these sub-headings and one is unable to re-order these or
    • UK MTD reports concerning turnover and cerash accounting

      Hi I am a sole trader, and I have just started with Zoho Books in order to comply with the new HMRC requirements. I use 'cash basis' - which I understand to mean that income is when the cash comes in (not the invoice date) and expenses are when they are
    • Retainer Invoice.

      Why ZOHO not have facilities to deduct partially advance payment from an invoice.
    • Next Page