Hello everyone,
During Zoho Books implementations, one common challenge is updating a large number of existing records. The current options are usually:
- Update records manually from the UI using Mass Update (with limited batch size).
- Update records one by one through code using the API.
For large data corrections, migrations, or post-implementation changes, manually updating records is not practical, so I created a Node.js utility that safely performs bulk custom-field updates through the Zoho Books API.
The workflow
- Create a custom view containing the records that need to be updated.
- Export the records and extract their IDs into a text file (one ID per line).
- Point the script at the IDs file.
- Define the custom fields and new values in
.env. - Run the migration in three stages:
probe → dry-run → run.
Alternatively, instead of exporting IDs manually, you can write a small search function that retrieves the records you need and generates the IDs file automatically.
What the script supports
- Multiple custom-field updates in the same request.
- Any Books module (recurring invoices, invoices, contacts, bills, ...) via configuration — no code changes.
- Zero-ceremony OAuth: you provide only the Self Client grant code — the script exchanges it for a refresh token on first run, persists it locally, and mints access tokens automatically from then on. No manual token calls, no hardcoded tokens.
- Automatic re-refresh if Zoho invalidates the access token mid-run (401 handling).
- Request timeouts, retry with backoff for HTTP 429 and 5xx (honours
Retry-After). - Canary update: one record is updated and verified with a follow-up GET before the batch starts — a typo in a dropdown value aborts after one record, not after thousands.
- Progress milestones roughly every 10% of the batch, with a live ETA (the initial estimate is measured from the canary request's actual round-trip, not guessed).
- Resume capability: every outcome is appended to
results.jsonl; re-running skips records already updated successfully. A token problem or a network drop mid-run costs nothing. - Failed-ID export (
failed_ids.txt) for targeted retry.
Configuration
Everything lives in .env. You need exactly: data center, org ID, client ID/secret, a Self Client grant code, the module, the IDs file, and the fields to set — nothing else:
ZB_DC=eu
ZB_ORG_ID=123456789
ZB_CLIENT_ID=1000.xxxxx
ZB_CLIENT_SECRET=xxxxx
ZB_AUTH_CODE=1000.xxxxx
ZB_MODULE=recurringinvoices
ZB_IDS_FILE=invoice_ids.txt
ZB_THROTTLE_MS=700
ZB_FIELDS=[{"api_name":"cf_status","value":"Approved"},{"api_name":"cf_sync_date","value":"2026-07-16"}]
ZB_AUTH_CODE is the grant code from the API console (Self Client → Generate Code, with the scopes below). It is single-use and expires within 3–10 minutes, so run the script right after generating it — the first run exchanges it for a permanent refresh token and saves it to .zb_token_store.json. Add both .env and .zb_token_store.json to .gitignore, and revoke the client when the migration is done.
Gotchas worth knowing:
ZB_FIELDS must stay on a single line — dotenv does not parse unquoted multi-line values.ZB_DC must match the data center the client was created on. A client from api-console.zoho.eu will not authenticate against accounts.zoho.com.- If the exchange fails with
invalid_code, the grant code expired or was already consumed — generate a fresh one and re-run immediately.
ZB_MODULE is the URL path segment (recurringinvoices, invoices, contacts, ...). Note that Books responses wrap the record in a singular root key (invoice, recurring_invoice, ...) that doesn't match the URL segment — the script auto-detects it from the first GET, so you don't have to know this.
Usage
Probe the configuration and field mapping (read-only — this also performs the one-time grant-code exchange on first run):
bash
node zoho-books-bulk-cf-update.mjs probe
Update and verify one record, then stop:
bash
node zoho-books-bulk-cf-update.mjs dry-run
Execute the complete migration:
bash
node zoho-books-bulk-cf-update.mjs run
Sample run output:
48 IDs total · 0 already ok · 48 pending
auto-detected response entity key: "invoice"
Probe 639896000003678005: custom_fields present: cf_status, cf_sync_date, ...
cf_status → customfield_id 639896000000729241 (current: "Draft")
Canary update on 639896000003678005 ...
Canary verified.
Small batch (47 records) — throttle lowered to 300 ms.
1/48 · ETA 1.1 min
5/48 · ETA 1.0 min
10/48 · ETA 0.9 min
...
48/48 Done · ok=48 fail=0
Implementation details
The update process intentionally runs sequentially instead of firing parallel requests, to respect the per-minute API limit (100 requests/min per organization), avoid failures caused by throttling, and keep the migration predictable. The default 700 ms delay keeps the rate at roughly 85 requests/min. Batches of 90 records or fewer physically cannot breach the per-minute cap, so the script speeds those up automatically.
One detail that matters across orgs: custom fields in the update payload are addressed by customfield_id where possible. The script GETs one record first, resolves each api_name to its customfield_id, and only falls back to api_name addressing if the field is not present on the sample record.
Required scopes:
ZohoBooks.invoices.READ
ZohoBooks.invoices.UPDATE
(or the equivalent scopes for the module you are updating — always least-privilege rather than ZohoBooks.fullaccess.all)
Production considerations
- Mind the daily API cap as well as the per-minute one — it varies by Books plan. A 10,000-record migration may need to be split across days on lower plans.
- Dropdown custom fields must receive a value that matches an option exactly (spacing, hyphens, casing — especially with non-Latin characters). The canary catches this before the batch runs.
- An in-memory ID list is fine into the tens of thousands; the point of
results.jsonl is durability — progress survives crashes, token expiry, and Ctrl+C. - For extremely large or recurring migrations, the same logic can move into a queue-based Node.js worker where you control execution time, retry strategy, parallelism, and monitoring.
Where this is useful
- Updating custom fields after migrations.
- Fixing incorrectly imported data.
- Updating integration-generated records.
- Applying bulk corrections after changing business logic.
- Cleaning up data after implementation projects.
Sharing this pattern because bulk updates are a common challenge when working with the Zoho Books API. Script and example .env attached.
Recent Topics
Customer Statement Showing Incorrect Negative Balance Due to Unused Advance
Dear Zoho Support Team, We are facing an issue with the Customer Statement in Zoho Invoice related to customer advances/mobilization advances. The issue is that when a customer has made an advance payment that has not yet been fully utilized against invoices,
【10/15・残席わずか】Zoho Championに学ぶ!Zoho Campaigns メール配信の基礎・活用勉強会
皆さま、こんにちは。ゾーホージャパンの中野です。 10月15日(木)、Zoho コミュニティ初となる「Zoho Campaigns メール配信の基礎・活用勉強会」をオンラインで開催します! 今回の登壇者は、Zoho の導入・活用支援に豊富な経験を持つZoho Champion の岡安 裕一さんです。 「一斉配信はできるけれど、現在の設定や運用が正しいか自信がない」 「Zoho CRMとZoho Campaignsのどちらから配信すればよいか分からない」 「リストとセグメントの違いや、配信停止の扱いを整理したい」
WorkDrive API: allow the modification time to be set when updating an existing file (x-last-modified-date is honoured on create, ignored on update)
Hi, I contribute to the Zoho WorkDrive backend of rclone, the open-source sync/copy tool. I would like to raise one specific, narrow API gap that currently makes reliable syncing to WorkDrive impossible, and ask whether it can be addressed. What already
WhatsApp Coexistence
Hello, please implement WhatsApp Coexistence, we need to track staff whatsapp chats on their PC and they need to be able to use WhatsApp on their mobile in around the office and warehouse, as we video call customers and send them product pictures. Thank
Kiosk / CRM Timezone Oddity
I grant you this is much easier to see than to explain, and snapshots here won't help much and I don't want to snapshot my record anyway in a forum, so bear with me... Effectively... As there had been discussions on times coming through in different timezones
Restricted Account - "This user is not allowed to add in Zoho" - citbinvestment.com.
Hi Zoho Support Team, I am attempting to set up user mailboxes for my domain citbinvestment.com, but I am receiving the following error: "This user is not allowed to add in Zoho. Please contact support-as@zohocorp.com for further details." > My MX, SPF,
👍 Zoho CRM's Notes now gets Reactions and a new look
Available in SA and JP DCs. Rolling out to other DCs in phases. Hello everyone, Notes help users capture important updates, collaborate with teammates, and maintain context for records. Now with Note Reactions, users can quickly acknowledge updates, express
Contact Sharing: Hide email alias from global address list
As the superadmin, I would like to hide my domain aliases from appearing in the global address list. Currently, my end users can see all my aliases. The aliases also appear as type-in addresses when composing a new email. This is a potential security
Incorrect Currency Shown
On Bills, each line shows the rate in the wrong currency (home currency).
This user is not allowed to add in Zoho. Please contact support-as@zohocorp.com for further details
Hello, Just signed up to ZOHO on a friend's recommendation. Got the TXT part (verified my domain), but whenever I try to add ANY user, I get the error: This user is not allowed to add in Zoho. Please contact support-as@zohocorp.com for further details I have emailed as well and writing here as well because when I searched, I saw many people faced the same issue and instead of email, they got a faster response here. My domain is: raisingreaderspk . com Hope this can be resolved. Thank you
[Free webinar] Beyond prompt-to-app: Vibe coding with Zoho Creator | Creator Tech Connect (October 2026)
Hello everyone, We are excited to invite you to another edition of the Creator Tech Connect webinar. About Creator Tech Connect The Creator Tech Connect series is a free monthly webinar consisting of purely technical sessions, where we dive deep into
Zoho Recruit Staffing version Interview using Zoho Meeting
I would like to understand whether Zoho Meeting has a native integration with Zoho Recruit – Staffing Edition. As of now, I am unable to find the native Zoho Meeting integration within the Staffing Edition of Zoho Recruit. Could someone please confirm
Payroll needs to automatically remit taxes, not just give me the calculations
Wagepoint, PayEvo, Waveapps, etc... All your competitors deposit employee payroll, but they ALSO remit taxes automatically. Get with the program, your Payroll app is extremely sparse.
New enhancements to user management
Hello everyone, We're excited to introduce a few enhancements to user creation and user preferences in Bigin! These updates give administrators more flexibility while inviting users, and give users more control over how their data is displayed. With this
How to add PHONE number to the Activites view
This just seems like something so obvious and I can't believe I can't find it. When I add a TASK for a person that I want to call back, I'd like to be able to see that persons PHONE NUMBER in the actives list. Ive added every field possible in the views, and the best that it gets is the person's name, but not their phone number. I'd like to be able to just print my tasks, seeing the person I need to call back with their phone number. Is there a way to do this in the FREE edition? thanks.
Public dashboard table does not load in mobile view - TypeError reading 'viewType'
Our public dashboard links have worked for years. We made no changes. Now the table widget does not load on mobile browsers. It loads fine on desktop, and it loads on a phone when we use "Request desktop site." Chrome DevTools shows this error in mobile
Cannot format "start date" field in Zoho Flow
I am trying to recreate a flow that connects Inventory package creation to Zoho projects (where a task is created in a defined project). I've been able to troubleshoot everything EXCEPT the date fields; specifically the "start date" - which is quite important
Bank Transactions page shows too few transactions due to large header area
In the Banking → Uncategorized Transactions screen, a lot of vertical space is being used by the account header, balance details, tabs, buttons, etc. Because of this, on a normal desktop screen I can see only around 2 transactions at a time, even though
Zoho Mail Android app update (v3.6.5) - Enhancements in Email Composer and Google Meet support
Hello everyone! We are excited to introduce new enhancements in the Zoho Mail Android app (v3.6.5). Let's dive into what's new. Drag and drop email addresses between recipient fields You can now drag and drop the email addresses across the recipient fields:
Migration from QuickBooks to Zoho Books for the U.S. Company
Is there any automation tool available to migrate data from QuickBooks to Zoho Books for a U.S.-based company? If yes, could you please provide the details?
Feature Request: Integración con la Lista del Artículo 69-B del SAT para Zoho Books México
Feature Request: Integración con la Lista del Artículo 69-B del SAT para Zoho Books México Hola equipo de Zoho, Durante los últimos meses he observado una necesidad recurrente entre varios clientes en México relacionada con el cumplimiento fiscal del
Introducing Zoho Key Service, a simpler way to access LLMs without API keys
Available in the Professional, Enterprise, and Ultimate editions in the US, IN, AU, JP, and CA DCs. Hello everyone, We are excited to bring Zoho Key Service (ZKS) in Zoho CRM, a simpler way for organizations to access and use third party LLMs. You can
Single Folder Archival in Zoho Mail
Dear Zoho Mail Community, Have you noticed and wondered what the banner is about in your Zoho Mail's Archive Policy Settings? In Zoho Mail, users have traditionally archived emails to keep their inbox and active folders clean. While this helped reduce
Trigger Workflow Rules from subform row actions
Hello all, Previously, workflow rules could only be configured at the module level, which meant subform data had to be tracked and managed manually. With this update, workflow rules can now be triggered directly by actions within subform rows, giving
Free Plan mail accounts details
In the zoho mail pricing there's a free plan that includes: FREE PLAN Up to 25 Users 5GB* /User, 25MB Attachment Limit Webmail access only. Single domain hosting. I need to make sure that I'm able to create multiple email accounts in the form of: name@domain.com
can not use my zoho mail
i bouht domain( avta group.com) and set up mail(Avtar@avta group.com) but i cannot receive or send emails . can you please help out.
Display Issues
Hello, Our company just changed General Managers and the other one was the super admin. Since deleting his profile and making our new General Manager the super admin there have been ongoing issues. One in particular, is when creating estimates, sales
Introducing Night Mode for Zoho Recruit [BETA]
Late-night hiring sessions? Long hours reviewing resumes? We heard you. Night mode [BETA] is now available in Zoho Recruit, giving you a cleaner, more comfortable workspace that’s easier on the eyes while keeping the focus on what matters most: hiring.
Unblock ME
info@pentekykloi.gr Unable to send message;Reason:554 5.1.8 Email Outgoing Blocked. Learn more. I purchase additional storage
Zoho Calendar integration for Bigin
Hello everyone, We're excited to introduce Zoho Calendar's integration in Bigin! For a while now, users have been able to sync events in Bigin with Google Calendar and Outlook Calendar - but with this new topping, it syncs with Zoho Calendar as well.
Workflows, webhooks, and zero manual work: Your webinar operations, on autopilot
Running a webinar is never just about going live. There's the flurry of registrations to track, attendees to follow up with, recordings to share, CRM records to update, and somehow, all of this has to happen on time, every time. Until now, most of it
Zoho Mail - More contextual actions on email list view
Hi Zoho Mail team, I recently completed an email migration from Gmail to Zoho Mail and noticed a feature in Gmail that I think would be a great addition to the Zoho Mail interface. When you hover over an email in Gmail's list view, a number of quick actions
Supervisor Rules --> Custom Function
Hello, currently I can't add a custom function to a supervise rule. Is there a reason for this? Background: We have BluePrint managed tickets and actually we have a Supervise rule which should set the ticket to "closed" after 168 hours since the last
Erro
Subject: CRM Standalone Function creation returns INTERNAL_ERROR Hello Zoho Support, I am trying to create a Standalone Deluge Function in Zoho CRM for a lead intake REST API. The CRM account reports that the Standalone category is enabled, but function
Digest Septembre - Un résumé de ce qui s'est passé le mois dernier sur Community
Bonjour chère communauté ! 👋 Le mois dernier a été riche en nouveautés, en échanges et en découvertes ! Retrouvez ici les contenus les plus utiles, les discussions les plus intéressantes et plus encore. En septembre, nous avons mis en lumière trois nouveautés
New Update: Convert External Users in Bulk in Zoho Directory
Greetings to all Zoho Directory users out there! We’re excited to introduce a new update that makes user management in Zoho Directory even more efficient; you can now convert external users in bulk! Earlier, admins could convert only one external user
Presenting ABM for Zoho CRM: Expand and retain your customers with precision
Picture this scenario: You're a growing SaaS company ready to launch a powerful business suite, and are looking to gain traction and momentum. But as a business with a tight budget, you know acquiring new customers is slow, expensive, and often delivers
API - Bank Accounts | Reconciliation Discrepancy
Unless I'm reading it wrong, the documentation for the Bank Reconciliations API is inconsistent with itself. https://www.zoho.com/books/api/v3/bank-accounts/#create-a-bank-reconciliation The text definition says that the transaction_id should be a string,
Employment Contract / HRMS Documents - Zoho People
How do I create customized HR documents for disbursal from Zoho People ? Example, say offer letters ? appointment letters ? Memos ? We want to be able to preset these in one or ther other form and issue them to employees who are in Zoho People.
Mobile authentication for Zoho Creator portals
Note: This feature was previously available in beta for IN data center users on request. It is now generally available for all users in the IN and US data centers on paid plans of Zoho Creator. Currently, it will be available only for Indian (+91) mobile
Next Page