Requirements
- Target platform
- OpenClaw
- Install method
- Manual import
- Extraction
- Extract archive
- Prerequisites
- OpenClaw
- Primary doc
- SKILL.md
Zoho CRM API integration with managed OAuth. Manage leads, contacts, accounts, deals, and other CRM records. Use this skill when users want to read, create,...
Zoho CRM API integration with managed OAuth. Manage leads, contacts, accounts, deals, and other CRM records. Use this skill when users want to read, create,...
Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.
I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete.
I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run.
Access the Zoho CRM API with managed OAuth authentication. Manage leads, contacts, accounts, deals, and other CRM modules with full CRUD operations including search and bulk operations. Also supports organization details, user management, and module metadata retrieval.
# List leads python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://gateway.maton.ai/zoho-crm/crm/v8/Leads?fields=First_Name,Last_Name,Email') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF
https://gateway.maton.ai/zoho-crm/crm/v8/{endpoint} The gateway proxies requests to www.zohoapis.com/crm/v8 and automatically injects your OAuth token.
All requests require the Maton API key in the Authorization header: Authorization: Bearer $MATON_API_KEY Environment Variable: Set your API key as MATON_API_KEY: export MATON_API_KEY="YOUR_API_KEY"
Sign in or create an account at maton.ai Go to maton.ai/settings Copy your API key
Manage your Zoho CRM OAuth connections at https://ctrl.maton.ai.
python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://ctrl.maton.ai/connections?app=zoho-crm&status=ACTIVE') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF
python <<'EOF' import urllib.request, os, json data = json.dumps({'app': 'zoho-crm'}).encode() req = urllib.request.Request('https://ctrl.maton.ai/connections', data=data, method='POST') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('Content-Type', 'application/json') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF
python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://ctrl.maton.ai/connections/{connection_id}') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF Response: { "connection": { "connection_id": "e55c5bac-241a-4cc8-9db5-50d2cad09136", "status": "ACTIVE", "creation_time": "2025-12-08T07:20:53.488460Z", "last_updated_time": "2026-01-31T20:03:32.593153Z", "url": "https://connect.maton.ai/?session_token=...", "app": "zoho-crm", "metadata": {} } } Open the returned url in a browser to complete OAuth authorization.
python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://ctrl.maton.ai/connections/{connection_id}', method='DELETE') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF
If you have multiple Zoho CRM connections, specify which one to use with the Maton-Connection header: python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://gateway.maton.ai/zoho-crm/crm/v8/Leads?fields=First_Name,Last_Name,Email') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('Maton-Connection', 'e55c5bac-241a-4cc8-9db5-50d2cad09136') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF If omitted, the gateway uses the default (oldest) active connection.
Zoho CRM organizes data into modules. Core modules include: ModuleAPI NameDescriptionLeadsLeadsPotential customersContactsContactsIndividual peopleAccountsAccountsOrganizations/companiesDealsDealsSales opportunitiesCampaignsCampaignsMarketing campaignsTasksTasksTo-do itemsCallsCallsPhone call logsEventsEventsCalendar appointmentsProductsProductsItems you sell
GET /zoho-crm/crm/v8/{module_api_name}?fields={field1},{field2} Query Parameters: ParameterTypeDescriptionfieldsstringRequired. Comma-separated field API names (max 50)pageintegerPage number (default: 1)per_pageintegerRecords per page (default/max: 200)sort_bystringSort by: id, Created_Time, or Modified_Timesort_orderstringasc or desc (default)cvidlongCustom view IDpage_tokenstringFor >2000 records pagination Example - List Leads: python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://gateway.maton.ai/zoho-crm/crm/v8/Leads?fields=First_Name,Last_Name,Email,Phone,Company') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF Response: { "data": [ { "First_Name": "Christopher", "Email": "christopher-maclead@noemail.invalid", "Last_Name": "Maclead (Sample)", "Phone": "555-555-5555", "Company": "Rangoni Of Florence", "id": "7243485000000597000" } ], "info": { "per_page": 200, "count": 1, "page": 1, "sort_by": "id", "sort_order": "desc", "more_records": false, "next_page_token": null } } Example - List Contacts: python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://gateway.maton.ai/zoho-crm/crm/v8/Contacts?fields=First_Name,Last_Name,Email,Phone') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF Example - List Accounts: python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://gateway.maton.ai/zoho-crm/crm/v8/Accounts?fields=Account_Name,Website,Phone') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF Example - List Deals: python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://gateway.maton.ai/zoho-crm/crm/v8/Deals?fields=Deal_Name,Stage,Amount') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF
GET /zoho-crm/crm/v8/{module_api_name}/{record_id} Example: python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://gateway.maton.ai/zoho-crm/crm/v8/Leads/7243485000000597000') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF
POST /zoho-crm/crm/v8/{module_api_name} Content-Type: application/json { "data": [ { "field_api_name": "value" } ] } Mandatory Fields by Module: ModuleRequired FieldsLeadsLast_NameContactsLast_NameAccountsAccount_NameDealsDeal_Name, StageTasksSubjectCallsSubject, Call_Type, Call_Start_Time, Call_DurationEventsEvent_Title, Start_DateTime, End_DateTime Example - Create Lead: python <<'EOF' import urllib.request, os, json data = json.dumps({ "data": [{ "Last_Name": "Smith", "First_Name": "John", "Email": "john.smith@example.com", "Company": "Acme Corp", "Phone": "+1-555-0123" }] }).encode() req = urllib.request.Request('https://gateway.maton.ai/zoho-crm/crm/v8/Leads', data=data, method='POST') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('Content-Type', 'application/json') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF Response: { "data": [ { "code": "SUCCESS", "details": { "Modified_Time": "2026-02-06T01:10:56-08:00", "Modified_By": { "name": "User Name", "id": "7243485000000590001" }, "Created_Time": "2026-02-06T01:10:56-08:00", "id": "7243485000000619001", "Created_By": { "name": "User Name", "id": "7243485000000590001" } }, "message": "record added", "status": "success" } ] } Example - Create Contact: python <<'EOF' import urllib.request, os, json data = json.dumps({ "data": [{ "Last_Name": "Doe", "First_Name": "Jane", "Email": "jane.doe@example.com", "Phone": "+1-555-9876" }] }).encode() req = urllib.request.Request('https://gateway.maton.ai/zoho-crm/crm/v8/Contacts', data=data, method='POST') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('Content-Type', 'application/json') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF Example - Create Account: python <<'EOF' import urllib.request, os, json data = json.dumps({ "data": [{ "Account_Name": "Acme Corporation", "Website": "https://acme.com", "Phone": "+1-555-1234" }] }).encode() req = urllib.request.Request('https://gateway.maton.ai/zoho-crm/crm/v8/Accounts', data=data, method='POST') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('Content-Type', 'application/json') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF
PUT /zoho-crm/crm/v8/{module_api_name} Content-Type: application/json { "data": [ { "id": "record_id", "field_api_name": "updated_value" } ] } Example: python <<'EOF' import urllib.request, os, json data = json.dumps({ "data": [{ "id": "7243485000000619001", "Phone": "+1-555-9999", "Company": "Updated Company Name" }] }).encode() req = urllib.request.Request('https://gateway.maton.ai/zoho-crm/crm/v8/Leads', data=data, method='PUT') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('Content-Type', 'application/json') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF Response: { "data": [ { "code": "SUCCESS", "details": { "Modified_Time": "2026-02-06T01:11:01-08:00", "Modified_By": { "name": "User Name", "id": "7243485000000590001" }, "Created_Time": "2026-02-06T01:10:56-08:00", "id": "7243485000000619001", "Created_By": { "name": "User Name", "id": "7243485000000590001" } }, "message": "record updated", "status": "success" } ] }
DELETE /zoho-crm/crm/v8/{module_api_name}?ids={record_id1},{record_id2} Query Parameters: ParameterTypeDescriptionidsstringComma-separated record IDs (required, max 100)wf_triggerbooleanExecute workflows (default: true) Example: python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://gateway.maton.ai/zoho-crm/crm/v8/Leads?ids=7243485000000619001', method='DELETE') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF Response: { "data": [ { "code": "SUCCESS", "details": { "id": "7243485000000619001" }, "message": "record deleted", "status": "success" } ] }
GET /zoho-crm/crm/v8/{module_api_name}/search Query Parameters (one required): ParameterTypeDescriptioncriteriastringSearch criteria (e.g., (Last_Name:equals:Smith))emailstringSearch by email addressphonestringSearch by phone numberwordstringGlobal text searchpageintegerPage numberper_pageintegerRecords per page (max 200) Criteria Format: ((field_api_name:operator:value) and/or (...)) Operators: Text fields: equals, not_equal, starts_with, in Date/Number fields: equals, not_equal, greater_than, less_than, between, in Boolean fields: equals, not_equal Example - Search by email: python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://gateway.maton.ai/zoho-crm/crm/v8/Leads/search?email=christopher-maclead@noemail.invalid') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF Example - Search by criteria: python <<'EOF' import urllib.request, os, json import urllib.parse criteria = urllib.parse.quote('(Last_Name:starts_with:Smith)') req = urllib.request.Request(f'https://gateway.maton.ai/zoho-crm/crm/v8/Leads/search?criteria={criteria}') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF Response: { "data": [ { "First_Name": "Christopher", "Email": "christopher-maclead@noemail.invalid", "Last_Name": "Maclead (Sample)", "id": "7243485000000597000" } ], "info": { "per_page": 200, "count": 1, "page": 1, "more_records": false } }
Retrieve your Zoho CRM organization details. GET /zoho-crm/crm/v8/org Example: python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://gateway.maton.ai/zoho-crm/crm/v8/org') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF Response: { "org": [ { "id": "7243485000000020005", "company_name": "Acme Corp", "domain_name": "org123456789", "primary_email": "admin@example.com", "phone": "555-555-5555", "currency": "US Dollar - USD", "currency_symbol": "$", "iso_code": "USD", "time_zone": "PST", "country_code": "US", "zgid": "123456789", "type": "production", "mc_status": false, "license_details": { "paid": true, "paid_type": "enterprise", "users_license_purchased": 10, "trial_expiry": null } } ] }
Retrieve users in your Zoho CRM organization. GET /zoho-crm/crm/v8/users Query Parameters: ParameterTypeDescriptiontypestringFilter by user type: AllUsers, ActiveUsers, DeactiveUsers, ConfirmedUsers, NotConfirmedUsers, DeletedUsers, ActiveConfirmedUsers, AdminUsers, ActiveConfirmedAdmins, CurrentUserpageintegerPage number (default: 1)per_pageintegerRecords per page (default/max: 200)idsstringComma-separated user IDs (max 100) Example - List all users: python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://gateway.maton.ai/zoho-crm/crm/v8/users?type=AllUsers') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF Response: { "users": [ { "id": "7243485000000590001", "first_name": "John", "last_name": "Doe", "full_name": "John Doe", "email": "john.doe@example.com", "status": "active", "confirm": true, "role": { "name": "CEO", "id": "7243485000000026005" }, "profile": { "name": "Administrator", "id": "7243485000000026011" }, "time_zone": "PST", "country": "US", "locale": "en_US" } ], "info": { "per_page": 200, "count": 1, "page": 1, "more_records": false } } Example - Get specific user: python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://gateway.maton.ai/zoho-crm/crm/v8/users/7243485000000590001') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF
Retrieve metadata about all available CRM modules. GET /zoho-crm/crm/v8/settings/modules Query Parameters: ParameterTypeDescriptionstatusstringFilter by status: user_hidden, system_hidden, scheduled_for_deletion, visible Example: python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://gateway.maton.ai/zoho-crm/crm/v8/settings/modules') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF Response: { "modules": [ { "api_name": "Leads", "module_name": "Leads", "singular_label": "Lead", "plural_label": "Leads", "api_supported": true, "creatable": true, "editable": true, "deletable": true, "viewable": true, "status": "visible", "generated_type": "default", "id": "7243485000000002175", "profiles": [ {"name": "Administrator", "id": "7243485000000026011"} ] } ] }
Retrieve field metadata for a specific module. GET /zoho-crm/crm/v8/settings/fields?module={module_api_name} Query Parameters: ParameterTypeDescriptionmodulestringRequired. API name of the module (e.g., Leads, Contacts)typestringall for all fields, unused for unused fields only Example: python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://gateway.maton.ai/zoho-crm/crm/v8/settings/fields?module=Leads') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF Response: { "fields": [ { "api_name": "Last_Name", "field_label": "Last Name", "data_type": "text", "system_mandatory": true, "custom_field": false, "visible": true, "searchable": true, "sortable": true, "id": "7243485000000002613" } ] }
Retrieve layout metadata for a specific module. GET /zoho-crm/crm/v8/settings/layouts?module={module_api_name} Query Parameters: ParameterTypeDescriptionmodulestringRequired. API name of the module (e.g., Leads, Contacts) Example: python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://gateway.maton.ai/zoho-crm/crm/v8/settings/layouts?module=Leads') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF Response: { "layouts": [ { "id": "7243485000000091055", "name": "Standard", "api_name": "Standard", "status": "active", "visible": true, "profiles": [ {"name": "Administrator", "id": "7243485000000026011"} ], "sections": [ { "display_label": "Lead Information", "api_name": "Lead_Information", "sequence_number": 1, "fields": [...] } ] } ] }
Retrieve roles in your Zoho CRM organization. GET /zoho-crm/crm/v8/settings/roles Example: python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://gateway.maton.ai/zoho-crm/crm/v8/settings/roles') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF Response: { "roles": [ { "id": "7243485000000026005", "name": "CEO", "display_label": "CEO", "share_with_peers": true, "description": null, "reporting_to": null }, { "id": "7243485000000026008", "name": "Manager", "display_label": "Manager", "share_with_peers": false, "reporting_to": { "name": "CEO", "id": "7243485000000026005" } } ] } Example - Get specific role: python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://gateway.maton.ai/zoho-crm/crm/v8/settings/roles/7243485000000026005') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF
Retrieve profiles (permission sets) in your Zoho CRM organization. GET /zoho-crm/crm/v8/settings/profiles Example: python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://gateway.maton.ai/zoho-crm/crm/v8/settings/profiles') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF Response: { "profiles": [ { "id": "7243485000000026011", "name": "Administrator", "display_label": "Administrator", "type": "normal_profile", "custom": false, "description": null }, { "id": "7243485000000026014", "name": "Standard", "display_label": "Standard", "type": "normal_profile", "custom": false, "description": null } ] } Example - Get specific profile: python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://gateway.maton.ai/zoho-crm/crm/v8/settings/profiles/7243485000000026011') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF
Zoho CRM uses page-based pagination with optional page tokens for large datasets: GET /zoho-crm/crm/v8/{module_api_name}?fields=First_Name,Last_Name&page=1&per_page=50 Response includes pagination info: { "data": [...], "info": { "per_page": 50, "count": 50, "page": 1, "sort_by": "id", "sort_order": "desc", "more_records": true, "next_page_token": "token_value", "page_token_expiry": "2026-02-07T01:10:56-08:00" } } For up to 2,000 records: Use page parameter (increment each request) For 2,000+ records: Use page_token from previous response Page tokens expire after 24 hours
const response = await fetch( 'https://gateway.maton.ai/zoho-crm/crm/v8/Leads?fields=First_Name,Last_Name,Email', { headers: { 'Authorization': `Bearer ${process.env.MATON_API_KEY}` } } ); const data = await response.json();
import os import requests response = requests.get( 'https://gateway.maton.ai/zoho-crm/crm/v8/Leads', headers={'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'}, params={'fields': 'First_Name,Last_Name,Email'} ) data = response.json()
The fields parameter is required for list operations (max 50 fields) Module API names are case-sensitive (e.g., Leads, not leads) Maximum 100 records per create/update request Maximum 100 records per delete request Maximum 200 records returned per GET request Maximum 2,000 records without page_token; up to 100,000 with page_token Use field API names (not display names) in requests If you receive a scope error, contact Maton support at support@maton.ai with the specific operations/APIs you need and your use-case Empty datasets return HTTP 204 (No Content) with empty body IMPORTANT: When using curl commands, use curl -g when URLs contain brackets to disable glob parsing IMPORTANT: When piping curl output to jq or other commands, environment variables like $MATON_API_KEY may not expand correctly in some shell environments
StatusMeaning400Missing Zoho CRM connection, missing required parameter, or invalid request401Invalid or missing Maton API key, or OAuth scope mismatch404Resource not found429Rate limited4xx/5xxPassthrough error from Zoho CRM API
CodeDescriptionOAUTH_SCOPE_MISMATCHOAuth token lacks required permissions for the endpointMANDATORY_NOT_FOUNDRequired field is missingINVALID_DATAData type mismatch or format errorDUPLICATE_DATARecord violates unique field constraintRECORD_NOT_FOUNDThe specified record ID does not exist
Check that the MATON_API_KEY environment variable is set: echo $MATON_API_KEY Verify the API key is valid by listing connections: python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://ctrl.maton.ai/connections') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF
Ensure your URL path starts with zoho-crm. For example: Correct: https://gateway.maton.ai/zoho-crm/crm/v8/Leads Incorrect: https://gateway.maton.ai/crm/v8/Leads
Zoho CRM API v8 Documentation Get Records API Insert Records API Update Records API Delete Records API Search Records API Organization API Users API Modules API Fields API Layouts API Roles API Profiles API Maton Community Maton Support
Code helpers, APIs, CLIs, browser automation, testing, and developer operations.
Largest current source with strong distribution and engagement signals.