Skip to main content
RapidDev - Software Development Agency
retool-integrationsREST API Resource

How to Integrate Retool with Zoho CRM

Connect Retool to Zoho CRM using a REST API Resource with OAuth 2.0 self-client (server-to-server) authentication. Use COQL (CRM Query Language) to query leads, contacts, deals, and custom modules, then build a custom CRM operations panel that overcomes Zoho's rigid UI with Retool's flexible dashboards.

What you'll learn

  • How to create a Zoho self-client OAuth application and generate a long-lived refresh token
  • How to configure Retool's Custom Auth to handle Zoho access token refresh automatically
  • How to write COQL queries to search and filter CRM records
  • How to build a Zoho CRM operations panel with leads, contacts, and deals views
  • How to update CRM records and create notes from Retool
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Intermediate13 min read30 minutesMarketingLast updated April 2026RapidDev Engineering Team
TL;DR

Connect Retool to Zoho CRM using a REST API Resource with OAuth 2.0 self-client (server-to-server) authentication. Use COQL (CRM Query Language) to query leads, contacts, deals, and custom modules, then build a custom CRM operations panel that overcomes Zoho's rigid UI with Retool's flexible dashboards.

Quick facts about this guide
FactValue
ToolZoho CRM
CategoryMarketing
MethodREST API Resource
DifficultyIntermediate
Time required30 minutes
Last updatedApril 2026

Build a Custom Zoho CRM Operations Panel in Retool

Zoho CRM's standard interface is comprehensive but can be slow and complex for operations teams who need fast access to specific CRM views, bulk updates, or cross-module reporting. Retool provides a faster, more focused alternative by connecting directly to Zoho's API and presenting exactly the data and actions your team needs.

Zoho CRM offers a powerful query language called COQL (CRM Object Query Language) that works like SQL — you can write SELECT statements with WHERE clauses, ORDER BY, GROUP BY, and JOINs across CRM modules. This makes Retool particularly well-suited for building complex CRM dashboards because you can express sophisticated data requirements in familiar SQL-like syntax.

The main complexity in this integration is Zoho's OAuth 2.0 flow. Unlike APIs with simple API keys, Zoho requires OAuth. For Retool integrations, the recommended approach is the 'self-client' method in Zoho's Developer Console, which provides a one-time authorization that generates a refresh token. Retool's Custom Auth flow handles subsequent token refreshes automatically using this refresh token.

Integration method

REST API Resource

Zoho CRM's REST API v7 requires OAuth 2.0 authentication. For server-to-server integrations like Retool, the recommended approach is a self-client application in the Zoho Developer Console, which generates a refresh token that can be exchanged for access tokens without user interaction. Retool proxies all API calls server-side, keeping OAuth credentials secure.

Prerequisites

  • A Zoho CRM account with API access (available on Professional plan and above)
  • Access to Zoho Developer Console (developer.zoho.com) to create a self-client application
  • A Retool account with permission to create Resources and use Custom Auth
  • The Zoho CRM data center for your account (US: zohoapis.com, EU: zohoapis.eu, IN: zohoapis.in)
  • Basic familiarity with SQL syntax for writing COQL queries

Step-by-step guide

1

Create a Zoho self-client OAuth application

Navigate to the Zoho Developer Console at developer.zoho.com (make sure you are logged in with your Zoho account). Click 'Add Client' and select 'Self Client' as the client type. Self-client is designed specifically for server-to-server integrations where there is no end-user browser redirect — it is the correct choice for Retool. Give the application a name like 'Retool CRM Integration' and click 'Create'. The Developer Console displays a Client ID and Client Secret — copy both values immediately. Next, you need to generate a refresh token. In the self-client application details, click 'Generate Code'. Enter the scopes your integration needs — for full CRM access, enter: ZohoCRM.modules.ALL,ZohoCRM.settings.ALL,ZohoCRM.bulk.ALL. Set the time duration to 3 minutes (the code is valid briefly). Copy the generated authorization code. Now make an API call to exchange this code for a refresh token: POST to accounts.zoho.com/oauth/v2/token with client_id, client_secret, code, redirect_uri=urn:ietf:wg:oauth:2.0:oob, and grant_type=authorization_code. You can use Postman or curl for this step. The response contains a refresh_token — this is long-lived and what Retool will use.

token-exchange.sh
1// Exchange authorization code for refresh token
2// POST https://accounts.zoho.com/oauth/v2/token
3// (Adjust domain for your data center: .eu, .in, .com.au)
4
5// Form parameters:
6// client_id=your_client_id
7// client_secret=your_client_secret
8// code=the_authorization_code_from_developer_console
9// redirect_uri=urn:ietf:wg:oauth:2.0:oob
10// grant_type=authorization_code
11
12// Response includes:
13// {
14// "access_token": "short-lived (1 hour)",
15// "refresh_token": "long-lived - SAVE THIS",
16// "token_type": "Bearer"
17// }

