Beam Help
Get help now

How-to · Zoho CRM

How to update records in Zoho

Modify existing record data using Zoho's record update API.

Updating records in Zoho requires a valid, active OAuth connection with the correct scopes — once those are in place, the update flow handles token refresh automatically and writes changes back to CRM or Desk.


Why this matters


Whether you're syncing contact details, closing tickets, or modifying lead data, programmatic record updates depend on a live OAuth token and the right permission scopes. If your token has expired or your scopes are too narrow, update calls will silently fail or return 401 errors. Understanding how the connection layer works helps you diagnose and fix these issues quickly.


> Note: Beam Help is independent expert support for Zoho — we are not official Zoho support.


---


Step-by-step


Step 1. Confirm your OAuth connection exists and holds a valid token.


Before any record update can succeed, the system must find a stored connection for your user. The connection is looked up from a local zohoconnections table using your userid. If no row is found, the API client cannot be initialised and all subsequent calls will fail.[3]


Step 2. Allow the token refresh cycle to run.


Tokens are refreshed proactively when the current time is within 120 seconds of the stored tokenexpiresat value. A successful refresh writes the new accesstoken and updated tokenexpiresat back to the zohoconnections row, so the next call always uses a fresh credential.[3] If the refresh itself fails (for example, the refresh_token is missing or revoked), the function returns None and no update will proceed.[1]


Step 3. Verify the correct OAuth scopes are granted.


For Zoho CRM record updates, your OAuth grant must include ZohoCRM.modules.ALL or the equivalent module-level UPDATE scope. For Zoho Desk, the relevant scopes include Desk.tickets.UPDATE, Desk.contacts.UPDATE, Desk.tasks.UPDATE, and similar per-object UPDATE permissions.[5] If these scopes were not requested during the original OAuth authorisation, you will need to re-authorise and explicitly include them.


Step 4. Initialise the correct API client for your product.


Pass apptype="crm" to target Zoho CRM, or apptype="desk" to target Zoho Desk. For Desk, an orgid is also required — if it is not already stored, the system will call getallorganizations to discover and persist it automatically.[1] For CRM, a ZohoCrmClient is constructed using the stored apidomain and access_token, with the token refresher callback wired in.[4]


Step 5. Execute the update tool with the target record ID and changed fields.


Once the API client is ready, call execute_tool with the appropriate update tool name and a params object that includes the record id and the fields you want to change. The execution layer will attempt the call, and if a clarifying question or error is returned in the result, that message is surfaced directly so you can correct the payload and retry.[8]


Step 6. Confirm the connection metadata is current after an auth callback.


If you recently re-authorised, check that the auth callback correctly wrote the latest accesstoken, refreshtoken, apidomain, and tokenexpiresat into zohoconnections. The callback performs an upsert — updating the existing row if one is found, or inserting a new one otherwise — and also stores crmorgid for CRM tenancy.[2]


---


Common pitfalls


  • Missing orgid for Desk calls. If deskorg_id is blank or whitespace, the client is still constructed but the first API call triggers an auto-discovery lookup. If that lookup also fails (e.g., due to a scope gap on Desk.basic.READ), all subsequent Desk updates will error.[1]
  • Token refresh returning no accesstoken. If ZohoOAuth.refreshtokens responds without an access_token key, the refresher returns None and the stale token remains in use, causing 401s on update calls.[1][3]
  • Scope gaps from the original grant. Scopes are set at authorisation time. Adding UPDATE scopes to your config file does not retroactively update an existing grant — the user must complete a fresh OAuth flow.[5]
  • SQLite locking during concurrent updates. Backfill or migration operations that update zoho_connections must use a single connection/transaction to avoid locking conflicts.[6]

---


What to check


  • Confirm the zohoconnections row for your userid has a non-null refreshtoken and that tokenexpires_at is a valid Unix timestamp.[3]
  • Verify your OAuth grant includes the relevant UPDATE scope for the module you are targeting (e.g., ZohoCRM.modules.ALL for CRM, Desk.tickets.UPDATE for Desk tickets).[5]
  • After any re-authorisation, check that the apidomain stored in zohoconnections contains zohoapis. so the data centre is correctly inferred for subsequent API calls.[2]

Sources cited

  1. [1] server.py: get_zoho_api
  2. [2] server.py: auth_callback
  3. [3] server.py: get_zoho_connection
  4. [4] run_direct_tests.py
  5. [5] config.py
  6. [6] db.py
  7. [7] run_api_tests.py
  8. [8] server.py: apply_plan
How to update records in Zoho | Beam Help