How to Integrate with the Zoho Books API

A complete guide to integrating with the Zoho Books API covering authentication, key endpoints, rate limits, data mapping, and common pitfalls. Learn how to build a reliable integration or simplify the process using a unified API.

Kateryna PoryvayKateryna Poryvay

Kateryna Poryvay

9 min read
How to Integrate with the Zoho Books API

Zoho Books is a cloud-based accounting platform popular with small and mid-sized businesses, particularly those already embedded in the Zoho ecosystem. If your product serves finance teams, you'll eventually get a request to pull invoice data from Zoho Books or push expense records into it.

This guide covers the technical work involved: authentication, key endpoints, rate limits, data mapping, and the common pitfalls that trip up first-time integrators. If you want to skip the direct integration work, Apideck's Zoho Books connector handles the plumbing through a unified accounting API.

What the Zoho Books API offers

The Zoho Books API is a REST API that returns JSON responses. Version 3 is the current release and covers the full range of accounting operations: contacts, invoices, expenses, bills, bank transactions, purchase orders, and sales orders.

Every API request requires two things: an OAuth 2.0 access token and an organization_id parameter. Zoho Books supports multiple organizations under a single account, and the API enforces strict separation between them. You'll need to retrieve the organization ID first (via GET /organizations) before calling any other endpoint.

Base URL: https://www.zohoapis.com/books/v3/

One complication: Zoho operates regional data centers with distinct API domains: .com, .eu, .in, .com.au, .jp, .ca, .sa (Saudi Arabia), and .uk. The API domain must match where the user's Zoho Books account is hosted. A customer on zoho.eu needs API calls to zohoapis.eu. Getting this wrong produces authentication errors that look like token problems.

The modern approach is to detect the data center automatically during OAuth. When you make the initial authorization request to accounts.zoho.com, the response includes a location parameter indicating the user's data center. You can also call https://accounts.zoho.com/oauth/serverinfo to get the full mapping of location codes to API domains. This beats asking users to identify their region manually.

Authentication setup

Zoho uses OAuth 2.0 with the authorization code grant type. The flow works like most OAuth implementations, with a few Zoho-specific details.

Register your application

Go to the Zoho Developer Console and create a new client. You'll choose between two client types:

  • Web-based: Standard OAuth flow with redirect URIs. Use this for applications where users authenticate through a browser.
  • Self-client: Server-to-server authentication. Generates tokens without user interaction after the initial setup. Useful for backend services and scheduled syncs.

Registration gives you a client ID and client secret.

Implement the authorization flow

For web-based clients, redirect users to Zoho's authorization endpoint:

GET https://accounts.zoho.com/oauth/v2/auth
  ?response_type=code
  &client_id={your_client_id}
  &scope=ZohoBooks.invoices.READ,ZohoBooks.contacts.READ
  &redirect_uri={your_redirect_uri}
  &access_type=offline

The access_type=offline parameter is important. Without it, you won't receive a refresh token, and your integration will break after an hour when the access token expires.

After the user authorizes, Zoho redirects to your URI with an authorization code. Exchange it for tokens within two minutes:

POST https://accounts.zoho.com/oauth/v2/token
  ?code={authorization_code}
  &client_id={your_client_id}
  &client_secret={your_client_secret}
  &redirect_uri={your_redirect_uri}
  &grant_type=authorization_code

Manage token lifecycle

Access tokens expire after one hour. Refresh tokens don't expire unless revoked, and you can reuse the same refresh token to generate new access tokens repeatedly. Store the refresh token securely and use it to generate new access tokens before they expire:

POST https://accounts.zoho.com/oauth/v2/token
  ?refresh_token={refresh_token}
  &client_id={your_client_id}
  &client_secret={your_client_secret}
  &grant_type=refresh_token

Zoho's scopes are granular. Instead of broad permissions like "accounting:read", you request specific capabilities: ZohoBooks.invoices.CREATE, ZohoBooks.contacts.READ, ZohoBooks.expenses.UPDATE. Request only what you need. The full scope list covers contacts, settings, estimates, invoices, customer payments, credit notes, projects, expenses, sales orders, purchase orders, bills, debit notes, vendor payments, banking, and accountant operations.

Key endpoints

CategoryEndpointCommon operations
Contacts/contactsCreate and manage customers and vendors
Invoices/invoicesCreate, send, and track invoices
Expenses/expensesRecord and categorize expenses
Bills/billsManage accounts payable
Banking/bankaccounts, /banktransactionsBank feeds and reconciliation
Recurring/recurringinvoices, /recurringexpensesSubscription billing and repeat expenses
Orders/salesorder, /purchaseorderSales and purchase order management

A few endpoints worth noting:

POST /invoices/fromsalesorder creates an invoice directly from a sales order, which saves a round trip if you're building order-to-cash workflows.

POST /invoices/email and POST /invoices/paymentreminder handle customer communication without leaving the API.

GET /organizations returns all organizations the authenticated user can access, along with currency settings, fiscal year configuration, and time zone. Call this first to get the organization_id you'll need for everything else.

Data mapping considerations

Zoho Books uses its own data model, which won't map 1:1 to other accounting systems. If you're building a multi-platform integration, here are the fields that cause the most trouble.

Contacts

Zoho combines customers and vendors into a single contacts endpoint, distinguished by contact_type. The contact_name field has a 200-character limit. Company information goes in company_name, not the contact name. Billing and shipping addresses are nested objects with their own field structure.

Invoices

Tax handling is line-item based. Each line item can have its own tax rate, and the tax configuration at the header level must match the line items. Mismatches produce validation errors that aren't always obvious from the error message.

Line items use item_id for products from your Zoho inventory or can be created as custom items with name, description, rate, and quantity.

Custom fields