Pro tip: The refresh token does not expire as long as it is used at least once per month. Store it in Retool's configuration variables as a secret. If you need to revoke access, delete the client in Zoho Developer Console.

Expected result: You have a Zoho OAuth Client ID, Client Secret, and Refresh Token stored securely, ready to configure in Retool.

2

Configure a REST API Resource with Zoho OAuth

In Retool, go to Resources → Create New → REST API. Set the Base URL to your Zoho CRM API endpoint based on your data center: 'https://www.zohoapis.com/crm/v7' for US accounts, 'https://www.zohoapis.eu/crm/v7' for EU, 'https://www.zohoapis.in/crm/v7' for India. Under Authentication, select 'Custom Auth'. The Custom Auth system in Retool allows you to define a flow that fetches an access token using your refresh token and stores it for subsequent requests. In the Custom Auth configuration, add a step that makes a POST request to Zoho's token endpoint (accounts.zoho.com/oauth/v2/token) with grant_type=refresh_token, client_id, client_secret, and refresh_token from your configuration variables. Store the returned access_token in a variable. Set the Authorization header for the resource to 'Bearer {{ access_token }}'. Configure token refresh to run when a 401 response is received, or on a 3600-second (1 hour) interval since Zoho access tokens expire after 1 hour.

custom-auth-config.js
1// Resource Base URL: https://www.zohoapis.com/crm/v7
2
3// Custom Auth token refresh step:
4// POST https://accounts.zoho.com/oauth/v2/token
5// Body (form-encoded):
6// grant_type=refresh_token
7// client_id={{ retoolContext.configVars.ZOHO_CLIENT_ID }}
8// client_secret={{ retoolContext.configVars.ZOHO_CLIENT_SECRET }}
9// refresh_token={{ retoolContext.configVars.ZOHO_REFRESH_TOKEN }}
10
11// Store response.access_token as {{ zoho_access_token }}
12// Use in Authorization header: Bearer {{ zoho_access_token }}

Pro tip: Store ZOHO_CLIENT_ID, ZOHO_CLIENT_SECRET, and ZOHO_REFRESH_TOKEN as separate Retool configuration variables marked as secrets. This way you can rotate the client secret without rebuilding the entire resource.

Expected result: The Zoho CRM REST API Resource is saved with Custom Auth configured. A test GET request to /Leads returns a 200 response with CRM data.

3

Query records using COQL

Zoho CRM's COQL endpoint allows SQL-like queries across all CRM modules. Create a new query using the Zoho CRM resource with HTTP method POST and path '/coql'. The request body is a JSON object with a single 'select_query' field containing your COQL statement. COQL syntax mirrors SQL: SELECT field1, field2 FROM ModuleName WHERE condition ORDER BY field LIMIT n OFFSET m. Module names in Zoho CRM are plural (Leads, Contacts, Deals, Accounts, Tasks) but in COQL they are singular (Lead, Contact, Deal, Account). The WHERE clause supports comparison operators, IN lists, LIKE for text search, and BETWEEN for date ranges. Bind the WHERE clause conditions to Retool component values for dynamic filtering. The COQL response wraps results in a 'data' array with a 'info' object containing pagination details.

coql-query.json
1// POST /coql
2// Request body:
3{
4 "select_query": "SELECT id, Last_Name, First_Name, Email, Lead_Status, Lead_Source, Annual_Revenue, Owner.name FROM Lead WHERE Lead_Status = '{{ statusFilter.value || 'New' }}' AND Created_Time >= '{{ dateRange.start || '2024-01-01T00:00:00+00:00' }}' ORDER BY Created_Time DESC LIMIT {{ pagination.pageSize || 50 }} OFFSET {{ (pagination.page - 1) * (pagination.pageSize || 50) || 0 }}"
5}

Pro tip: Use COQL's LIKE operator for text search: WHERE Last_Name LIKE '%{{ searchInput.value }}%'. The % wildcard works at the start or end of a value, but avoid leading wildcards on large datasets as they cannot use indexes.

Expected result: The COQL query returns a JSON response with a 'data' array of CRM records and an 'info' object containing count, more_records boolean, and per_page values for pagination.

4

Transform COQL response and build the dashboard

Add a transformer to the COQL query to normalize the Zoho response format. The COQL response nests results in data.data and includes owner information as a nested object. Flatten the owner name into a top-level field and format dates for display. Bind the transformer output to a Table component. For the dashboard layout, add a row of Select components for status and source filters, a DateRangePicker for date filtering, and a TextInput for name search. Wire each filter component's onChange event to trigger the COQL query. Add a Chart component showing lead distribution by status using a JavaScript query that aggregates the COQL data. Include a numeric stats row at the top showing total leads, new leads today, and conversion rate metrics.

