Zoho Deluge Scripting: Custom Functions, Governance Limits, and Execution Constraints

Type: ERP Integration System: Zoho Deluge Runtime (Deluge 2.0) Confidence: 0.90 Sources: 8 Verified: 2026-03-02 Freshness: 2026-03-02

TL;DR

System Profile

Deluge is Zoho's proprietary scripting language embedded in their entire product ecosystem. Unlike traditional ERP scripting (Salesforce Apex, NetSuite SuiteScript), Deluge is shared across 40+ Zoho applications -- the same language works in CRM, Creator, Desk, Books, and every other Zoho product. This card covers the Deluge runtime as it applies to Zoho CRM and Zoho Creator (the most common contexts), but the core language and most governance limits are consistent across all Zoho products. Edition-specific limits (API credits, daily call quotas) vary by which Zoho product you are scripting in. [src6]

PropertyValue
VendorZoho
SystemZoho Deluge Runtime (across Zoho One / CRM / Creator / 40+ apps)
API SurfaceDeluge scripting language (integration tasks + invokeURL)
Current VersionDeluge 2.0 (current runtime)
Editions CoveredStandard, Professional, Enterprise, Ultimate, Zoho One
DeploymentCloud
API DocsZoho Deluge Help
StatusGA

API Surfaces & Capabilities

Deluge provides three primary mechanisms for integrating with external systems and other Zoho services. [src4, src6]

API SurfaceProtocolBest ForMax Records/RequestRate LimitReal-time?Bulk?
Integration TasksZoho internal RESTZoho-to-Zoho operations (CRM, Books, Desk, etc.)Service-dependentCounts as API creditsYesLimited
invokeURLHTTPS (any method)Third-party API calls, custom webhooks5 MB response (external), 15 MB (Zoho)2,000-5,000,000/day (edition)YesNo
Standalone Functions (REST API)HTTPS POSTExposing Deluge logic as API endpoints10 MB response, 95K chars bodyShares CRM API credit poolYesNo
Scheduled FunctionsInternal triggerBatch operations, periodic syncN/A15-min execution windowNoYes

Rate Limits & Quotas

Per-Execution Limits

Limit TypeValueApplies ToNotes
Max statements executed5,000All Deluge functionsLoops multiply: 3 statements x 100 iterations = 300 consumed [src1]
Max recursive function calls75All Deluge functionsNested function calls within a function [src1]
Max response size10 MBStandalone functions (REST API)Return value size limit [src3]
Max lines of execution200,000Zoho CRM functionsHigher than statement limit; counts include framework overhead [src2]
Max POST body size95,000 charsStandalone functionsURL arguments capped at 5,000 chars [src7]
Max CRM fields per data transfer10Workflow custom functionsData pushed to third-party apps [src5]

Execution Timeouts by Trigger Type

Trigger TypeTimeoutNotes
Custom button click10 secondsUser-facing, must be fast
Validation rule10 secondsSynchronous, blocks record save
Related list10 secondsSynchronous rendering
REST API (standalone function)10 secondsExternal API callers expect quick response
Workflow rule (automation)30 secondsTriggered by record create/update/delete
Blueprint transition30 secondsTriggered during process stage changes
Scheduled function15 minutesBackground execution, longest timeout

[src3]

Daily Limits (Rolling 24-Hour Window)

Limit TypeValueApplies ToNotes
sendmail (email)500/day (Deluge general), 50,000/day (CRM)Email sendingCRM has higher allocation
invokeURL / getUrl / postUrl2,000/day (Deluge general), 5,000,000/day (CRM)External API callsCRM Enterprise/Ultimate have much higher limits
Integration tasks2,000/day (Deluge general)Zoho-to-Zoho API callsEach execution = 1 API credit consumed
SMS1,000,000/dayCRM SMS functionsEnterprise and above

[src1, src2]

API Credit Limits by Edition (Zoho CRM)

EditionBase CreditsPer User LicenseMaximumNotes
Standard5,000+200/license15,000Functions via Extensions only
Professional5,000+200/license20,000Functions via Extensions only
Enterprise / Zoho One20,000+500/license200,000Full function support
Ultimate / CRM Plus20,000+1,000/licenseUnlimitedScales with licenses

[src2, src3]

Authentication

Deluge handles authentication differently depending on the integration type. [src4, src7]

