zoho
Interact with Zoho CRM, Projects.
Installation
npx clawhub@latest install zohoView the full skill documentation and source below.
Documentation
Zoho Integration (CRM + Projects + Meeting)
Made by [Zone 99]() · [GitHub]() · [Contribute]()
Quick Start
Use the zoho CLI wrapper — it handles OAuth token refresh and caching automatically.
zoho help # Show all commands
zoho token # Print current access token (auto-refreshes)
Authentication Setup
Step 1: Register Your Application
- Client Name: your app name (e.g. "Clawdbot Zoho Integration")
- Homepage URL: your domain or
- **Redirect URI**: (or any URL you control — you only need it once to grab the code)Step 2: Generate Authorization Code (Grant Token)
Build this URL and open it in your browser (replace the placeholders):
?response_type=code
&client_id=YOUR_CLIENT_ID
&scope=ZohoCRM.modules.ALL,ZohoCRM.settings.ALL,ZohoProjects.projects.ALL,ZohoProjects.tasks.ALL,ZohoMeeting.recording.READ,ZohoMeeting.meeting.READ,ZohoMeeting.meetinguds.READ,ZohoFiles.files.READ
&redirect_uri=
&access_type=offline
&prompt=consent
Important: Use the accounts URL matching your datacenter:
| Region | Accounts URL |
|--------|-------------|
| US | |
> | EU | |
| IN | |
> | AU | |
| JP | |
> | UK | |
| CA | |
> | SA | |
After granting access, you'll be redirected to something like:
Copy the code parameter value. This code expires in 2 minutes — move to Step 3 immediately.
Step 3: Exchange Code for Refresh Token
Run this curl command (replace placeholders):
curl -X POST "" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET" \
-d "grant_type=authorization_code" \
-d "redirect_uri=" \
-d "code=PASTE_CODE_FROM_STEP_2"
Response:
{
"access_token": "1000.xxxx.yyyy",
"refresh_token": "1000.xxxx.zzzz",
"api_domain": "",
"token_type": "Bearer",
"expires_in": 3600
}
Save the refresh_token — this is your long-lived credential. The access token expires in 1 hour, but the CLI auto-refreshes it using the refresh token.
Step 4: Find Your Org IDs
CRM/Projects Org ID:
# After setting up .env with client_id, client_secret, refresh_token:
zoho raw GET /crm/v7/org | jq '.org[0].id'
Meeting Org ID:
Log into [Zoho Meeting]() → Admin Settings → look for the Organization ID in the URL or settings page. It's different from the CRM org ID.
Step 5: Configure .env
Create .env in the skill directory:
ZOHO_CLIENT_ID=1000.XXXXXXXXXXXXXXXXXXXXXXXXX
ZOHO_CLIENT_SECRET=your_client_secret_here
ZOHO_REFRESH_TOKEN=1000.your_refresh_token_here
ZOHO_ORG_ID=123456789 # CRM/Projects org ID
ZOHO_MEETING_ORG_ID=987654321 # Meeting org ID (different from CRM)
ZOHO_CRM_DOMAIN=
ZOHO_PROJECTS_DOMAIN=
ZOHO_MEETING_DOMAIN=
ZOHO_ACCOUNTS_URL=
Adjust the domain URLs if you're on a non-US datacenter (e.g..eu,.in,.com.au).
OAuth Scopes Reference
| Scope | Used For |
ZohoCRM.modules.ALL | Read/write CRM records (Deals, Contacts, Leads, etc.) |
ZohoCRM.settings.ALL | Read CRM field definitions and org settings |
ZohoProjects.projects.ALL | Read/write projects |
ZohoProjects.tasks.ALL | Read/write tasks, milestones, bugs, timelogs |
ZohoMeeting.recording.READ | List and access meeting recordings |
ZohoMeeting.meeting.READ | List meetings and session details |
ZohoMeeting.meetinguds.READ | Download recording files |
ZohoFiles.files.READ | Download files (recordings, transcripts) |
Troubleshooting Auth
- "invalid_code" → The authorization code expired (2 min lifetime). Redo Step 2.
- "invalid_client" → Wrong Client ID, or wrong accounts-server URL for your datacenter.
- "invalid_redirect_uri" → The redirect_uri in the curl must exactly match what you registered in API Console.
- Token refresh fails → Refresh tokens can be revoked. Redo Steps 2–3 to get a new one.
- "Given URL is wrong" → You're hitting the wrong API domain for your datacenter.
CRM Commands
# List records from any module
zoho crm list Deals
zoho crm list Deals "page=1&per_page=5&sort_by=Created_Time&sort_order=desc"
zoho crm list Contacts
zoho crm list Leads
# Get a specific record
zoho crm get Deals 1234567890
# Search with criteria
zoho crm search Deals "(Stage:equals:Closed Won)"
zoho crm search Contacts "(Email:contains:@acme.com)"
zoho crm search Leads "(Lead_Source:equals:Web)"
# Create a record
zoho crm create Contacts '{"data":[{"Last_Name":"Smith","First_Name":"John","Email":"j@co.com"}]}'
zoho crm create Deals '{"data":[{"Deal_Name":"New Project","Stage":"Qualification","Amount":50000}]}'
# Update a record
zoho crm update Deals 1234567890 '{"data":[{"Stage":"Closed Won"}]}'
# Delete a record
zoho crm delete Deals 1234567890
CRM Modules
Leads, Contacts, Accounts, Deals, Tasks, Events, Calls, Notes, Products, Quotes, Sales_Orders, Purchase_Orders, InvoicesSearch Operators
equals, not_equal, starts_with, contains, not_contains, in, not_in, between, greater_than, less_thanProjects Commands
# List all projects
zoho proj list
# Get project details
zoho proj get 12345678
# Tasks
zoho proj tasks 12345678
zoho proj create-task 12345678 "name=Fix+login+bug&priority=High&start_date=01-27-2026"
zoho proj update-task 12345678 98765432 "percent_complete=50"
# Other
zoho proj milestones 12345678
zoho proj tasklists 12345678
zoho proj bugs 12345678
zoho proj timelogs 12345678
Task Fields
name, start_date (MM-DD-YYYY), end_date, priority (None/Low/Medium/High), owner, description, tasklist_id, percent_completeMeeting Commands
# List all recordings
zoho meeting recordings
zoho meeting recordings | jq '[.recordings[] | {topic, sDate, sTime, durationInMins, erecordingId}]'
# Download a recording (use downloadUrl from recordings list)
zoho meeting download "" output.mp4
# List meetings/sessions
zoho meeting list
zoho meeting list "fromDate=2026-01-01T00:00:00Z&toDate=2026-01-31T23:59:59Z"
# Get meeting details
zoho meeting get 1066944216
Recording Response Fields
Key fields fromzoho meeting recordings:
erecordingId— encrypted recording ID (use for dedup/tracking)topic— meeting titlesDate,sTime— start date/time (human-readable)startTimeinMs— start time as epoch ms (use for date filtering)durationInMins— recording durationdownloadUrl/publicDownloadUrl— MP4 download URLtranscriptionDownloadUrl— Zoho-generated transcript (if available)summaryDownloadUrl— Zoho-generated summary (if available)fileSize/fileSizeInMB— recording file sizestatus— e.g.UPLOADEDmeetingKey— meeting identifiercreatorName— who started the recording
Meeting Recording Pipeline
For automated standup/meeting summarization:# 1. List recordings, filter by today's date (epoch ms)
zoho meeting recordings | jq --argjson start "$START_MS" --argjson end "$END_MS" \
'[.recordings[] | select(.startTimeinMs >= $start and .startTimeinMs <= $end)]'
# 2. Download recording
zoho meeting download "$DOWNLOAD_URL" /tmp/recording.mp4
# 3. Extract audio
ffmpeg -i /tmp/recording.mp4 -vn -acodec pcm_s16le -ar 16000 -ac 1 /tmp/audio.wav -y
# 4. Transcribe via Gemini Flash API (great for Arabic + English mix)
# See scripts/standup-summarizer.sh for full implementation
# 5. Summarize transcript with Claude/GPT
# 6. Clean up temp files
A complete standup summarizer script is included at scripts/standup-summarizer.sh.
Raw API Calls
For anything not covered by subcommands:
# CRM endpoints
zoho raw GET /crm/v7/settings/fields?module=Deals
zoho raw GET /crm/v7/org
# Meeting endpoints
zoho raw GET ""
# Custom modules
zoho raw GET /crm/v7/Custom_Module
Usage Patterns
When checking deals/pipeline
zoho crm list Deals "sort_by=Created_Time&sort_order=desc&per_page=10" | jq '.data[] | {Deal_Name, Stage, Amount, Closing_Date}'
When checking project progress
zoho proj list | jq '.projects[] | {name, status, id: .id_string}'
zoho proj tasks <project_id> | jq '.tasks[] | {name, status: .status.name, percent_complete, priority}'
When creating tasks from conversation
zoho proj create-task <project_id> "name=Task+description&priority=High&start_date=MM-DD-YYYY&end_date=MM-DD-YYYY"
When summarizing meeting recordings
# Quick list of recent recordings
zoho meeting recordings | jq '[.recordings[:5] | .[] | {topic, sDate, sTime, durationInMins, fileSize}]'
# Download latest recording
URL=$(zoho meeting recordings | jq -r '.recordings[0].downloadUrl')
zoho meeting download "$URL" /tmp/latest.mp4
Rate Limits
- CRM: 100 requests/min
- Projects: varies by plan
- Meeting: standard API limits
- Token refresh: don't call more than needed (cached automatically)
References
- CRM API Fields
- Projects API Endpoints
- Meeting API Reference