Zoho CRM uses OAuth 2.0 for API authentication. Every API request must include a valid access token in the Authorization header. Access tokens expire after one hour — your application refreshes them automatically using a refresh token, which does not expire unless revoked.
Set up OAuth credentials in Zoho’s API Console (api-console.zoho.com). Register your application, choose the appropriate client type (server-side, single-page or self-client for scripts and integrations) and note your Client ID and Client Secret. Then obtain your initial authorization code through the OAuth flow and exchange it for your first access and refresh tokens.
| # Python: Refresh an access token import requests TOKEN_URL = “https://accounts.zoho.com/oauth/v2/token” def refresh_access_token(client_id, client_secret, refresh_token): params = { “grant_type”: “refresh_token”, “client_id”: client_id, “client_secret”: client_secret, “refresh_token”: refresh_token, } response = requests.post(TOKEN_URL, params=params) return response.json()[“access_token”] |
|---|
With a valid access token, every API call follows the same structure: method, endpoint URL, Authorization header and (for POST/PUT requests) a JSON request body.
| # cURL: Get all Deals (first 200 records) curl -X GET \ “https://www.zohoapis.com/crm/v3/Deals” \ -H “Authorization: Zoho-oauthtoken YOUR_ACCESS_TOKEN” # Python: Get all Deals import requests BASE_URL = “https://www.zohoapis.com/crm/v3” HEADERS = {“Authorization”: f”Zoho-oauthtoken {access_token}”} response = requests.get(f”{BASE_URL}/Deals”, headers=HEADERS) data = response.json() # Records are in data[“data”] for deal in data[“data”]: print(deal[“Deal_Name”], deal[“Amount”]) |
|---|
The Zoho CRM API uses standard HTTP methods for CRUD operations:
| Operation | HTTP Method | Endpoint Example | What It Does |
|---|---|---|---|
| Create | POST | /crm/v3/Deals | Create one or more new records |
| Read | GET | /crm/v3/Deals/{id} | Fetch a single record by ID |
| Update | PUT | /crm/v3/Deals/{id} | Replace all fields on a record |
| Partial Update | PATCH | /crm/v3/Deals | Update specific fields only (recommended) |
| Delete | DELETE | /crm/v3/Deals?ids={id} | Delete one or more records by ID |
| Search | GET | /crm/v3/Deals/search?criteria=… | Query records by field values |
| # Python: Create a new Deal record deal_data = { “data”: [ { “Deal_Name”: “Acme Corp – Platform Licence”, “Amount”: 24000, “Stage”: “Proposal Sent”, “Close_Date”: “2026-06-30”, “Account_Name”: {“name”: “Acme Corp”} } ] } response = requests.post( f”{BASE_URL}/Deals”, headers={**HEADERS, “Content-Type”: “application/json”}, json=deal_data ) new_deal_id = response.json()[“data”][0][“details”][“id”] print(f”Created deal ID: {new_deal_id}”) # Python: Update specific fields (PATCH) update_data = { “data”: [{“id”: new_deal_id, “Stage”: “Negotiation”, “Amount”: 26000}] } requests.patch(f”{BASE_URL}/Deals”, headers=HEADERS, json=update_data) |
|---|
| # Python: Search for deals by criteria # Criteria format: (field:operator:value) params = { “criteria”: “(Stage:equals:Proposal Sent)”, “page”: 1, “per_page”: 200 } response = requests.get(f”{BASE_URL}/Deals/search”, headers=HEADERS, params=params) # Multiple criteria: AND / OR params[“criteria”] = (“(Stage:equals:Proposal Sent)” “and(Amount:greater_than:10000)”) # Available operators: # equals, not_equal, starts_with, ends_with # contains, between, greater_than, less_than # greater_equal, less_equal, is_empty, is_not_empty |
|---|
The Zoho CRM API returns a maximum of 200 records per request. For datasets larger than 200 records, paginate using the page and per_page parameters. To create or update records in bulk, include up to 100 records in a single POST or PATCH request body — this is significantly faster than one request per record for large data operations.
For the full API reference including webhooks, related records and metadata queries, see Zoho’s official API documentation. For building a complete integration using the API with error handling, retry logic and monitoring, see the Zoho system integration guide, or contact the ABR development team to scope a custom integration build.
| # Python: Paginate through all records def get_all_deals(access_token): all_deals = [] page = 1 while True: params = {“page”: page, “per_page”: 200} response = requests.get(f”{BASE_URL}/Deals”, headers=HEADERS, params=params) data = response.json() if “data” not in data: break # no more records all_deals.extend(data[“data”]) # Check if there are more pages if not data.get(“info”, {}).get(“more_records”, False): break page += 1 return all_deals |
|---|
What can the Zoho CRM REST API do?
How do I authenticate with the Zoho CRM REST API?
What is the difference between the Zoho CRM API v2 and v6?
Are there rate limits on the Zoho CRM REST API?
Can ABR build a custom integration using the Zoho CRM REST API?