FlowUse WhenToken LifetimeRefresh?Notes
Built-in integration tasksZoho-to-Zoho operationsManaged by platformAutomaticNo explicit auth needed; uses logged-in user context or admin context
Connections (OAuth 2.0)Third-party APIs via invokeURLManaged by connectionAutomatic refreshCreate in Settings > Connections; supports OAuth 2.0 for 100+ services
API KeyExposing standalone functions as REST endpointsNon-expiring (until regenerated)N/AStatic key; admin-only regeneration
OAuth 2.0 (internal)Sharing standalone functions within orgStandard OAuth token lifecycleYesFor internal organizational consumption

Authentication Gotchas

Constraints

Integration Pattern Decision Tree

START -- User needs to script in Zoho Deluge
|-- What kind of operation?
|   |-- Zoho-to-Zoho (e.g., CRM to Books, CRM to Desk)
|   |   |-- Is there a built-in integration task?
|   |   |   |-- YES --> Use integration task (zoho.crm.*, zoho.books.*, etc.)
|   |   |   |   Simplest approach, pre-built wrappers, 1 API credit each
|   |   |   |-- NO --> Use invokeURL with Zoho API + connection
|   |-- Zoho-to-third-party (e.g., CRM to Slack, Stripe, custom API)
|   |   |-- Set up OAuth connection in Settings first
|   |   |-- Use invokeURL with connection parameter
|   |   |-- Response > 5 MB? --> Cannot process in Deluge; use middleware
|   |-- Internal logic only (calculations, validations, field updates)
|       |-- No API calls needed
|       |-- Watch statement limit (5,000) for complex logic
|-- How will it be triggered?
|   |-- User action (button click, validation) --> 10s timeout
|   |-- Automation (workflow, blueprint) --> 30s timeout
|   |-- Scheduled (periodic batch) --> 15min timeout
|   |-- External system (REST API) --> 10s timeout, expose as standalone
|-- Data volume?
|   |-- < 500 records per execution --> OK for single function
|   |-- 500-5,000 records --> Chunk into batches via scheduled functions
|   |-- > 5,000 records --> Use Zoho CRM Bulk API (not Deluge)
|-- Error handling needed?
    |-- YES --> Wrap in try-catch, log errors via info or integration tasks
    |-- Critical failures --> sendmail alert + return error response

Quick Reference

TaskDeluge SyntaxNotes
Get CRM recordzoho.crm.getRecordById("Leads", recordId)Returns MAP; 1 API credit
Search CRM recordszoho.crm.searchRecords("Contacts", "Email:equals:" + email)Returns LIST of MAPs
Create CRM recordzoho.crm.createRecord("Deals", dataMap)Returns MAP with id
Update CRM recordzoho.crm.updateRecord("Accounts", recordId, updateMap)Returns MAP
Delete CRM recordzoho.crm.deleteRecord("Leads", recordId)Returns MAP
HTTP GET (external)invokeurl [url: apiUrl type: GET connection: "conn"]5 MB response limit
HTTP POST (external)invokeurl [url: apiUrl type: POST body: jsonStr headers: headerMap connection: "conn"]Set Content-Type in headers
Send emailsendmail [from: zoho.adminuserid to: email subject: subj message: body]15 MB attachment limit
Log debug outputinfo variableNameVisible in execution logs
Error handlingtry { ... } catch(e) { info e.message; }e.lineNo for line number
Return valuereturn responseMap10 MB max for standalone functions
Loop (list)for each item in myList { ... }Each iteration counts as statements

Step-by-Step Integration Guide

1. Create a custom function in Zoho CRM

Navigate to Setup > Developer Hub > Functions > + Create New Function. Name the function, add arguments, and write Deluge code in the editor. [src7]

// Function: updateAccountRevenue
// Arguments: accountId (bigint), newAmount (decimal)

accountMap = zoho.crm.getRecordById("Accounts", accountId);
currentRevenue = ifnull(accountMap.get("Annual_Revenue"), 0.0);
updatedRevenue = currentRevenue + newAmount;

updateMap = Map();
updateMap.put("Annual_Revenue", updatedRevenue);

response = zoho.crm.updateRecord("Accounts", accountId, updateMap);
info response;
return response;

Verify: Click "Save & Execute Script" with test argument values. Check the execution log for the info output.

