Skip to main content

Zoho CRM

Read and write a Zoho CRM org - leads, contacts, accounts, deals and custom modules - with COQL queries, related lists, notes and lead conversion.

Connect a Zoho CRM org with a Self Client refresh token to work its records end to end: discover the org's own modules and field schemas; list, get, search and COQL-query records of ANY module including custom ones; read related lists, notes and deletions; create, update, upsert and delete records in batches of up to 100; attach notes; and convert leads into contacts, accounts and deals. Counting is done with COQL aggregates rather than by measuring a page, and every write reports its outcome per record.

Connect

Credential fieldRequiredWhere it comes from
Client ID (CLIENT_ID)YesThe Self Client's Client ID from the Zoho API console.
Client secret (CLIENT_SECRET)YesThe Self Client's Client Secret, from the same screen.
Refresh token (REFRESH_TOKEN)YesThe long-lived refresh token exchanged from the Self Client's grant code. It carries the scopes chosen at that moment and identifies the Zoho user every action is attributed to.
SettingRequiredWhat it is
Data centre (DATA_CENTER)YesThe Zoho region this org lives in - one of: us, eu, in, au, jp, ca, sa, cn. Shown in your Zoho CRM URL. It selects both the sign-in host and the API host, and a Self Client from another region will not work.

Tools

ToolAccessWhat it does
Get organization (yekar.zoho-crm.get-organization)ReadThe Zoho CRM organization this connection points at - company name, primary email, country, time zone, currency, edition and the org id (zgid). The cheapest way to confirm the connection works and that the Data centre setting matches the org you meant. To see WHICH Zoho user the connection acts as, use List users with type CurrentUser.
List modules (yekar.zoho-crm.list-modules)ReadEvery module in this Zoho CRM org - the standard ones (Leads, Contacts, Accounts, Deals…) and any custom modules - with the exact case-sensitive API name each record tool needs, plus whether the module is creatable, editable and deletable. This is the discovery path: module API names are not guessable, custom modules have org-specific ones, and even standard modules can be renamed.
List fields (yekar.zoho-crm.list-fields)ReadEvery field on a module with its exact API name, data type, whether it is read-only or mandatory, its picklist values, and for lookup fields the module an id must come from. Call this before writing a record: field API names are case-sensitive and org-specific, writing a read-only field is rejected, and a picklist only accepts values from its own list.
List users (yekar.zoho-crm.list-users)ReadUsers in this Zoho CRM org with their role, profile and status - the ids that record Owner fields and assignment take. Pass type CurrentUser to find out which Zoho user this connection itself acts as, whose profile is the permission ceiling for every tool here.
List records (yekar.zoho-crm.list-records)ReadA page of records from any module - standard or custom - with cursor or page-number paging. Ask for the fields you need; Zoho returns a default set otherwise. This endpoint reports no total: use Query records with COUNT() to count, or Search records to filter by field values.
Get record (yekar.zoho-crm.get-record)ReadOne record by id from any module, with its fields as Zoho types them - numbers stay numbers, and a lookup field comes back as an id plus a display name. Reads live data, so unlike Search records it sees a record created a moment ago.
Search records (yekar.zoho-crm.search-records)ReadFind records in a module by criteria expression, email, phone or free text. Exactly one of those four is used per call, in that priority order. Note two things this tool cannot do: it reports no total (use Query records with COUNT), and it reads a lagging search index, so a just-written record may not appear yet - Query records and Get record read live data.
Query records (yekar.zoho-crm.query-records)ReadRun a COQL SELECT against this org's CRM data - the most precise read here, and the only one that can COUNT. Supports WHERE with and/or, joins across lookup fields, ORDER BY, LIMIT/OFFSET, and the aggregates COUNT, SUM, AVG, MIN and MAX with GROUP BY. Reads live data, so it is also the reliable way to confirm a record that was just written. Read-only: COQL has no INSERT, UPDATE or DELETE.
List related records (yekar.zoho-crm.list-related-records)ReadThe records linked to one record through a named related list - a contact's Deals, an account's Contacts, any record's Notes or Tasks. The related list API names are per-module; the module metadata in Zoho lists them, and the common ones are Notes, Attachments, Tasks, Contacts, Deals and Products.
List deleted records (yekar.zoho-crm.list-deleted-records)ReadRecords deleted from a module, who deleted them and when, and whether each is still in the Recycle Bin or has been permanently purged. Use this to confirm a delete landed, or to find a record that has gone missing before concluding it never existed. Returns a slim entry per deletion, not the record's fields - Zoho does not serve those once deleted.
Create records (yekar.zoho-crm.create-records)WriteCreate up to 100 records in one module. Zoho reports the outcome PER RECORD, so a partly-valid batch returns some ids and some failures with their reasons - read the counts, not just the absence of an error. Records are created as the Zoho user this connection acts as. Not idempotent: calling twice creates two sets of records; use Upsert records when re-running must not duplicate.
Update records (yekar.zoho-crm.update-records)WriteUpdate up to 100 records in one module by id. This is a partial update: only the fields you send change, and sending null clears one. Zoho reports the outcome PER RECORD, so a partly-valid batch returns some successes and some failures with their reasons - read the counts. Records are stamped as modified by the Zoho user this connection acts as.
Upsert records (yekar.zoho-crm.upsert-records)WriteInsert up to 100 records, updating any that already match on the duplicate-check fields instead of creating a second copy. Each result says which branch Zoho took - insert or update - so a re-run is visible rather than assumed. This is the tool to use when an automation may run more than once over the same data; Create records would duplicate.
Delete records (yekar.zoho-crm.delete-records)WriteDelete up to 100 records from a module by id. This moves them to the Zoho Recycle Bin, where they remain restorable from the Zoho CRM UI - it does not erase them, and this integration has no tool that does. A record's notes and attachments go with it. Zoho reports the outcome per record, so a batch containing an unknown id returns that failure alongside the successes.
Create note (yekar.zoho-crm.create-note)WriteAttach a note to a record in any module. Notes are visible to everyone who can see the record - this is not a private annotation. Authored as the Zoho user this connection acts as. Not idempotent: calling twice leaves two notes, so re-run it only when a duplicate note is acceptable.
Convert lead (yekar.zoho-crm.convert-lead)WriteConvert a Lead into a Contact and an Account, optionally creating a Deal at the same time. This is irreversible - the Lead ceases to exist as a Lead and there is no undo, in this integration or in Zoho. Existing Contact and Account ids can be supplied to merge into them rather than creating duplicates.