transformer.js
1// Transformer: normalize Zoho COQL response
2const records = data.data || [];
3
4return records.map(record => ({
5 id: record.id,
6 name: `${record.First_Name || ''} ${record.Last_Name || ''}`.trim(),
7 email: record.Email || '',
8 status: record.Lead_Status || 'Unknown',
9 source: record.Lead_Source || 'Unknown',
10 owner: record.Owner?.name || 'Unassigned',
11 revenue: record.Annual_Revenue
12 ? `$${Number(record.Annual_Revenue).toLocaleString()}`
13 : 'N/A',
14 created: record.Created_Time
15 ? new Date(record.Created_Time).toLocaleDateString()
16 : 'N/A'
17}));

Pro tip: Add a color coding to the Table's Status column using Retool's conditional column formatting: green for 'Converted', yellow for 'Contacted', red for 'Not Contacted'.

Expected result: The dashboard displays a filterable Table of CRM records with charts and summary metrics. Changing filter components triggers the COQL query and updates the Table with fresh data.

5

Update CRM records and create activities

Create a write-back query to update CRM records. Use PUT method with path '/{{ module }}/{{ table1.selectedRow.id }}' where module is the CRM module name (Leads, Contacts, Deals). The request body is a JSON object with a 'data' array containing a single record object with the fields to update — only include fields you want to change, not the entire record. Create a Form component in Retool for the update panel with fields for status, owner, and notes. Wire the form's submit button to run the PUT query. For adding activity notes, create a separate POST query to '/Activities' with the note text, date, and related record ID. Add a confirmation modal before submitting to prevent accidental updates. For complex multi-module workflows and CRM automation, RapidDev's team can help build sophisticated Retool applications that integrate Zoho CRM with your other business tools.

update-record.json
1// PUT /Leads/{{ table1.selectedRow.id }}
2// Request body:
3{
4 "data": [
5 {
6 "Lead_Status": "{{ statusSelect.value }}",
7 "Owner": {
8 "id": "{{ ownerSelect.value }}"
9 }
10 }
11 ]
12}
13
14// POST /Notes (create activity note)
15// Request body:
16{
17 "data": [
18 {
19 "Note_Title": "Retool Update",
20 "Note_Content": "{{ noteInput.value }}",
21 "Parent_Id": {
22 "id": "{{ table1.selectedRow.id }}",
23 "module": "Leads"
24 }
25 }
26 ]
27}

Pro tip: Zoho CRM's API returns a 'code': 'SUCCESS' field in successful update responses alongside the HTTP 200 status. Add transformer logic to check this field and show a meaningful error message if the update failed despite a 200 status code.

Expected result: Selecting a record, changing the status in the form, and clicking save successfully updates the record in Zoho CRM. The query refreshes the table, and the updated status is visible immediately.

Common use cases

Build a CRM operations dashboard for sales managers

Create a Retool app showing pipeline stages, deal values, and owner assignments across all active deals. Add COQL-powered filters for deal stage, closing date range, and deal owner. Include one-click actions to update deal stages, assign owners, and add activity notes — providing faster deal management than Zoho's native kanban view.

Retool Prompt

Build a Retool dashboard that shows all Zoho CRM deals with status 'Negotiation/Review' or 'Value Proposition', grouped by owner, with total deal value per stage, and a button to mark selected deals as 'Closed Won'.

Copy this prompt to try it in Retool

Create a lead qualification and routing panel

Display new and unqualified leads with their source, score, and contact details in a Retool Table. Build a form for sales reps to update lead status, assign to an owner, and convert to a contact+deal — all from a single panel. Add COQL queries to identify leads that have been untouched for more than 7 days.

Retool Prompt

Create a Retool lead management panel showing all leads with status 'Not Contacted' or 'Attempted to Contact', with their source, lead score, and contact details. Include buttons to assign to a rep, change status, and add a follow-up note.

Copy this prompt to try it in Retool

Build a cross-module reporting dashboard

Use COQL JOINs to combine data from multiple Zoho CRM modules — for example, join Contacts with Deals to show each contact's deal pipeline value, or join Accounts with Contacts to build an account health view. Display charts showing deal win rates by lead source, average deal size by territory, or conversion rates by campaign.

Retool Prompt

Build a Retool CRM reporting dashboard using COQL JOINs to show total deal value per Account, grouped by deal stage, with a bar chart visualization and a Table of accounts sorted by pipeline value descending.

Copy this prompt to try it in Retool

Troubleshooting

OAuth token exchange returns 'invalid_client' error

Cause: The Client ID or Client Secret does not match the self-client application in Zoho Developer Console, or the authorization code has expired (codes are valid for only 3 minutes after generation).

Solution: Verify Client ID and Secret by copying them again directly from Zoho Developer Console → your self-client application → Client Secret tab. If the authorization code expired, generate a new code in the 'Generate Code' section and immediately exchange it before the 3-minute window closes.