2. Associate function with a workflow rule

Go to Setup > Automation > Workflow Rules > create a new rule. Set the trigger, add an instant action > Custom Function > select your function. Map arguments to CRM fields. [src5]

// Workflow-triggered function (30-second timeout)
// Argument mapping: accountId = ${Deals.Account_Name.id}
//                   newAmount = ${Deals.Amount}

accountMap = zoho.crm.getRecordById("Accounts", accountId);
currentRevenue = ifnull(accountMap.get("Annual_Revenue"), 0.0);
updatedRevenue = currentRevenue + newAmount;

updateMap = Map();
updateMap.put("Annual_Revenue", updatedRevenue);
zoho.crm.updateRecord("Accounts", accountId, updateMap);

Verify: Create or update a Deal matching the workflow criteria. Check the Account's Annual_Revenue field for the updated value.

3. Call an external API with invokeURL

Create a Connection first (Settings > Developer Space > Connections), then use invokeURL in your function. [src4]

// Call Slack webhook to notify on deal closure
slackUrl = "https://hooks.slack.com/services/T00/B00/xxx";
payload = Map();
payload.put("text", "Deal Won: " + dealName + " for $" + amount);

response = invokeurl
[
  url: slackUrl
  type: POST
  parameters: payload.toString()
  headers: {"Content-Type": "application/json"}
];

info response;

Verify: Check the Slack channel for the notification message. Check the execution log for the info output showing the API response.

4. Implement error handling with try-catch

Wrap external API calls and record operations in try-catch blocks to handle failures gracefully. [src8]

try
{
  response = invokeurl
  [
    url: apiEndpoint
    type: GET
    connection: "my_api_connection"
    detailed: true
  ];

  statusCode = response.get("responseCode");
  if (statusCode != 200)
  {
    info "API returned " + statusCode + ": " + response.get("responseText");
    sendmail
    [
      from: zoho.adminuserid
      to: "[email protected]"
      subject: "Integration Error: API returned " + statusCode
      message: "Response: " + response.get("responseText")
    ];
  }
  else
  {
    data = response.get("responseText").toJSONList();
    for each record in data
    {
      recordMap = record.toMap();
      // Process each record...
    }
  }
}
catch(e)
{
  info "Error at line " + e.lineNo + ": " + e.message;
  sendmail
  [
    from: zoho.adminuserid
    to: "[email protected]"
    subject: "Deluge Function Error"
    message: "Line: " + e.lineNo + " Error: " + e.message
  ];
}

Verify: Deliberately provide an invalid URL to trigger the catch block. Check execution logs and email for error details.

Code Examples

Python: Call a Zoho CRM Standalone Function via REST API

# Input:  Zoho CRM standalone function URL, API key or OAuth token
# Output: Function execution result

import requests

function_url = "https://www.zohoapis.com/crm/v2/functions/my_function/actions/execute"
params = {
    "auth_type": "apikey",
    "zapikey": "YOUR_API_KEY"
}

payload = {
    "arguments": {
        "accountId": "1234567890",
        "newAmount": 5000.00
    }
}

response = requests.post(
    function_url,
    params=params,
    json=payload,
    headers={"Content-Type": "application/json"}
)

if response.status_code == 200:
    result = response.json()
    print(f"Function result: {result}")
else:
    print(f"Error {response.status_code}: {response.text}")

JavaScript/Node.js: Call Zoho CRM Function via OAuth

// Input:  OAuth access token, function name, arguments
// Output: Function execution result

// npm install axios@1
const axios = require("axios");

const accessToken = process.env.ZOHO_ACCESS_TOKEN;
const functionName = "my_function";

async function callZohoFunction() {
  const url = `https://www.zohoapis.com/crm/v2/functions/${functionName}/actions/execute`;

  const response = await axios.post(url, {
    arguments: {
      accountId: "1234567890",
      newAmount: 5000.00
    }
  }, {
    params: { auth_type: "oauth" },
    headers: {
      Authorization: `Zoho-oauthtoken ${accessToken}`,
      "Content-Type": "application/json"
    }
  });

  console.log("Result:", response.data);
  return response.data;
}

callZohoFunction().catch(console.error);

Deluge: Batch Processing with Statement Limit Awareness

