Zoho Books/Inventory/CRM REST API Capabilities and Rate Limits
Type: ERP Integration
System: Zoho Books (API v3), Zoho Inventory (API v1), Zoho CRM (API v7/v8)
Confidence: 0.91
Sources: 8
Verified: 2026-03-02
Freshness: 2026-03-02
TL;DR
- Bottom line: Zoho Books (API v3) and Inventory (API v1) share a simple 100 requests/minute rate limit with daily caps by plan; Zoho CRM (API v7/v8) uses a credit-based system with concurrent call limits instead of per-minute caps. All three use OAuth 2.0 with 1-hour access tokens.
- Key limit: Zoho Books/Inventory hard cap at 100 requests/minute/org with daily limits ranging from 1,000 (Free) to 10,000 (Premium+). Zoho CRM caps at 5,000 credits/day (Free) to unlimited (Ultimate/CRM Plus) with concurrent limits of 5-25 simultaneous calls.
- Watch out for: Each Zoho product has independent API limits — Books, Inventory, and CRM quotas do not share pools. The 100/min Books/Inventory limit cannot be increased by upgrading to a higher plan.
- Best for: SMB integrations with < 10,000 daily transactions across accounting, inventory, and CRM. For high-volume enterprise integrations, Zoho CRM's Bulk API (async, credit-based) is the only option exceeding per-minute caps.
- Authentication: OAuth 2.0 via Zoho accounts server. Self Client (client_credentials) for server-to-server; Authorization Code for user-context. Access tokens last 1 hour; refresh tokens do not expire.
System Profile
This card covers the REST APIs for three core Zoho business applications — Zoho Books (accounting), Zoho Inventory (warehouse and order management), and Zoho CRM (customer relationship management). These three products share Zoho's OAuth 2.0 authentication infrastructure but have entirely separate API endpoints, rate limits, and capabilities. This card does NOT cover Zoho People, Zoho Desk, Zoho Projects, or other Zoho One suite products.
| System | API Version | Base URL | API Docs |
| Zoho Books | v3 | https://www.zohoapis.com/books/v3 | Books API v3 |
| Zoho Inventory | v1 | https://www.zohoapis.com/inventory/v1 | Inventory API v1 |
| Zoho CRM | v7/v8 | https://www.zohoapis.com/crm/v7 or /v8 | CRM API v8 |
API Surfaces & Capabilities
| API Surface | Protocol | Best For | Max Records/Request | Rate Limit | Real-time? | Bulk? |
| Zoho Books REST v3 | HTTPS/JSON | Invoices, expenses, banking, contacts, accounting | 200 per page | 100 req/min + daily cap | Yes | No |
| Zoho Inventory REST v1 | HTTPS/JSON | Items, sales/purchase orders, packages, shipments | 200 per page | 100 req/min + daily cap | Yes | No |
| Zoho CRM REST v7/v8 | HTTPS/JSON | Leads, contacts, deals, accounts, modules CRUD | 200 (GET), 100 (write) | Credit-based + concurrency | Yes | No |
| Zoho CRM Bulk API | HTTPS/CSV | Data migration, backup, batch sync > 2K records | 25,000 per file | 50/500 credits per job | No (async) | Yes |
| Zoho CRM COQL | HTTPS/JSON | Complex record queries with joins and conditions | 200-2,000 per query | 1-3 credits per query | Yes | No |
| Zoho CRM Notifications | HTTPS/JSON | Real-time record change notifications | N/A | Included in CRM limits | Yes | N/A |
| Zoho CRM Webhooks | HTTPS/JSON | Event-driven outbound notifications | N/A | Workflow-triggered | Yes | N/A |
Rate Limits & Quotas
Per-Request Limits
| Limit Type | Value | Applies To | Notes |
| Max records per GET (Books/Inventory) | 200 per page | List endpoints | Use page and per_page parameters |
| Max records per GET (CRM) | 200 per request | Get Records API | Use page token for pagination |
| Max records per write (CRM) | 100 per request | Insert/Update/Upsert | Each 10 records = 1 credit |
| Max COQL query results | 200-2,000 | CRM COQL API | 1-3 credits depending on limit |
| Max bulk file size (CRM) | 25,000 records per CSV | Bulk Read/Write API | Async processing |
Zoho Books & Inventory — Rolling / Daily Limits
| Plan | Daily Limit | Per-Minute Limit | Concurrent Calls |
| Free | 1,000 requests/day | 100/min | 5 |
| Standard | 2,000 requests/day | 100/min | 10 |
| Professional | 5,000 requests/day | 100/min | 10 |
| Premium / Elite / Ultimate (Books) | 10,000 requests/day | 100/min | 10 |
| Premium / Enterprise (Inventory) | 10,000 requests/day | 100/min | 10 |
Zoho CRM — Credit-Based System (24h Rolling Window)
| Edition | Base Credits | Per-User Credits | Max Credits/24h | Concurrent Calls | Sub-Concurrency |
| Free | 5,000 | — | 5,000 | 5 | 10 |
| Standard/Starter | 50,000 | +250/user | 100,000 | 10 | 10 |
| Professional | 50,000 | +500/user | 3,000,000 | 15 | 10 |
| Enterprise/Zoho One | 50,000 | +1,000/user | 5,000,000 | 20 | 10 |
| Ultimate/CRM Plus | 50,000 | +2,000/user | Unlimited | 25 | 10 |
CRM API Credit Costs
| Operation | Credit Cost | Notes |
| Standard metadata/user retrieval | 1 credit | Org info, users, roles, profiles |
| Get Records (standard) | 1 credit | Up to 200 records |
| Get Records via COQL (1-200) | 1 credit | Query language interface |
| Get Records via COQL (201-1,000) | 2 credits | Higher page sizes cost more |
| Get Records via COQL (1,001-2,000) | 3 credits | Maximum COQL page size |
| Insert/Update/Upsert | 1 credit per 10 records | Bulk within single request |
| Convert Lead | 5 credits | Creates Contact + Account + Deal |
| Send Mail | 20 credits | Email operations are expensive |
| Merge Records | 50 credits | Deduplication merges |
| Bulk Read Initialize | 50 credits | Async bulk export job |
| Bulk Write Initialize | 500 credits | Async bulk import job |
| Mass Convert Leads | 200 credits | Batch lead conversion |
Authentication
All Zoho APIs authenticate via OAuth 2.0 through Zoho's accounts server. The token endpoint varies by data center region. [src5]
| Flow | Use When | Token Lifetime | Refresh? | Notes |
| Self Client — Client Credentials | Server-to-server, backend jobs | Access: 1 hour | No refresh token; request new each hour | Recommended for integrations. grant_type=client_credentials |
| Self Client — Authorization Code | Backend scripts with user scopes | Access: 1 hour; Refresh: never expires | Yes — permanent refresh token | Generate code in API Console (3-min expiry) |
| Server-based App — Auth Code | Web apps with user interaction | Access: 1 hour; Refresh: never expires | Yes | Standard OAuth 2.0 with redirect URI |
| Client-side App | SPAs and mobile apps | Access: 1 hour | Limited | Uses implicit or PKCE flow |
Regional Token Endpoints
| Data Center | Accounts Server URL |
| US (.com) | https://accounts.zoho.com/oauth/v2/token |
| EU (.eu) | https://accounts.zoho.eu/oauth/v2/token |
| India (.in) | https://accounts.zoho.in/oauth/v2/token |
| Australia (.com.au) | https://accounts.zoho.com.au/oauth/v2/token |
| Japan (.jp) | https://accounts.zoho.jp/oauth/v2/token |
| Canada (.ca) | https://accounts.zohocloud.ca/oauth/v2/token |
| China (.com.cn) | https://accounts.zoho.com.cn/oauth/v2/token |
| Saudi Arabia (.sa) | https://accounts.zoho.sa/oauth/v2/token |
Authentication Gotchas
- Authorization header format is non-standard: Zoho uses
Authorization: Zoho-oauthtoken {access_token} instead of the standard Bearer prefix for Books and Inventory APIs. CRM v7/v8 accepts both. [src3]
- Organization ID required on every Books/Inventory call: Every request must include
organization_id as a query parameter. Forgetting this returns a confusing generic error. [src3]
- Scopes are product-specific: Books uses
ZohoBooks.{module}.{permission}, Inventory uses ZohoInventory.{module}.{permission}, CRM uses ZohoCRM.{module}.{permission}. Cross-product scopes must be comma-separated. [src5]
- Client credentials flow returns no refresh token: For
grant_type=client_credentials, you get only a 1-hour access token. Use authorization code flow for permanent refresh tokens. [src5]
- Data center mismatch causes silent auth failures: If your org is on EU but you hit the US token endpoint, authentication succeeds but API calls fail with 401 or wrong-org data. [src5]
Constraints
- 100 requests/minute is a hard cap for Books and Inventory — cannot be increased by upgrading plans. Only the daily cap scales.
- Zoho CRM has no per-minute limit but has concurrent call caps — rate limiting is based on simultaneous connections (5-25) and daily credit budgets.
- Sub-concurrency limit of 10 applies to all CRM editions — resource-intensive operations share a fixed pool of 10.
- Books/Inventory APIs have no bulk endpoint — unlike CRM, all operations are synchronous and subject to the 100/min limit.
- Cross-product API calls consume independent quotas — reading from CRM and writing to Books consumes both quotas independently.
- Zoho CRM API v2.1 is on deprecation path — new features are v8-exclusive. No formal EOL date announced.
- Webhook payload size limit — CRM webhook payloads are limited to 1 MB.
- Access tokens expire after exactly 1 hour — no configurable lifetime across any Zoho product.
Integration Pattern Decision Tree
START — User needs to integrate with Zoho Books, Inventory, or CRM
├── Which Zoho product?
│ ├── Zoho Books (accounting)
│ │ ├── Daily volume < 1,000 records? → REST API (any plan)
│ │ ├── Need real-time sync? → REST API with 100/min throttling
│ │ └── Need >10K ops/day? → Not possible via API — use CSV import
│ ├── Zoho Inventory (warehouse/orders)
│ │ └── Same limits as Books (100/min, daily cap by plan)
│ └── Zoho CRM (customer data)
│ ├── < 2K records/op? → REST API with credit tracking
│ ├── > 2K records? → Bulk API (async CSV)
│ ├── Complex queries? → COQL API (SQL-like, 200-2K results)
│ └── Need notifications? → Webhooks or Notification API
├── Authentication type?
│ ├── Server-to-server → Self Client: client_credentials
│ ├── Backend + user context → Self Client: authorization code
│ └── Web/mobile app → Server-based or client-side flow
└── Error tolerance?
├── Zero-loss → retry queue + dead letter + idempotency
└── Best-effort → retry on 429 with exponential backoff
Quick Reference
Zoho Books API v3 — Key Endpoints
| Operation | Method | Endpoint | Notes |
| List invoices | GET | /books/v3/invoices?organization_id={org_id} | Paginated, 200/page max |
| Create invoice | POST | /books/v3/invoices?organization_id={org_id} | JSON body with line items |
| Get invoice | GET | /books/v3/invoices/{invoice_id}?organization_id={org_id} | Single record |
| Update invoice | PUT | /books/v3/invoices/{invoice_id}?organization_id={org_id} | Full or partial update |
| Delete invoice | DELETE | /books/v3/invoices/{invoice_id}?organization_id={org_id} | Soft delete |
| List contacts | GET | /books/v3/contacts?organization_id={org_id} | Customers and vendors |
| List items | GET | /books/v3/items?organization_id={org_id} | Products/services |
| List expenses | GET | /books/v3/expenses?organization_id={org_id} | Expense records |
Zoho Inventory API v1 — Key Endpoints
| Operation | Method | Endpoint | Notes |
| List items | GET | /inventory/v1/items?organization_id={org_id} | Product catalog |
| Create item | POST | /inventory/v1/items?organization_id={org_id} | With variants support |
| List sales orders | GET | /inventory/v1/salesorders?organization_id={org_id} | Sales pipeline |
| List purchase orders | GET | /inventory/v1/purchaseorders?organization_id={org_id} | Procurement |
| List packages | GET | /inventory/v1/packages?organization_id={org_id} | Shipment packaging |
| List transfer orders | GET | /inventory/v1/transferorders?organization_id={org_id} | Inter-warehouse |
Zoho CRM API v7/v8 — Key Endpoints
| Operation | Method | Endpoint | Credits | Notes |
| Get records | GET | /crm/v7/{module} | 1 | Max 200 records/page |
| Create records | POST | /crm/v7/{module} | 1 per 10 records | Max 100 records/request |
| Update records | PUT | /crm/v7/{module} | 1 per 10 records | Max 100 records/request |
| Upsert records | POST | /crm/v7/{module}/upsert | 1 per 10 records | Deduplicate on unique fields |
| Search records | GET | /crm/v7/{module}/search | 1 | Criteria-based search |
| COQL query | POST | /crm/v7/coql | 1-3 | SQL-like queries |
| Bulk read | POST | /crm/v7/bulk-read | 50 | Async CSV export |
| Bulk write | POST | /crm/v7/bulk-write | 500 | Async CSV import |
| Convert lead | POST | /crm/v7/Leads/{id}/actions/convert | 5 | Creates Contact + Account + Deal |
Step-by-Step Integration Guide
1. Register a Self Client in Zoho API Console
Navigate to Zoho API Console and create a Self Client. Copy the Client ID and Client Secret. [src5]
# No CLI — use Zoho API Console (https://api-console.zoho.com/)
# Record: Client ID, Client Secret, Data center domain
Verify: Client ID and Client Secret appear in API Console under Self Client > Client Secret tab.
2. Generate access token using client credentials flow
For server-to-server integrations, use the client_credentials grant type. [src5]
curl -X POST "https://accounts.zoho.com/oauth/v2/token" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET" \
-d "grant_type=client_credentials" \
-d "scope=ZohoBooks.invoices.READ,ZohoInventory.items.READ,ZohoCRM.modules.READ" \
-d "soid=ZohoBooks.{zsoid}"
Verify: Response contains access_token and expires_in: 3600.
3. Call Zoho Books API — list organizations
Retrieve your organization ID, required on every subsequent Books/Inventory API call. [src3]
curl -s "https://www.zohoapis.com/books/v3/organizations" \
-H "Authorization: Zoho-oauthtoken YOUR_ACCESS_TOKEN"
Verify: Response code is 0 and organizations array is non-empty.
4. Implement rate-limited API calls with retry logic
Wrap all calls with rate limit awareness. Books/Inventory return 429 when exceeding 100/min or daily caps. [src6]
import time, requests
class ZohoRateLimiter:
def __init__(self, access_token, org_id, base_url="https://www.zohoapis.com"):
self.token = access_token
self.org_id = org_id
self.base_url = base_url
self.headers = {
"Authorization": f"Zoho-oauthtoken {access_token}",
"Content-Type": "application/json"
}
def request(self, method, endpoint, max_retries=5, **kwargs):
url = f"{self.base_url}{endpoint}"
params = kwargs.pop("params", {})
params["organization_id"] = self.org_id
for attempt in range(max_retries):
resp = requests.request(method, url, headers=self.headers, params=params, **kwargs)
if resp.status_code == 429:
wait = min(2 ** attempt * 2, 60)
time.sleep(wait)
continue
return resp.json()
raise Exception("Max retries exceeded")
Verify: Calling limiter.request("GET", "/books/v3/invoices") returns JSON with code: 0.
Code Examples
Python: Sync Zoho Books invoices with pagination
# Input: access_token, organization_id
# Output: All invoices from Zoho Books (paginated)
import requests, time
TOKEN = "YOUR_ACCESS_TOKEN"
ORG_ID = "YOUR_ORG_ID"
BASE = "https://www.zohoapis.com/books/v3"
headers = {"Authorization": f"Zoho-oauthtoken {TOKEN}"}
def get_all_invoices():
all_invoices, page, has_more = [], 1, True
while has_more:
resp = requests.get(f"{BASE}/invoices", headers=headers,
params={"organization_id": ORG_ID, "page": page, "per_page": 200})
if resp.status_code == 429:
time.sleep(60); continue
data = resp.json()
all_invoices.extend(data.get("invoices", []))
has_more = data.get("page_context", {}).get("has_more_page", False)
page += 1; time.sleep(0.6) # stay under 100/min
return all_invoices
JavaScript/Node.js: Create CRM records with credit tracking
// Input: access_token, module name, records array
// Output: Created record IDs with credit usage estimate
// npm install axios@1
const axios = require("axios");
const TOKEN = process.env.ZOHO_ACCESS_TOKEN;
async function createRecords(module, records) {
const chunks = [];
for (let i = 0; i < records.length; i += 100) chunks.push(records.slice(i, i + 100));
const results = []; let totalCredits = 0;
for (const chunk of chunks) {
try {
const resp = await axios.post(`https://www.zohoapis.com/crm/v7/${module}`,
{ data: chunk },
{ headers: { Authorization: `Zoho-oauthtoken ${TOKEN}`, "Content-Type": "application/json" } });
results.push(...resp.data.data);
totalCredits += Math.ceil(chunk.length / 10);
} catch (err) {
if (err.response?.status === 429) { await new Promise(r => setTimeout(r, 5000)); continue; }
throw err;
}
}
console.log(`Created ${results.length} records, ~${totalCredits} credits`);
return results;
}
cURL: Quick API test across all three products
# Input: access_token, organization_id
# Output: Verification that auth works for all three APIs
TOKEN="YOUR_ACCESS_TOKEN"; ORG_ID="YOUR_ORG_ID"
# Test Zoho Books
curl -s "https://www.zohoapis.com/books/v3/organizations" \
-H "Authorization: Zoho-oauthtoken $TOKEN" | python3 -m json.tool
# Test Zoho Inventory
curl -s "https://www.zohoapis.com/inventory/v1/items?organization_id=$ORG_ID" \
-H "Authorization: Zoho-oauthtoken $TOKEN" | python3 -m json.tool
# Test Zoho CRM
curl -s "https://www.zohoapis.com/crm/v7/org" \
-H "Authorization: Zoho-oauthtoken $TOKEN" | python3 -m json.tool
Data Mapping
Cross-Product Field Mapping (Books <-> Inventory <-> CRM)
| Books Field | Inventory Field | CRM Field | Type | Gotcha |
| contact_name | contact_name | Account_Name | String | CRM uses Account module; Books/Inventory use Contacts — different entity model |
| customer_id | contact_id | id | String (ID) | IDs are not shared across products — maintain cross-reference mapping |
| line_items[].item_id | line_items[].item_id | Product_Details[].product.id | String (ID) | Item IDs sync between Books and Inventory but NOT with CRM Products |
| total | total | Amount | Decimal | Currency formatting differs by product |
| date | date | Closing_Date | Date | All use YYYY-MM-DD but CRM datetime includes timezone offset |
| status | status | Stage | String (enum) | Status values differ completely — must map explicitly |
| currency_code | currency_code | Currency | ISO 4217 | Multi-currency must be enabled independently in each product |
Data Type Gotchas
- Entity IDs are product-scoped: A contact ID in Books is completely different from the same contact's ID in CRM. Maintain a cross-reference table. [src3]
- Date/datetime format inconsistency: Books and Inventory use YYYY-MM-DD. CRM uses YYYY-MM-DDTHH:mm:ss+HH:MM for datetime fields. [src3]
- Multi-currency handling differs: Exchange rates are maintained independently in each product — they do not sync even in Zoho One. [src3]
Error Handling & Failure Points
Common Error Codes
| Code | HTTP Status | Meaning | Resolution |
| 44 | 429 | Per-minute rate limit exceeded | Wait 60 seconds. Implement 600ms minimum gap between requests. |
| 45 | 429 | Daily rate limit exceeded | Wait until next day or upgrade plan. |
| 1070 | 429 | Concurrent call limit exceeded | Reduce parallelism. Free: max 5, Paid: max 10. |
| 1000 | 500 | Internal server error | Retry with exponential backoff. |
| 1002 | 404 | Resource not found | Verify resource ID. Check if record deleted. |
| — | 401 | Unauthorized | Refresh token. Verify Zoho-oauthtoken prefix. |
| INVALID_DATA | 400 | Malformed request body | Validate against API docs. |
Failure Points in Production
- Token expiry mid-batch: Access tokens expire after 1 hour. A batch processing 10K records at 100/min takes ~100 minutes. Fix:
Request new token every 50 minutes proactively. [src5]
- Organization ID missing causes cryptic errors: Books/Inventory return generic errors when organization_id is omitted. Fix:
Always include organization_id. Store as config constant. [src3]
- Data center mismatch after org migration: Hardcoded API URLs break if Zoho migrates your org. Fix:
Use api_domain from token response, not hardcoded URLs. [src5]
- Webhook delivery failures are not retried: CRM webhooks have no built-in retry. Fix:
Log deliveries. Run reconciliation job to detect missed webhooks. [src8]
- Concurrent limit hit during parallel processing: Running 15 threads against Standard CRM (10 concurrent limit) causes 429 errors. Fix:
Use semaphore matching edition's concurrent limit. [src2]
Anti-Patterns
Wrong: Ignoring rate limits — sending requests as fast as possible
# BAD — will hit 100/min limit on Books/Inventory almost immediately
for invoice in invoices:
requests.post(f"{BASE}/invoices", headers=headers, json=invoice, params={"organization_id": org_id})
Correct: Implement request throttling with minimum gap
# GOOD — 600ms gap ensures < 100 requests/min for Books/Inventory
import time
for invoice in invoices:
requests.post(f"{BASE}/invoices", headers=headers, json=invoice, params={"organization_id": org_id})
time.sleep(0.6) # 600ms gap = max 100 requests/min
Wrong: Using Bearer prefix for Zoho Books/Inventory
# BAD — Books/Inventory require "Zoho-oauthtoken" prefix, not "Bearer"
curl -H "Authorization: Bearer 1000.xxxx" \
"https://www.zohoapis.com/books/v3/invoices?organization_id=12345"
Correct: Use Zoho-oauthtoken prefix
# GOOD — correct authorization header format
curl -H "Authorization: Zoho-oauthtoken 1000.xxxx" \
"https://www.zohoapis.com/books/v3/invoices?organization_id=12345"
Wrong: Hardcoding US data center domain for all orgs
# BAD — breaks for EU, India, Australia, Japan orgs
BASE_URL = "https://www.zohoapis.com"
TOKEN_URL = "https://accounts.zoho.com/oauth/v2/token"
Correct: Use data center domain from configuration
# GOOD — data center domain from config
import os
DC = os.environ.get("ZOHO_DC", "com") # com, eu, in, com.au, jp, ca
BASE_URL = f"https://www.zohoapis.{DC}"
TOKEN_URL = f"https://accounts.zoho.{DC}/oauth/v2/token"
Common Pitfalls
- Assuming all Zoho APIs share rate limits: Books, Inventory, and CRM have independent pools. Track limits separately. Fix:
Implement per-product rate limit tracking. [src1]
- Not accounting for CRM credit costs: A single Bulk Write costs 500 credits. 10 bulk imports on Free plan (5K credits) exhausts the budget. Fix:
Calculate credit costs before operations. Log cumulative usage. [src2]
- Using CRM API v2.1 for new integrations: V2.1 receives no new features. Fix:
Start new integrations on v7 or v8. [src7]
- Forgetting the soid parameter in client_credentials: For multi-org setups, omitting soid defaults to primary org. Fix:
Include soid={servicename}.{zsoid} in every token request. [src5]
- Not handling pagination: Both Books/Inventory (200/page) and CRM (200/page) paginate by default. Fix:
Always check has_more_page (Books/Inventory) or info.more_records (CRM) and loop. [src3]
- Testing with admin credentials, deploying with limited-scope token: Fix:
Define exact scopes during design. Test with production token scope. [src5]
Diagnostic Commands
# Check remaining API quota (Books — response headers)
curl -I "https://www.zohoapis.com/books/v3/organizations" \
-H "Authorization: Zoho-oauthtoken YOUR_TOKEN"
# Test authentication — Books
curl -s "https://www.zohoapis.com/books/v3/organizations" \
-H "Authorization: Zoho-oauthtoken YOUR_TOKEN" | python3 -m json.tool
# Test authentication — CRM
curl -s "https://www.zohoapis.com/crm/v7/org" \
-H "Authorization: Zoho-oauthtoken YOUR_TOKEN" | python3 -m json.tool
# Get available CRM modules
curl -s "https://www.zohoapis.com/crm/v7/settings/modules" \
-H "Authorization: Zoho-oauthtoken YOUR_TOKEN" | python3 -m json.tool
# Generate new access token (client_credentials)
curl -X POST "https://accounts.zoho.com/oauth/v2/token" \
-d "client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&grant_type=client_credentials&scope=ZohoBooks.fullaccess.all,ZohoInventory.fullaccess.all,ZohoCRM.modules.ALL"
# Refresh access token (authorization_code flow)
curl -X POST "https://accounts.zoho.com/oauth/v2/token" \
-d "client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&grant_type=refresh_token&refresh_token=YOUR_REFRESH_TOKEN"
Version History & Compatibility
| Product | API Version | Release | Status | Key Changes |
| Zoho Books | v3 | 2023 | Current (GA) | Latest stable with 40+ modules |
| Zoho Inventory | v1 | 2020 | Current (GA) | Only version available |
| Zoho CRM | v8 | 2025-Q3 | Current (GA) | Credit-based limits, Data Sharing APIs, Workflow APIs, OAS 3.0, Zia AI API |
| Zoho CRM | v7 | 2024-Q3 | Supported | Improved webhook/notification APIs |
| Zoho CRM | v6 | 2024-Q1 | Supported | Record locking, cadences, scoring rules |
| Zoho CRM | v2.1 | 2020 | Deprecated (maintenance) | No new features. Migration recommended. |
| Zoho CRM | v1 | 2016 | EOL | XML-based, fully retired |
When to Use / When Not to Use
| Use When | Don't Use When | Use Instead |
| SMB accounting integration with < 10K transactions/day | Enterprise-scale ERP with > 100K transactions/day | SAP, Oracle, NetSuite APIs with higher throughput |
| Zoho-centric ecosystem (Books + Inventory + CRM) | Need high-volume integration with many external systems | iPaaS middleware (Workato, Celigo) with Zoho connectors |
| Real-time individual record sync with < 100 ops/min | High-frequency data ingestion | Streaming platforms (Kafka, AWS EventBridge) |
| CRM data migration or bulk export | Books/Inventory bulk operations (no bulk API) | Zoho Books CSV import or scheduled REST batching |
| Server-to-server integration without user interaction | Mobile/SPA needing offline access | Zoho SDKs with PKCE flow |
Cross-System Comparison
| Capability | Zoho Books (v3) | Zoho Inventory (v1) | Zoho CRM (v7/v8) | Notes |
| Rate Limit Model | 100/min + daily cap | 100/min + daily cap | Credit-based + concurrent cap | CRM is most flexible |
| Max Daily (top tier) | 10,000 requests | 10,000 requests | Unlimited credits (Ultimate) | CRM scales much higher |
| Concurrent Calls (paid) | 10 | 10 | 10-25 (by edition) | CRM Enterprise: 20, Ultimate: 25 |
| Bulk API | None | None | Yes (async CSV) | Major gap for Books/Inventory |
| Webhook Support | No | No | Yes (Workflow Rules) | Books/Inventory lack push notifications |
| COQL/Query Language | No | No | Yes (SQL-like) | CRM-only feature |
| Pagination | page + per_page (200 max) | page + per_page (200 max) | page token (200 max) | Similar across all three |
| Auth Header | Zoho-oauthtoken | Zoho-oauthtoken | Zoho-oauthtoken or Bearer | CRM accepts both |
| API Versioning | Single (v3) | Single (v1) | Multiple (v2.1-v8) | CRM has rich version history |
| Error Format | code + message JSON | code + message JSON | code + details JSON array | CRM errors more structured |
| Modules/Endpoints | 40+ (financial) | 15+ (inventory) | 50+ (CRM + custom modules) | Books has broadest financial coverage |
Important Caveats
- Rate limits are subject to change without notice. Zoho occasionally adjusts limits, especially for CRM credits. Always verify against current documentation.
- The 100 requests/minute limit for Books and Inventory is an absolute ceiling that does not increase with any plan upgrade. Only the daily cap scales.
- Zoho CRM's credit-based system was introduced in v8. Organizations on v7 or earlier may see different rate limiting behavior.
- Zoho's built-in Books-CRM integration syncs contacts and invoices. If both APIs are called with conflicting data, native sync may overwrite API changes. Disable native sync for custom bidirectional integrations.
- Free plan limits (1K/day for Books/Inventory, 5K credits for CRM) are extremely restrictive for production. Budget for at least Professional tier.
Related Units