Most resources support custom fields through a custom_fields array. Each custom field requires a customfield_id (retrieved from the organization settings API) and a value. Custom field IDs are organization-specific, so don't hardcode them.

Rate limits

Zoho Books has some of the most restrictive rate limits among major accounting APIs. Plan your integration accordingly.

Per-minute limit: 100 requests per minute per organization. Exceeding this returns HTTP 429 with error code 44.

Daily limits vary by plan:

  • Free: 1,000 calls/day
  • Standard: 2,000 calls/day
  • Professional: 5,000 calls/day
  • Premium/Elite/Ultimate: 10,000 calls/day

Exceeding daily limits returns HTTP 429 with error code 45.

Concurrent limit: Roughly 10 simultaneous requests per organization. HTTP 429 with error code 1070 indicates you've hit this ceiling.

The daily limit is shared across all API consumers for that organization. If your customer uses other Zoho integrations or third-party tools that call the API, those count against the same quota. This creates situations where your integration fails because something else exhausted the limit.

Build in exponential backoff for 429 responses. For bulk operations, consider batching and spreading requests across longer time windows.

Error handling

Zoho Books returns HTTP status codes with JSON error bodies:

{
  "code": 44,
  "message": "For security reasons your account has been blocked as you have exceeded the maximum number of requests per minute."
}

Common error codes:

  • 0: Success
  • 44: Per-minute rate limit exceeded
  • 45: Daily rate limit exceeded
  • 1070: Concurrent request limit exceeded
  • 1000-1099: Various validation and business logic errors

Log the full error response, not just the HTTP status. The code field often contains more actionable information than the status code alone.

Testing your integration

Zoho Books doesn't offer a dedicated sandbox environment. You have two options:

  1. Create a test organization: Set up a separate Zoho Books organization for development. This uses real API calls against real infrastructure but keeps test data isolated from production.

  2. Use a trial account: Zoho offers free trials that provide API access. Useful for testing, but trial limitations may not reflect production behavior.

Test these scenarios specifically:

  • Token refresh: Let an access token expire and verify your refresh logic works
  • Rate limit handling: Intentionally exceed limits and confirm your backoff implementation
  • Multi-organization: If your users might have multiple Zoho Books organizations, test the organization selection flow
  • Regional domains: Test with accounts on different Zoho data centers if your customer base is international

Webhooks and real-time sync

Zoho Books supports outgoing webhooks for real-time notifications. You can configure webhooks in Zoho Books to fire when events occur (invoices created, payments received, contacts updated, etc.), sending HTTP POST requests to your endpoint with the event payload. This eliminates the need for constant polling.

To set up webhooks, navigate to Settings > Automation > Webhooks in the Zoho Books UI and define the trigger events and destination URL. You can also receive incoming webhooks from external systems to create or update records in Zoho Books.

For scenarios where webhooks aren't practical, you can poll endpoints periodically using the last_modified_time field on most resources to filter for recent updates. But webhooks are the cleaner approach for near-real-time sync requirements.

Connecting through a unified API

Building a direct Zoho Books integration makes sense if Zoho is your only target. But most B2B applications need to support multiple accounting platforms. Your QuickBooks customers expect the same sync features as your Zoho customers, and your Xero customers will ask for parity next quarter.

Direct integrations mean duplicating the authentication, data mapping, error handling, and maintenance work for each platform. A unified accounting API abstracts those differences behind a single interface.

Apideck's accounting API normalizes Zoho Books alongside QuickBooks, Xero, Sage, NetSuite, and 20+ other platforms. One integration gives your customers their choice of accounting software. Authentication, webhooks, and rate limit management are handled at the platform level.

This approach trades some Zoho-specific customization for dramatically reduced integration scope. If you're building invoice automation or expense sync features, the normalized data model covers the common operations without requiring platform-specific code paths.

Getting started

If you're building direct to Zoho Books:

  1. Register at the Zoho Developer Console
  2. Implement OAuth with offline access
  3. Detect data centers automatically via the location parameter in OAuth responses
  4. Store organization IDs and regional domains per customer
  5. Build rate limit handling from day one

If you want to support multiple accounting platforms:

  1. Sign up for an Apideck account
  2. Enable the Zoho Books connector
  3. Use the unified accounting API for contacts, invoices, and expenses

FAQ

Does Zoho Books have a sandbox environment?

No. Test against a separate organization or trial account to avoid polluting production data.

How do I handle customers on different Zoho data centers?

Detect the data center automatically during OAuth. The authorization response includes a location parameter (e.g., us, eu, in). Use https://accounts.zoho.com/oauth/serverinfo to map location codes to the correct API domains. Store the data center domain alongside the OAuth tokens for each customer.

Why am I getting "invalid_code" when exchanging the authorization code?

Authorization codes expire after two minutes and can only be used once. If your token exchange is slow or you retry a failed request with the same code, you'll hit this error.

Can I increase the API rate limits?

The limits are tied to the Zoho Books subscription plan. Your customer would need to upgrade to a higher tier for increased limits. There's no separate API-specific upgrade path.

Does Zoho Books support webhooks?

Yes. Zoho Books supports outgoing webhooks that notify your application when events occur. Configure them through Settings > Automation > Webhooks in the Zoho Books interface. You can trigger webhooks on invoice creation, payment receipt, contact updates, and other events.

Ready to get started?

Scale your integration strategy and deliver the integrations your customers need in record time.

Ready to get started?
Talk to an expert

Trusted by fast-moving product & engineering teams

JobNimbus
Blue Zinc
Drata
Octa
Nmbrs
Apideck Blog

Insights, guides, and updates from Apideck

Discover company news, API insights, and expert blog posts. Explore practical integration guides and tech articles to make the most of Apideck's platform.