// Input:  Module name, list of record IDs to process
// Output: Count of successfully processed records
// IMPORTANT: This pattern avoids the 5,000 statement limit

module = "Contacts";
processedCount = 0;
errorCount = 0;

// Fetch max ~400 records (10 statements per iteration = 4,000 max)
contacts = zoho.crm.getRecords(module, 1, 200);

for each contact in contacts
{
  try
  {
    email = ifnull(contact.get("Email"), "");
    if (email != "")
    {
      updateMap = Map();
      updateMap.put("Email_Verified", true);
      zoho.crm.updateRecord(module, contact.get("id"), updateMap);
      processedCount = processedCount + 1;
    }
  }
  catch(e)
  {
    errorCount = errorCount + 1;
    info "Error processing " + contact.get("id") + ": " + e.message;
  }
}

info "Processed: " + processedCount + ", Errors: " + errorCount;
return {"processed": processedCount, "errors": errorCount};

Data Mapping

Deluge Data Types Reference

Deluge TypeDescriptionConversion FunctionGotcha
TEXTString values.toString() or toText()Max length varies by context; no explicit limit documented
NUMBERInteger/decimal.toNumber() or toDecimal()Division of integers returns integer (use toDecimal first)
BOOLEANtrue/false.toBoolean()Truthy/falsy coercion differs from JavaScript
DATEDate without time.toDate()Format: yyyy-MM-dd; timezone depends on user settings
DATETIMEDate with time.toDateTime()Format: yyyy-MM-dd hh:mm; 24h format in API
LISTOrdered collection.toJSONList()Zero-indexed; for-each creates new scope
MAPKey-value pairs.toMap()Keys are case-sensitive; .get() returns null for missing keys
FILEBinary file data.toFile()50 MB max in Creator; fetched via invokeURL or getUrl

Data Type Gotchas

Error Handling & Failure Points

Common Error Codes

CodeMeaningCauseResolution
EXECUTION_LIMIT_EXCEEDEDStatement limit (5,000) reachedLoop over large datasetReduce iteration count; chunk into scheduled batches
FUNCTION_CALL_LIMIT_EXCEEDED75 recursive calls exceededDeep recursion or circular function callsFlatten recursive logic; use iteration instead
SOCKET_TIMEOUTinvokeURL timed out at 40sExternal API too slowAdd timeout handling; use async webhook pattern instead
EXECUTION_TIME_EXCEEDEDFunction exceeded trigger timeoutComplex logic in button/validation contextMove heavy logic to scheduled function or workflow
INVALID_DATAMalformed data in API callWrong data type or missing required fieldValidate all inputs with isBlank/ifnull before API calls
AUTHENTICATION_FAILUREConnection OAuth token expired/revokedConnection owner deactivated or token revokedRe-authorize connection; use service account
DAILY_LIMIT_EXCEEDEDDaily API credit quota exhaustedToo many function executions in 24h windowUpgrade edition or optimize to reduce API calls per function
RESPONSE_SIZE_EXCEEDEDResponse larger than 5 MB / 10 MBLarge API response or return valuePaginate API calls; reduce response payload

[src1, src2, src3, src4]

Failure Points in Production

Anti-Patterns

Wrong: Processing all records in a single loop

// BAD -- 1,000 records x 8 statements = 8,000 statements (exceeds 5,000 limit)
allContacts = zoho.crm.getRecords("Contacts", 1, 200);
for each contact in allContacts
{
  email = contact.get("Email");
  phone = contact.get("Phone");
  company = contact.get("Company");
  updateMap = Map();
  updateMap.put("Processed", true);
  updateMap.put("Last_Processed", zoho.currentdate);
  zoho.crm.updateRecord("Contacts", contact.get("id"), updateMap);
  info "Processed: " + contact.get("id");
  // 8 statements per iteration -- exceeds limit quickly
}

Correct: Chunk processing across scheduled functions

// GOOD -- Process in batches of 100, stay within statement limits
batchSize = 100;
page = 1;
contacts = zoho.crm.getRecords("Contacts", page, batchSize);

for each contact in contacts
{
  updateMap = Map();
  updateMap.put("Processed", true);
  zoho.crm.updateRecord("Contacts", contact.get("id"), updateMap);
  // 3 statements per iteration = 300 total for 100 records
}
// For remaining records, trigger next batch via scheduled function