Notes

  • Set Data centre to the region this Zoho org is registered in - one of: us, eu, in, au, jp, ca, sa, cn. It is visible in your Zoho CRM URL (zoho.eu, zoho.in, zohocloud.ca…). A Self Client only exists in the data centre that created it, so a mismatch fails sign-in with a misleading 'invalid client' error.
  • In the Zoho API console (api-console.zoho.com, or the console for your data centre) create a Self Client, and copy its Client ID and Client Secret.
  • On the Self Client's Generate Code tab request these scopes: ZohoCRM.modules.ALL, ZohoCRM.settings.modules.READ, ZohoCRM.settings.fields.READ, ZohoCRM.coql.READ, ZohoCRM.users.READ, ZohoCRM.org.READ. Set a time duration and describe the client, then copy the grant code - it is valid for minutes only.
  • Exchange the grant code once for a refresh token: POST to https://<your accounts host>/oauth/v2/token with grant_type=authorization_code, your client id and secret, and the code. Paste the refresh_token from the response here. The access token in that same response is not needed - this integration mints its own.
  • Scopes are bound to the refresh token when it is created. Adding a scope later means generating a NEW grant code and a new refresh token - it is not a setting you can toggle, and a missing scope shows up as a scope-mismatch error naming the fix.
  • EVERY action is attributed to the Zoho user who generated the refresh token, not to the person who triggered the automation: records are created and modified under that user's name, and their profile, role and data-sharing rules are the permission ceiling. Bind automations using this integration as a service connection.
  • Zoho keeps a limited number of refresh tokens per client and drops the oldest when you mint another - reusing this Self Client for something else can silently revoke this connection.
  • Deleting a record moves it to the Recycle Bin, where it stays restorable from the Zoho CRM UI. Converting a lead, by contrast, cannot be undone.