COQL query returns 'INVALID_MODULE' error

Cause: COQL uses singular module names (Lead, Contact, Deal, Account) but Zoho's REST API module endpoints use plural names (Leads, Contacts, Deals, Accounts). Using the wrong form in COQL will cause this error.

Solution: Use singular module names in COQL SELECT statements: FROM Lead, FROM Contact, FROM Deal. For custom modules, the API name is used (e.g., FROM Custom_Module_Name). Check your module's API name in Zoho CRM → Settings → Modules and Fields → the module's 'API Name' field.

typescript
1// Correct COQL module names:
2// SELECT ... FROM Lead (not Leads)
3// SELECT ... FROM Contact (not Contacts)
4// SELECT ... FROM Deal (not Deals)
5// SELECT ... FROM Account (not Accounts)

Access token expires and queries start returning 401 errors

Cause: Zoho access tokens are valid for only 1 hour. If Retool's Custom Auth token refresh is not configured correctly, the token expires and subsequent queries fail.

Solution: In the Resource's Custom Auth configuration, ensure the token refresh trigger is set to '401 response' so Retool automatically re-fetches the access token when it expires. Also verify the refresh_token in configuration variables has not expired due to inactivity — Zoho refresh tokens expire if unused for 60 days.

API returns correct data for US accounts but wrong data center error for EU accounts

Cause: Zoho has regional data centers and the API base URL must match the data center where your account is hosted. Using the US URL for an EU account returns errors.

Solution: Determine your Zoho data center by checking the URL when logged in: .zoho.com = US, .zoho.eu = EU, .zoho.in = India, .zoho.com.au = Australia. Update the REST API Resource base URL to match: zohoapis.eu/crm/v7, zohoapis.in/crm/v7, etc. The accounts/OAuth URL also changes: accounts.zoho.eu, accounts.zoho.in.

Best practices

  • Store Zoho OAuth credentials (Client ID, Client Secret, Refresh Token) in Retool configuration variables marked as secrets — never include them in query bodies
  • Use COQL queries instead of the standard module list endpoints when you need filtered or sorted data — COQL is significantly more efficient and reduces the number of API calls needed
  • Request only the specific fields you need in COQL SELECT statements rather than selecting all fields — Zoho CRM can have hundreds of custom fields, and fetching all of them wastes API quota and slows Retool tables
  • Implement pagination using COQL's LIMIT and OFFSET clauses and track total count from the response's info.count field — Zoho limits COQL results to 200 records per request
  • Use Retool Workflows for scheduled CRM data sync operations (e.g., daily lead reports, weekly pipeline summaries) rather than loading large datasets in interactive Retool apps
  • Build role-based access control into your Retool app using Retool Groups to ensure sales reps can only see and update their own CRM records, mirroring Zoho's territory-based permissions

Alternatives

Frequently asked questions

What is COQL and how does it differ from Zoho's standard REST API?

COQL (CRM Object Query Language) is Zoho's SQL-like query language that lets you fetch filtered, sorted, and aggregated CRM data in a single API call. The standard REST API requires separate endpoints for each module and offers limited filtering options. COQL is more powerful — you can JOIN modules, use complex WHERE conditions, and get exactly the fields you need — making it the preferred approach for Retool integrations.

Does Retool have a native Zoho CRM connector?

No, Retool does not have a native Zoho CRM connector. You connect using a REST API Resource with Custom Auth for OAuth 2.0 token management. The REST API approach provides access to all Zoho CRM API capabilities including COQL, bulk operations, and custom module management.

How many Zoho CRM API calls can I make per day?

Zoho CRM API limits vary by plan. The Professional plan allows 3,000 API calls per hour per organization. The Enterprise plan allows 10,000 calls per hour. COQL queries count as one API call regardless of how many records they return (up to 200 per page). Monitor your usage in Zoho CRM → Settings → Developer Space → API Dashboard.

Can I access Zoho CRM custom modules and custom fields from Retool?

Yes. Custom modules created in Zoho CRM are accessible via the REST API and COQL using their API name (visible in Zoho Settings → Modules → API Name column). Custom fields are included in API responses and can be referenced in COQL SELECT and WHERE clauses using their API field name.

Can I bulk update multiple Zoho CRM records from Retool?

Yes. Zoho CRM's REST API supports bulk updates via PUT requests to module endpoints where the request body contains a 'data' array with up to 100 records per request. Use a Retool Workflow to iterate through a list of records and batch them into 100-record chunks for bulk updates, which is more efficient than individual record updates.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Integrations are where projects stall

We wire Retool integrations like this one every week — auth, webhooks, edge cases included. Fixed-price builds from $13K, delivered in 6–10 weeks.

Talk to an integration engineer

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.