Wrong: No error handling on invokeURL calls

// BAD -- if API fails, function crashes with no logging
response = invokeurl
[
  url: "https://api.example.com/data"
  type: GET
  connection: "example_api"
];
data = response.toJSONList();
for each item in data { /* process */ }

Correct: Wrap invokeURL in try-catch with detailed response

// GOOD -- capture status code, handle errors, log everything
try
{
  response = invokeurl
  [
    url: "https://api.example.com/data"
    type: GET
    connection: "example_api"
    detailed: true
  ];

  if (response.get("responseCode") == 200)
  {
    data = response.get("responseText").toJSONList();
    for each item in data
    {
      itemMap = item.toMap();
      // Process safely
    }
  }
  else
  {
    info "API Error: " + response.get("responseCode");
  }
}
catch(e)
{
  info "Exception: " + e.message + " at line " + e.lineNo;
}

Wrong: Hardcoding API credentials

// BAD -- credentials in script, breaks on environment change
apiKey = "sk_live_abc123def456";
response = invokeurl
[
  url: "https://api.stripe.com/v1/charges"
  type: POST
  headers: {"Authorization": "Bearer sk_live_abc123def456"}
  parameters: chargeMap
];

Correct: Use Zoho Connections for authentication

// GOOD -- OAuth managed by connection, no credentials in code
response = invokeurl
[
  url: "https://api.stripe.com/v1/charges"
  type: POST
  parameters: chargeMap
  connection: "stripe_production"
];
// Connection handles OAuth token refresh automatically

Common Pitfalls

Diagnostic Commands

// Check current API credit usage (Zoho CRM admin)
// Navigate to: Setup > Developer Hub > APIs > Dashboard
// Shows: credits consumed, remaining, per-function breakdown

// Debug a function: add info statements throughout
info "Step 1: Input received - accountId = " + accountId;
info "Step 2: Record fetched - " + recordMap;
info "Step 3: Before update - statement count approx: " + statementCounter;

// Test invokeURL with detailed:true to see full HTTP response
testResponse = invokeurl
[
  url: "https://api.example.com/test"
  type: GET
  connection: "my_connection"
  detailed: true
];
info "Status: " + testResponse.get("responseCode");
info "Headers: " + testResponse.get("responseHeader");
info "Body: " + testResponse.get("responseText");

// Check function execution logs
// Navigate to: Setup > Developer Hub > Functions > select function > Logs
// Shows: execution time, input arguments, output, errors

// Verify connection status
// Navigate to: Setup > Developer Space > Connections
// Shows: connection name, service, status (active/expired), last used

// Monitor scheduled function execution
// Navigate to: Setup > Automation > Schedules > History
// Shows: execution status, start/end time, errors

Version History & Compatibility

ChangeDateImpactNotes
Deluge 2.0 runtime (current)2020Platform upgradeImproved performance, expanded built-in functions, wider product support
API credit system overhaul2024Credit calculation changeTiered consumption for Java/Node.js functions; Deluge remains 1 credit/execution
invokeURL enhancements2024New capabilitiesAdded PATCH, OPTIONS methods; response-format and response-decoding parameters
Try-catch support expanded2023Error handlingAvailable across all Zoho products (previously limited to some)
260+ integration tasks2025Expanded integrationsCoverage across 35 Zoho services
Scheduled functions 15-min timeout2023Increased limitEnables longer-running batch operations

[src3, src4, src6]

When to Use / When Not to Use

Use WhenDon't Use WhenUse Instead
Custom business logic inside any Zoho app (CRM, Creator, Desk, Books)High-volume ETL processing (>5,000 records per batch)Zoho CRM Bulk API or external ETL tool
Automating workflows between Zoho products (CRM to Books, Desk to CRM)Compute-intensive operations (ML, image processing, heavy math)External service via invokeURL + webhook callback
Quick integrations with third-party APIs (Slack, Stripe, custom endpoints)Real-time processing requiring <1s latency on complex logicExternal microservice with direct API integration
Scheduled data sync running under 15 minutesOperations requiring more than 5,000 statement executionsChunk across multiple scheduled functions or use external orchestration
Form validation and data enrichment on record saveStandard/Professional CRM editions without ExtensionsUpgrade to Enterprise or use Zoho Flow for no-code automation

Important Caveats

Related Units