Zoho CRM Integration
Connect your AI agents to Zoho CRM
One-Click Connect available! Zoho CRM connects via OAuth. Just click “Connect Platform”, select your region, and authorize. No API keys, tokens, or manual configuration needed.
Step 1: Connect Zoho CRM
Recommended: Use the one-click OAuth connection. It automatically handles authentication, token refresh, and multi-region support.
- 1Go to Settings → Integrations
- 2Click Connect Platform → Zoho CRM
- 3Select your Zoho region (US, EU, India, Australia, or Japan)
- 4Log in to your Zoho account and click Accept to authorize
- 5Done! Your access token refreshes automatically. No maintenance needed
| Detail | Value |
|---|---|
| Base URL | Set automatically from your Zoho region |
| Auth Type | OAuth 2.0 (automatic) |
| Token Refresh | Automatic (every 60 minutes) |
| API Version | v7 |
Supported Regions
| Region | Domain | API Base URL |
|---|---|---|
| United States (default) | zoho.com | https://www.zohoapis.com |
| Europe | zoho.eu | https://www.zohoapis.eu |
| India | zoho.in | https://www.zohoapis.in |
| Australia | zoho.com.au | https://www.zohoapis.com.au |
| Japan | zoho.jp | https://www.zohoapis.jp |
Step 2: Add Actions with Pre-Built Templates
Once connected, click Add Action to open the template picker. Choose from 60 pre-built actions across 15 Zoho CRM modules, so there is no need to configure endpoints, body templates, or field names manually.
New: Pre-built templates configure everything for you in one click. Just select a template, review the settings, and save. You can always customize the action after adding it.
Available Templates (60 total)
Contacts
Leads
Accounts
Deals
Cases
Tasks
Calls
Events
Notes
Products
Quotes
Appointments
Solutions
Direct Lookups
Users & Tags
What Each Action Does
Search
Searches across all text fields in the module using the /search?word= API. Requires at least 2 characters. Returns up to 200 matching records.
GET /crm/v7/Contacts/search?word=John
# Response (200 OK):
{
"data": [{
"id": "4878934000000123456",
"First_Name": "John",
"Last_Name": "Smith",
"Email": "[email protected]",
"Phone": "+15551234567"
}],
"info": { "count": 1, "more_records": false }
}
# No results returns 204 No Content (empty body, not an error)Create
Creates a new record. All Zoho create operations use the {"data": [{...}]} array wrapper, even for a single record. Returns 201 on success.
POST /crm/v7/Contacts
Body: { "data": [{ "Last_Name": "Smith", "Email": "[email protected]" }] }
# Response (201 Created):
{
"data": [{
"code": "SUCCESS",
"status": "success",
"message": "record added",
"details": {
"id": "4878934000000314001",
"Created_Time": "2026-02-12T10:00:00-08:00"
}
}]
}Update
Updates an existing record. Zoho uses PUT (not PATCH), but it behaves like a partial update where only provided fields are changed. Returns 200 on success.
PUT /crm/v7/Contacts/4878934000000123456
Body: { "data": [{ "Email": "[email protected]" }] }
# Response (200 OK):
{
"data": [{
"code": "SUCCESS",
"status": "success",
"message": "record updated",
"details": { "id": "4878934000000123456" }
}]
}Delete
Soft-deletes a record. Deleted records go to the Recycle Bin for 60 days and can be restored. After 60 days they are permanently removed.
DELETE /crm/v7/Contacts/4878934000000123456
# Response (200 OK):
{
"data": [{
"code": "SUCCESS",
"status": "success",
"message": "record deleted",
"details": { "id": "4878934000000123456" }
}]
}Notes
Notes are attached to a parent record (Contact, Lead, Deal, etc.). When creating a note, you must specify the parent module and record ID. Search retrieves notes across all parent records.
# Search Notes
GET /crm/v7/Notes/search?word=follow up
# Create Note (attached to a Contact)
POST /crm/v7/Notes
Body: { "data": [{ "Note_Title": "Call follow-up", "Note_Content": "Discussed pricing options.", "Parent_Id": { "id": "4878934000000123456" }, "se_module": "Contacts" }] }
# Update Note
PUT /crm/v7/Notes/{{note_id}}
Body: { "data": [{ "Note_Title": "Updated title", "Note_Content": "Updated content" }] }
# 200 OK
{
"data": [{ "code": "SUCCESS", "status": "success", "message": "record updated" }]
}
# Delete Note
DELETE /crm/v7/Notes/4878934000000567890Products
Products represent your catalog items. They can be linked to Quotes and Deals as line items. Only Product_Name is required for creation.
# Search Products
GET /crm/v7/Products/search?word=Widget
# Create Product
POST /crm/v7/Products
Body: { "data": [{ "Product_Name": "Widget Pro", "Unit_Price": 49.99, "Product_Code": "WP-001", "Qty_in_Stock": 500 }] }
# Update Product
PUT /crm/v7/Products/4878934000000234567
Body: { "data": [{ "Unit_Price": 59.99 }] }
# Delete Product
DELETE /crm/v7/Products/4878934000000234567Quotes
Quotes represent price proposals sent to prospects. They contain line items (Quoted_Items) referencing Products. A Subject is required.
# Search Quotes
GET /crm/v7/Quotes/search?word=Enterprise
# Create Quote
POST /crm/v7/Quotes
Body: { "data": [{ "Subject": "Enterprise Plan - Acme Corp", "Quoted_Items": [{ "product": { "id": "4878934000000234567" }, "quantity": 10, "list_price": 49.99 }] }] }
# Update Quote
PUT /crm/v7/Quotes/4878934000000345678
Body: { "data": [{ "Subject": "Enterprise Plan v2 - Acme Corp" }] }
# Delete Quote
DELETE /crm/v7/Quotes/4878934000000345678Appointments
Appointments are scheduled meetings or visits. They require a name, start time, and end time in ISO 8601 format. Cancel uses the DELETE method and moves the appointment to the Recycle Bin.
# Search Appointments
GET /crm/v7/Appointments/search?word=demo
# Schedule Appointment
POST /crm/v7/Appointments
Body: { "data": [{ "Appointment_Name": "Product Demo - Acme Corp", "Start_DateTime": "2026-02-15T14:00:00-08:00", "End_DateTime": "2026-02-15T15:00:00-08:00", "Location": "Zoom" }] }
# Update Appointment
PUT /crm/v7/Appointments/4878934000000456789
Body: { "data": [{ "Start_DateTime": "2026-02-16T14:00:00-08:00", "End_DateTime": "2026-02-16T15:00:00-08:00" }] }
# Cancel Appointment
DELETE /crm/v7/Appointments/4878934000000456789Solutions
Solutions are knowledge base articles linked to Cases. They help your AI agent reference known fixes during support calls. Only Solution_Title is required.
# Search Solutions
GET /crm/v7/Solutions/search?word=password reset
# Create Solution
POST /crm/v7/Solutions
Body: { "data": [{ "Solution_Title": "How to Reset Password", "Solution_Details": "Navigate to Settings > Security > Change Password. Enter current password, then new password twice." }] }Direct Lookups
Fetch a single record by its Zoho ID. Use these when you already have the record ID from a previous action (e.g. after a search). Returns the full record with all fields.
# Get Contact by ID
GET /crm/v7/Contacts/4878934000000123456
# Get Lead by ID
GET /crm/v7/Leads/4878934000000123456
# Get Account by ID
GET /crm/v7/Accounts/4878934000000123456
# Get Deal by ID
GET /crm/v7/Deals/4878934000000123456
# Get Case by ID
GET /crm/v7/Cases/4878934000000123456
# Response (200 OK):
{
"data": [{
"id": "4878934000000123456",
"Full_Name": "John Smith",
"Email": "[email protected]",
...all fields
}]
}Users & Tags
Manage CRM users and record tags. List Users retrieves your team members (useful for assigning records). Tags help categorize records. Add Tag and Remove Tag use the record actions endpoint.
# List Users
GET /crm/v7/users?type=AllUsers
# Get User by ID
GET /crm/v7/users/4878934000000123456
# List Tags for a module
GET /crm/v7/settings/tags?module=Contacts
# Add Tag to a record
POST /crm/v7/Contacts/4878934000000123456/actions/add_tags
Body: { "tags": [{ "name": "VIP" }] }
# Remove Tag from a record
POST /crm/v7/Contacts/4878934000000123456/actions/remove_tags
Body: { "tags": [{ "name": "VIP" }] }Required Fields per Module
These are the system-mandatory fields for creating records. The AI agent knows which fields are required and will collect them from the customer before creating.
| Module | Required Fields | Notes |
|---|---|---|
| Contact | Last_Name | Only last name needed |
| Lead | Last_Name, Company | Both must be provided |
| Account | Account_Name | Company/org name |
| Deal | Deal_Name, Stage, Closing_Date | Closing_Date is YYYY-MM-DD format |
| Case | Subject, Status, Case_Origin | AI defaults: Status=New, Origin=Phone |
| Task | Subject | Only subject needed |
| Call | Subject, Call_Type, Call_Start_Time, Call_Duration | Duration in mm:ss format (e.g. 05:00) |
| Event | Event_Title, Start_DateTime, End_DateTime | ISO 8601 format. Remind_At auto-set to 15 min |
| Note | Note_Title, Note_Content, Parent_Id, se_module | se_module = parent module (e.g. Contacts) |
| Product | Product_Name | Only product name needed |
| Quote | Subject, Quoted_Items | Quoted_Items is an array of line items |
| Appointment | Appointment_Name, Start_DateTime, End_DateTime | ISO 8601 format |
| Solution | Solution_Title | Only solution title needed |
Step 3: Enable on Your AI Agent
- 1Go to AI Agents → select your employee → Edit
- 2Scroll to Integrations section
- 3Toggle on Zoho CRM and select which actions the employee can use
- 4Save. The AI will now use Zoho CRM during calls and widget conversations when relevant
Example Conversation
Here's how your AI agent uses Zoho CRM during a real phone call:
Caller: “Hi, this is John Smith from Acme Corp. I need help with my order.”
AI Agent: “Let me look you up, John.”
→ Executes: search_contact with search_term=“John Smith”
AI Agent: “I found your record, John. Let me create a support case for your order issue.”
→ Executes: create_case with Subject=“Order issue - John Smith”, Status=“New”, Case_Origin=“Phone”
AI Agent: “I've created case for you. Would you like me to schedule a callback with our specialist?”
Caller: “Yes, tomorrow at 2 PM please.”
→ Executes: create_event with Event_Title=“Callback - John Smith order issue”
AI Agent: “Done! I've scheduled a callback for tomorrow at 2 PM. I'll also log this call.”
→ Executes: log_call with Subject=“Inbound - John Smith order inquiry”, Call_Type=“Inbound”
Zoho-Specific Notes
Body wrapper: All Zoho create and update operations wrap the data in {"data": [{...}]}. The templates handle this automatically, so you don't need to add it manually.
Field naming: Zoho uses Title_Case_Underscores for field names (e.g. Last_Name, Deal_Name, Account_Name). This is different from HubSpot (camelCase) and Salesforce (PascalCase).
Updates use PUT: Zoho uses PUT instead of PATCH for updates, but it behaves as a partial update. Only the fields you send are changed and other fields are left untouched.
Search minimum: The word search parameter requires at least 2 characters. Single-character searches return an error. No results returns HTTP 204 (empty body), not an error.
Lookup fields: To link records (e.g. assign a Task to a Contact), use the object format: "Who_Id": {"id": "record_id_here"}. Plain string IDs won't work for lookup fields. You can add lookup fields by editing the action after creating it from a template.
Custom Actions from Scratch
Need something not covered by the 60 templates? You can create custom actions using any Zoho CRM API v7 endpoint. Here are some examples:
Search by Phone Number
Use the phone parameter for exact phone field matching:
GET /crm/v7/Contacts/search?phone={{caller_phone}}Search by Email
Use the email parameter to search across all email fields:
GET /crm/v7/Contacts/search?email={{email}}Criteria-Based Search
Use the criteria parameter for structured field-level queries:
GET /crm/v7/Leads/search?criteria=(Lead_Status:equals:Contacted)
# Multiple criteria (max 10):
GET /crm/v7/Deals/search?criteria=(Stage:equals:Qualification)and(Amount:greater_than:5000)
# Supported operators: equals, not_equal, starts_with, in,
# greater_than, less_than, greater_equal, less_equal, betweenList Records (No Search)
To list records without a search term, use the base module endpoint:
GET /crm/v7/Contacts?fields=First_Name,Last_Name,Email,Phone&per_page=10&sort_by=Modified_Time&sort_order=descAvailable Variables
Use these variables in your custom action endpoints and body templates:
| Variable | Description | Example |
|---|---|---|
| {{caller_phone}} | Phone number of the current customer | +15551234567 |
| {{employee_id}} | ID of the AI agent handling the call | emp_abc123 |
| {{call_id}} | Unique ID of the current call session | call_xyz789 |
| {{action.field}} | Value from a previous action result | {{search_contact.id}} |
Error Handling
Common Zoho API errors you may encounter:
| Error Code | HTTP Status | Meaning |
|---|---|---|
| MANDATORY_NOT_FOUND | 400 | A required field is missing |
| INVALID_DATA | 400 | Invalid value, wrong type, or search term too short |
| DUPLICATE_DATA | 400 | Duplicate value in a unique field |
| AUTHENTICATION_FAILURE | 401 | Token expired or invalid (auto-refresh should handle this) |
| NO_PERMISSION | 403 | User lacks permission for this module |
| RECORD_NOT_FOUND | 404 | The record ID does not exist |
Manual Setup (Advanced)
If you prefer not to use OAuth, you can manually configure the connection using a Self Client in the Zoho API Console. This is only recommended for advanced users.
- 1Go to Zoho API Console → Add Client → Self Client
- 2Note your Client ID and Client Secret
- 3Generate a grant token with scopes:
ZohoCRM.modules.ALL,ZohoCRM.settings.ALL - 4Exchange the grant token for access + refresh tokens
curl -X POST https://accounts.zoho.com/oauth/v2/token \
-d "grant_type=authorization_code" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET" \
-d "code=YOUR_GRANT_TOKEN"
# For EU region: use https://accounts.zoho.eu/oauth/v2/token
# For India: use https://accounts.zoho.in/oauth/v2/token| Field | Value |
|---|---|
| Connection Name | Zoho CRM |
| Base URL | https://www.zohoapis.com (or regional variant) |
| Auth Type | Bearer Token |
| Token | Your access_token |
| Token Expires | Enabled (1 hour) |
| Auto-Refresh | Enabled |
| Token URL | https://accounts.zoho.com/oauth/v2/token |
| Refresh Token | Your refresh_token |
| Client ID | Your Client ID |
| Client Secret | Your Client Secret |
Last updated: February 2026