Kommo + Zoho Books: automatic invoices from the sales pipeline

Zoho Books is an accounting platform from the Zoho ecosystem with support for multi-currency invoicing, tax reporting, and built-in payment processing. Unlike Wave, Zoho Books uses a full REST API without GraphQL — which simplifies integration through standard tooling. Connecting it to Kommo automates invoicing: a deal reaches a stage -> an invoice is created in Zoho Books -> after payment, the CRM is updated.

Zoho Books vs Wave vs Xero: when to choose Zoho Books

Choosing an accounting platform usually comes before building a CRM integration. A brief overview:

ParameterZoho BooksWaveXero
APIRESTGraphQLREST
Free tierUp to $50k revenue/yearYes (basic)No
Multi-currencyYesPartialYes
EcosystemZoho (50+ products)IndependentIndependent
Built-in payment processingYes (Stripe, PayPal)US/CanadaYes

Zoho Books wins if a company already uses Zoho CRM, Zoho Projects, or other Zoho products — integration within the ecosystem is native. For companies on Kommo, the integration is built via API.

What gets synchronised

Kommo -> Zoho Books:
— Deal contact -> Customer in Zoho Books (with deduplication by email)
— Deal amount and line items -> Invoice lines
— Payment due date from custom field -> Payment Terms
— Invoice ID and link -> custom field in the Kommo deal card

Zoho Books -> Kommo:
— Invoice status = paid -> “Paid” field updated in Kommo deal
— Deal moved to “Payment Received” stage
— Payment amount and date -> Note on the deal

Architecture

Kommo Webhook: deal moved to stage "Issue Invoice"
  ↓ Backend
  1. GET /api/v4/leads/{id} + contacts
  2. Zoho Books API: GET /contacts?email={email}
     -> found: use contact_id
     -> not found: POST /contacts (create)
  3. Zoho Books API: POST /invoices
     -> receive invoice_id and invoice_url
  4. Zoho Books API: POST /invoices/{id}/email
     -> send invoice to client
  5. Kommo: PATCH /leads/{id}
     -> update custom fields invoice_id, invoice_url

Zoho Books Webhook: invoice.payment_received
  ↓ Backend
  1. GET invoice details (custom_field: kommo_deal_id)
  2. Kommo: PATCH /leads/{deal_id}
     -> payment_status = paid, stage -> "Payment Received"

Zoho Books REST API: key requests

Zoho Books uses OAuth 2.0. All requests require organization_id as a parameter.

Search for a customer:

response = requests.get(
    'https://books.zoho.com/api/v3/contacts',
    params={
        'organization_id': ORG_ID,
        'contact_name': company_name,
        'email': email
    },
    headers={'Authorization': f'Zoho-oauthtoken {access_token}'}
)
contacts = response.json().get('contacts', [])

Create an invoice:

invoice_data = {
    'customer_id': customer_id,
    'invoice_number': f'INV-{deal_id}',
    'date': today_str,
    'payment_terms': 30,  # Net 30
    'line_items': [
        {
            'name': deal_name,
            'quantity': 1,
            'rate': deal_price,
            'tax_id': TAX_ID  # if applicable
        }
    ],
    'custom_fields': [
        {'label': 'Kommo Deal ID', 'value': str(deal_id)}
    ]
}
response = requests.post(
    'https://books.zoho.com/api/v3/invoices',
    params={'organization_id': ORG_ID},
    json=invoice_data,
    headers={'Authorization': f'Zoho-oauthtoken {access_token}'}
)

Send the invoice to the client:

requests.post(
    f'https://books.zoho.com/api/v3/invoices/{invoice_id}/email',
    params={'organization_id': ORG_ID},
    json={
        'send_from_org_email_id': True,
        'to_mail_ids': [client_email],
        'subject': f'Invoice {invoice_number} from {company_name}'
    },
    headers={'Authorization': f'Zoho-oauthtoken {access_token}'}
)

Tax handling

Zoho Books supports tax profiles (VAT, GST, Sales Tax). If the company works with clients in multiple jurisdictions, the applicable tax is determined by the client’s country:

TAX_MAP = {
    'DE': 'VAT_19',      # Germany - VAT 19%
    'UK': 'VAT_20',      # United Kingdom - VAT 20%
    'US': None,           # USA - no VAT
    'AU': 'GST_10',      # Australia - GST 10%
}

def get_tax_id(country_code: str) -> str | None:
    return TAX_MAP.get(country_code)

The client’s country is taken from a Kommo custom field or from the contact record.

Real-world case

Consulting company (EU market, 15–20 projects per month, clients in 6 countries):

  • Before: the accountant manually created invoices in Zoho Books by requesting data from sales managers. Average time from Won to invoice issued — 3 days.
  • After: Won in Kommo -> invoice in Zoho Books with the correct tax for the client’s country -> sent to the client -> within 30 minutes of closing the deal.
  • Additional effect: the accountant stopped requesting data from managers — everything arrives automatically.

We implemented the same logic in the Kommo and Wave integration — the API is different there (GraphQL), but the pattern is identical.

Who this is relevant for

  • Zoho Books is in use (or a migration to the Zoho ecosystem is planned)
  • Clients in multiple countries with different tax requirements
  • Volume: 10+ invoices per month
  • The full cycle needs to be closed: Won -> invoice -> payment -> CRM updated

Frequently asked questions

Is Zoho Books OAuth harder to set up than Wave?

Zoho OAuth is standard: Authorization Code Flow via accounts.zoho.com. You need to register an application in the Zoho API Console and obtain a client_id and client_secret. One additional detail: Zoho tokens are region-specific — EU accounts use accounts.zoho.eu, not .com. This is a common source of errors on first connection.

Does Zoho Books support recurring invoices — can retainer billing be automated?

Yes. Zoho Books has a Recurring Invoice API: create a template with an interval (monthly, quarterly) and a start date. The Kommo integration creates a recurring invoice when a deal moves to the “Retainer Active” stage and cancels it when it moves to “Completed.”

Is a paid Zoho Books subscription required?

Zoho Books is free for businesses with revenue up to $50,000/year. The API is available on all plans. Above that threshold — from $15/month. Significantly cheaper than Xero or QuickBooks.

How do you pass multiple line items from Kommo?

Via custom fields of type multilist, or via separate “Item / Quantity / Price” fields. Each item maps to a line_items row. If there are no detailed line items, the full deal amount goes as a single row.

Summary

  • Zoho Books REST API is simpler to integrate than Wave GraphQL — standard OAuth, clear endpoints
  • Multi-currency and tax profile support by client country — important for EU markets
  • Pattern: Won -> invoice -> sent -> payment -> Kommo updated
  • Free tier up to $50k revenue — relevant for small businesses
  • Typical development timeline — 2–3 weeks

If you use Zoho Books and Kommo and want to automate invoicing — describe your tax structure and invoicing workflow. Exceltic.dev will work through the mapping and propose an architecture.

More articles

All →