Deluge

A practical reference for writing Zoho CRM Functions in Deluge.

 

Deluge is Zoho's proprietary scripting language and the most deeply integrated language for writing CRM Functions. It has direct access to zoho.crm.* integration tasks as well as native integration tasks for other Zoho services, and first-class support for argument mapping via merge variables.

This guide covers the CRM-specific integration tasks available in Deluge including how to read and write records, fetch modules and organisation details, read CRM variables, access other Zoho services, handle arguments, and return values. For general Deluge syntax (control flow, loops, string manipulation, collections), refer to the Deluge language documentation.

No draft state:

Deluge Functions do not have a draft/deploy workflow. Every save in the editor immediately updates the live Function. Be cautious when editing Functions that are associated with workflows, buttons, or schedules. Changes take effect immediately when you save them. Java, Node.js, and Python Functions have a separate draft and deploy step. See Java, Node.js, Python Language Guide for details.

CRM Integration Tasks

Deluge provides built-in integration tasks under the zoho.crm namespace for performing record operations, bulk processing, related record handling, lead conversion, and file attachments. These tasks are available directly in every Deluge Function. No SDK setup, imports, or connection configuration is required.

Note:

All tasks below accept an optional connection parameter as the last argument. This is only needed when calling CRM from a different Zoho service. Within a CRM Function, you can omit it.

zoho.crm.v8.createRecord

Creates a new record in the specified module.

Syntax:

 

response = zoho.crm.v8.createRecord(<module_name>, <record_values>, <options_map>, <connection>);

Example: Creating a Lead

 

leadinfo = {"Company":"Zylker", "Last_Name":"Williams", "Phone":"+1 678 XXX XXXX", "Email":"will@zylker.com", "Country":"US"};
response = zoho.crm.v8.createRecord("Leads", leadinfo);
info "Created ID: " + response.get("id");

Example: Adding Notes to a Lead

 

notesMap = {"Parent_Id":"2303XXXXXXXXXX", "Note_Title":"Title", "Note_Content":"Note_Description", "$se_module":"Leads"};
response = zoho.crm.v8.createRecord("Notes", notesMap);

Example: Custom Module

 

custominfo = {"Name":"John", "Phone":"+1 678 XXX XXXX", "Email":"john@zylker.com"};
response = zoho.crm.v8.createRecord("Hotels", custominfo);

Response format:

Success:

 

{"Modified_Time":"2018-03-26T14:33:01+05:30", "Modified_By":{"name":"Ben","id":"2303XXXXXXXXXX"}, "Created_Time":"2018-03-26T14:33:01+05:30", "id":"2303XXXXXXXXXX", "Created_By":{"name":"Ben","id":"2303XXXXXXXXXX"}}

Failure:

 

{"code":"MANDATORY_NOT_FOUND", "details":{"api_name":"Last_Name"}, "message":"required field not found", "status":"error"}

zoho.crm.v8.getRecords

Fetches records from the specified module with pagination and sorting options.

Syntax:

 

response = zoho.crm.v8.getRecords(<module_name>, <page>, <per_page>, <query_map>, <connection>);

Example: fetch sorted Contacts

 

query_map = Map();
query_map.put("sort_order", "asc");
query_map.put("sort_by", "First_Name");
response = zoho.crm.v8.getRecords("Contacts", 1, 10, query_map);

Example: Fetch from a Custom Module

 

response = zoho.crm.v8.getRecords("Hotels", 1, 200, Map());

zoho.crm.v8.getRecordById

Fetches a single record using its module and record ID.

Syntax:

 

response = zoho.crm.v8.getRecordById(<module_name>, <record_ID>, <query_value>, <connection>);

Example:

 

response = zoho.crm.v8.getRecordById("Leads", 23033XXXXXXXXXXXXXX);
info response.get("Last_Name");

Tip:

Field names in the response use the field's API name, not the display label. You can find API names in SetupDeveloper HubAPIsAPI Names.

zoho.crm.v8.searchRecords

Searches for records in a module matching specific criteria.

Syntax:

 

response = zoho.crm.v8.searchRecords(<module_name>, <criteria>, <page>, <per_page>, <options_map>, <connection>);

Example: Search by Email

 

response = zoho.crm.v8.searchRecords("CustomModule1", "(Email:equals:john@zylker.com)");

Example: Search Accounts Starting with a Character

 

response = zoho.crm.v8.searchRecords("Accounts", "(Account_Name:starts_with:A)");

Common criteria operators:equals, not_equal, greater_than, less_than, starts_with, contains, between.

Note:

searchRecords returns a maximum of 200 records per call. If your query may match more, implement pagination or narrow the criteria.

zoho.crm.v8.updateRecord

Updates a particular record using its ID in the specified module.

Syntax:

 

response = zoho.crm.v8.updateRecord(<module_name>, <record_ID>, <record_value>, <options_map>, <connection>);

Example:

 

leadinfo = {"Company":"Zylker", "Last_Name":"Stewart", "Phone":"9876XXXXXX", "Email":"stewart@zylker.com"};
response = zoho.crm.v8.updateRecord("Leads", 23033XXXXXXXXXXXXXX, leadinfo);

Note:

Include only the fields you want to update. Fields not included in the map remain unchanged.

zoho.crm.v8.upsert

Updates a record if the ID is provided; creates a new record if not.

Syntax:

 

response = zoho.crm.v8.upsert(<module_name>, <record_values>, <options_map>, <connection>);

Example: Create (no ID)

 

record_values = Map();
record_values.put("Last_Name", "Williams");
record_values.put("Company", "Will Tech");
response = zoho.crm.v8.upsert("Leads", record_values);

Example: Update (with ID)

 

record_values = Map();
record_values.put("Last_Name", "John");
record_values.put("id", 2303XXXXXXXXXXXXXXX);
response = zoho.crm.v8.upsert("Leads", record_values);

zoho.crm.v8.bulkCreate

Creates multiple records simultaneously. Up to 100 records at a time.

Syntax:

 

response = zoho.crm.v8.bulkCreate(<module_name>, <record_list>, <options_map>, <connection>);

Example:

 

createList = List();
createList.add({"Company":"Zylker", "Last_Name":"Daly", "First_Name":"Paul", "Email":"p.daly@zylker.com"});
createList.add({"Company":"Tycoon", "Last_Name":"Richard", "First_Name":"Brian", "Email":"brian@villa.com"});
response = zoho.crm.v8.bulkCreate("Leads", createList);

zoho.crm.v8.bulkUpdate

Updates multiple records simultaneously. Up to 100 records at a time. Each record map must include its id.

Syntax:

 

response = zoho.crm.v8.bulkUpdate(<module_name>, <record_list>, <options_map>, <connection>);

Example:

 

updateList = List();
updateList.add({"id":"3171565000000600001", "Company":"Zylker", "Last_Name":"Daly", "Email":"p.daly@zylker.com"});
updateList.add({"id":"3171565000000600002", "Company":"Tycoon", "Last_Name":"Richard", "Email":"brian@villa.com"});
response = zoho.crm.v8.bulkUpdate("Leads", updateList);

zoho.crm.v8.getRelatedRecords

Fetches records from a submodule (related list) related to a record in a parent module.

Syntax:

 

response = zoho.crm.v8.getRelatedRecords(<submodule_name>, <parent_module>, <parent_record_ID>, <page>, <per_page>, <query_value>, <connection>);

Example: Fetch Notes from a Lead

 

notesinfo = zoho.crm.v8.getRelatedRecords("Notes", "Leads", 23033XXXXXXXXXXXXXX);

Example: Fetch Events from a Custom Module with Pagination

 

eventsinfo = zoho.crm.v8.getRelatedRecords("Events", "Hotels", 23033XXXXXXXXXXXXXX, 1, 3);

zoho.crm.v8.updateRelatedRecord

Updates a record in a submodule related to a record in a parent module.

Syntax:

 

response = zoho.crm.v8.updateRelatedRecord(<submodule_name>, <submodule_record_ID>, <parent_module>, <parent_record_ID>, <record_value>, <connection>);

Example:

 

response = zoho.crm.v8.updateRelatedRecord("Price_Books", 2303XXXXXXXXXXXXXXX, "Products", 4770XXXXXXXXXXXXXXX, {"list_price":200});

zoho.crm.v8.convertLead

Converts a lead into a contact, deal, and account.

Syntax:

 

response = zoho.crm.v8.convertLead(<lead_id>, <values>, <connection>);

Example: Create New Records in Contacts, Deals, and Accounts

 

deal_values = Map();
deal_values.put("Deal_Name", "Jake");
deal_values.put("Closing_Date", "2018-12-06");
deal_values.put("Stage", "Closed Won");
response = zoho.crm.v8.convertLead(2303XXXXXXXXXXXXXXX, {"Deals":deal_values});

Example: Associate to Existing Account and ontact:

 

values_map = Map();
values_map.put("overwrite", true);
values_map.put("Accounts", "2303XXXXXXXXXXXXXXX");
values_map.put("Contacts", "2303XXXXXXXXXXXXXXX");
response = zoho.crm.v8.convertLead(2303XXXXXXXXXXXXXXX, values_map);

zoho.crm.v8.attachFile

Attaches a file to the specified record.

Syntax:

 

response = zoho.crm.v8.attachFile(<module_name>, <record_id>, <file_object>, <connection>);

Example:

 

file_object = invokeUrl[url:"https://assets.example.com/report.pdf" type:GET];
response = zoho.crm.v8.attachFile("Leads", 4770XXXXXXXXXX, file_object);

Note:

Before you can process a file, fetch it using invokeurl or invokeAPI. Deluge cannot operate on local or offline files.

Zoho Service Built-ins

Beyond CRM, Deluge has built-in integration tasks for interacting with other Zoho services directly. Following are a few examples:

NamespaceServiceCommon Operations
zoho.mailZoho MailSend emails with subject, body, attachments
zoho.booksZoho BooksCreate invoices, fetch payments, manage contacts
zoho.invoiceZoho InvoiceCreate and manage invoices
zoho.deskZoho DeskCreate tickets, update ticket status, add comments
zoho.peopleZoho PeopleAccess employee records, manage leave requests
zoho.projectsZoho ProjectsCreate tasks, update milestones, log time entries
zoho.calendarZoho CalendarCreate events, manage calendars

Example: Creating a Zoho Books Invoice from a Deal

 

invoiceData = Map();
invoiceData.put("customer_id", customerId);
invoiceData.put("line_items", lineItems);
response = zoho.books.createRecord("Invoices", orgId, invoiceData);
info "Invoice created: " + response;

For more details about integration tasks, refer to the Deluge Integration Guide.

Note:

For calling external third-party APIs (non-Zoho), use invokeurl with a configured Connection. See Using Connections below and Connections for details.

Zoho Variables

Deluge exposes a set of system-level variables under the zoho namespace. These are read-only values that are resolved at runtime. They provide information about the current user, organization, and execution environment without requiring an API call.

VariableTypeDescription
zoho.currentdateDateThe current date in the org's timezone
zoho.currenttimeDate-TimeThe current date and time in the org's timezone
zoho.loginuseridLongThe record ID of the user who triggered the Function
zoho.loginuserStringThe email address of the user who triggered the Function
zoho.adminuseridLongThe record ID of the CRM org's super admin
zoho.adminuserStringThe email address of the CRM org's super admin
zoho.ipaddressStringThe IP address of the user who triggered the Function

Example: Stamping an Audit Trail on Record Update

 

updateMap = Map();
updateMap.put("Last_Modified_By_Function", zoho.loginuser);
updateMap.put("Last_Function_Run", zoho.currenttime.toString("yyyy-MM-dd HH:mm:ss"));
zoho.crm.v8.updateRecord("Deals", dealId.toLong(), updateMap);

Example: Conditional Logic based on the Executing User

 

if (zoho.loginuserid == zoho.adminuserid)
{
    info "Executed by admin — full access.";
}
else
{
    info "Executed by: " + zoho.loginuser;
}

Date formatting:zoho.currentdate and zoho.currenttime support .toString("<pattern>") for formatting — e.g. zoho.currentdate.toString("dd-MMM-yyyy") produces 05-Mar-2026.

Tasks

Deluge provides built-in task statements for sending emails and making HTTP calls. These are standalone language constructs, not methods that belong to a namespace.

sendmail

Sends an email from the CRM org. Commonly used in Automation and Button Functions to notify contacts, owners, or external recipients.

Syntax:

 

sendmail
[
    from: <userId or email>
    to: <recipientEmail>
    subject: <subjectString>
    message: <bodyString>
]

Parameters:

ParameterRequiredDescription
fromYesThe sender email address. Use zoho.loginuserid
toYesRecipient email address (String)
subjectYesEmail subject line
messageYesEmail body (supports HTML)
ccNoCC recipients (comma-separated String)
bccNoBCC recipients

Example: Notify the Deal Owner when a Deal is Won

 

ownerEmail = deal.get("Owner").get("email");
sendmail
[
    from: zoho.loginuserid
    to: ownerEmail
    subject: "Deal Won: " + deal.get("Deal_Name")
    message: "<h3>Congratulations!</h3><p>Your deal <b>" + deal.get("Deal_Name") + "</b> worth $" + deal.get("Amount") + " has been marked as Closed Won.</p>"
]

Note:

sendmail uses the org's email sending quota. For high-volume or transactional emails, consider using an external service via invokeurl.

invokeurl

Sends an HTTP request to any URL, including external APIs, webhooks, and internal services. This is the primary mechanism for third-party integrations in Deluge.

Syntax:

 

response = invokeurl
[
    url: <endpointURL>
    type: <GET | POST | PUT | PATCH | DELETE>
    parameters: <bodyMap or bodyString>
    headers: <headersMap>
    connection: <connectionLinkName>
    content-type: <mimeType>
]

Parameters:

ParameterRequiredDescription
urlYesThe target endpoint URL
typeYesHTTP method: GET, POST, PUT, PATCH, DELETE
parametersNoRequest body, a Map (auto-serialised) or raw String
headersNoA Map of HTTP header key-value pairs
connectionNoThe link name of a configured Connection (for OAuth2 / API key auth). See Using Connections.
content-typeNoMIME type of the request body (e.g. application/json, application/x-www-form-urlencoded)

Returns: The response body as a String. If the response is JSON, Deluge auto-parses it into a Map or List.

Example: POST JSON to an External Webhook

 

payload = Map();
payload.put("event", "deal_closed");
payload.put("deal_name", deal.get("Deal_Name"));
payload.put("amount", deal.get("Amount"));

response = invokeurl
[
    url: "https://example.com/crm-events"
    type: POST
    parameters: payload.toString()
    content-type: "application/json"
];
info response;

Example: GET with Headers and a Connection

 

headers = Map();
headers.put("Accept", "application/json");

response = invokeurl
[
    url: "https://api.example.com/v2/contacts?email=" + contactEmail
    type: GET
    headers: headers
    connection: "example_api"
];
info response.get("name");

Tip:

When calling APIs that require authentication, always use a Connection rather than hardcoding API keys in headers. See Using Connections.

invokeAPI

The invokeAPI task is an HTTP client that allows you to access and modify data across Zoho services using their APIs. Unlike invokeurl, where you specify the complete URL, invokeAPI requires only the API path. The appropriate Zoho service domain is resolved automatically based on the organization’s data center, ensuring the request works across all supported data centers.

Note:

Each invokeAPI execution triggers an API call in the back-end. These calls are deducted from your overall external calls limit. The system counts actual executions, not the number of times the task appears in the script.

Syntax:

 

response = invokeapi
[
    service: <zohoServiceName>
    path: <apiPath>
    type: <GET | POST | PUT | PATCH | DELETE | OPTIONS>
    parameters: <queryParams>
    body: <requestBody>
    headers: <headersMap>
    connection: <connectionLinkName>
    response-format: <FILE | COLLECTION | STRING | NONE | DEFAULT>
    response-decoding: <encodingScheme>
];

Parameters:

ParameterRequiredTypeDescription
serviceYesTextThe Zoho service name. Allowed values: zohocrm, zohobooks, zohoinvoice, zohobilling, zohoinventory, zohobookings, zohocreator, zohoworkdrive
pathYesTextThe URL path excluding the base URL. For example, if the full URL is https://www.zohoapis.com/crm/v8/Leads, the path is /crm/v8/Leads
typeNoConstantHTTP method: GET, POST, PUT, PATCH, DELETE, OPTIONS. Default: GET
parametersNoText / Key-ValueQuery strings appended to the URL for filtering or processing
bodyNoText / File / Key-ValueThe request body. Supports text/plain, application/x-www-form-urlencoded, multipart/form-data, application/json, application/octet-stream
headersNoKey-ValueHTTP header key-value pairs including content-type
connectionNoTextThe connection link name. Optional when calling within the same service (e.g. calling CRM APIs from a CRM Function). Required when calling a different Zoho service (e.g. calling Zoho Books from CRM) or when you need specific scopes. Customers can still use a connection even within the same service if they need fine-grained scope control.
response-formatNoTextReturn type: FILE, COLLECTION, STRING, NONE, DEFAULT. Default: DEFAULT. Set to NONE to discard the response
response-decodingNoTextCharacter encoding for decoding the response. Default: UTF-8

Response helpers:

MethodDescription
response.statusReturns the HTTP status code (e.g. 200, 400)
response.headersReturns the response headers as a Map

Timeouts: The task throws a "socket timeout error" if the API takes more than 40 seconds to respond. The default connection timeout is 10 seconds, and the connection request timeout is 5 seconds.

invokeAPI vs invokeurl

AspectinvokeAPIinvokeurl
TargetZoho services onlyAny URL (external or Zoho)
URL handlingPath only (domain resolved by data center)Full URL required
Data center awareYes (automatically routes to correct DC)No (you must use the correct domain)
Use whenCalling Zoho APIs (CRM, Books, Inventory, etc.)Calling external third-party APIs

Sending Body Data

The body parameter supports different formats depending on the content type:

JSON body: Convert to Text using toString()

 

data = Map();
data.put("Last_Name", "Smith");
data.put("Company", "Acme Corp");
data.put("Email", "smith@acme.com");

response = invokeapi
[
    service: zohocrm
    path: "/crm/v8/Leads"
    type: POST
    body: data.toString()
    headers: {"content-type": "application/json"}
];

File upload: Use the param-name / param-value format

 

response = invokeapi
[
    service: zohocrm
    path: "/crm/v8/Leads/" + recordId + "/Attachments"
    type: POST
    body: {{"param-name": "file", "param-value": fileVariable}}
];

Key-Value body: For application/x-www-form-urlencoded or multipart/form-data

 

// Simple key-value (text)
bodyData = {{"param-name": "field_name", "param-value": "field_value"}};

// With content-type and encoding
bodyData = {{"param-name": "field_name", "param-value": "field_value", "content-type": "text/plain", "encoding-type": "UTF-8"}};

// List of key-value pairs
bodyList = List();
bodyList.add({"param-name": "name", "param-value": "Hard Drive"});
bodyList.add({"param-name": "file", "param-value": fileObject});

Note:

If content-type and encoding-type are not specified in key-value body data, the defaults are text/plain and UTF-8 respectively.

Example: Fetch Leads from CRM

 

response = invokeapi
[
    service: zohocrm
    path: "/crm/v8/Leads"
    type: GET
];
info response;

Since the Function runs within Zoho CRM, no connection is required. The task authenticates automatically using the current CRM session.

Example: Update a CRM Record with JSON Body

 

updateData = Map();
updateData.put("Stage", "Closed Won");
updateData.put("Closing_Date", zoho.currentdate.toString("yyyy-MM-dd"));

response = invokeapi
[
    service: zohocrm
    path: "/crm/v8/Deals/" + dealId
    type: PUT
    body: updateData.toString()
    headers: {"content-type": "application/json"}
];
info "Status: " + response.status;

Example: Upload an Attachment to a CRM Record

 

// Fetch the file
attachment = invokeurl
[
    url: "https://example.com/files/report.xls"
    type: GET
];

recordId = "2689962xxxxx509150";

response = invokeapi
[
    service: zohocrm
    path: "/crm/v8/Leads/" + recordId + "/Attachments"
    type: POST
    body: {{"param-name": "file", "param-value": attachment}}
];
info response.status;

Example: Using a Connection (Optional for Same-Service Calls)

When you need specific OAuth scopes or want explicit scope control, you can pass a connection even for CRM-to-CRM calls:

 

response = invokeapi
[
    service: zohocrm
    path: "/crm/v8/Deals"
    type: GET
    connection: "zohocrm_connection"
];
info response;

Tip:

Use invokeAPI when calling Zoho services. It automatically resolves the appropriate service domain based on the organization’s data center. Use invokeurl for external third-party APIs. For calling other Zoho services (Books, Desk, etc.) from CRM, a connection is required. See Using Connections for setup details.

Using Connections

Connections store OAuth2 tokens or API keys securely within Zoho CRM. When you use a Connection with invokeurl, invokeAPI, Integration Tasks, etc. Deluge automatically adds the required authorization headers, so you do not need to handle access tokens in your code.

Creating a Connection

Connections are configured in SetupDeveloper SpaceConnections. Each Connection has a unique link name that you use to reference it in your code.

There are three types:

TypeUse CaseHow Auth is Handled
Zoho OAuthCalling Zoho APIs (CRM v2 REST API, other Zoho products)Zoho handles token refresh automatically
Custom OAuth2External APIs with OAuth2 (Google, Slack, etc.)You provide client ID, secret, auth/token URLs; Zoho manages refresh
API Key / Basic AuthExternal APIs with static credentialsYou provide the key; Zoho passes it in headers

Using a Connection in invokeurl

Reference the Connection by its link name in the connection parameter:

 

response = invokeurl
[
    url: "https://www.exampleapis.com/calendar/v3/calendars/primary/events"
    type: GET
    connection: "example_calendar"
];
info response;

Deluge resolves the Connection at runtime, attaches the appropriate Authorization header, and handles token refresh for OAuth2 Connections transparently.

Example: Creating a to-do Card via OAuth2 Connection

 

cardData = Map();
cardData.put("name", deal.get("Deal_Name") + " — Follow Up");
cardData.put("idList", "60f1a2b3c4d5e6f7a8b9c0d1");

response = invokeurl
[
    url: "https://api.example.com/1/cards"
    type: POST
    parameters: cardData.toString()
    content-type: "application/json"
    connection: "trello_oauth"
];
info "Created card: " + response.get("shortUrl");

Logging and Error Handling

info()

info is the primary logging statement in Deluge. It writes output to the Logs panel in the Function Editor and to the execution history. Use it to trace values, debug logic, and confirm execution flow.

Syntax:

 

info <expression>;

Examples:

 

info "Function started";
info "Deal Name: " + deal.get("Deal_Name");
info deal; // logs the entire map
info "Record count: " + records.size();

info accepts any data type, including Strings, numbers, Maps, Lists, Booleans. Maps and Lists are printed in their string representation.

Tip:

In production Functions, keep info statements targeted. Excessive logging can make the Logs panel hard to read and may slow execution marginally. Consider removing or commenting out debug info statements before deploying.

try / catch

Deluge supports try - catch blocks for handling runtime errors, such as failed API calls, null values, type mismatches, and other exceptions.

The catch block accepts an exception variable (e), that stores information about the runtime error. You can use this variable to access details such as the line number where the error occurred (e.lineNo) and the error message (e.message). Printing e displays both values together.

Syntax:

 

try
{
    // code that may fail
}
catch (e)
{
    // handle the error
    info "Error: " + e;
}

Example: Handling a Failed External API Call

 

try
{
    response = invokeurl
    [
        url: "https://api.example.com/data"
        type: GET
        connection: "example_api"
    ];
    info "API response: " + response;
}
catch (e)
{
    info "API call failed: " + e;
    // Optionally update a record with the error status
    errorMap = Map();
    errorMap.put("Integration_Status", "Failed");
    errorMap.put("Error_Message", e.toString());
    zoho.crm.v8.updateRecord("Deals", dealId.toLong(), errorMap);
}

Example: Guarding against Null Values

 

try
{
    contactEmail = deal.get("Contact_Name").get("Email");
    info "Contact email: " + contactEmail;
}
catch (e)
{
    info "No contact linked to this deal — skipping email.";
}

throw

Use throw to explicitly raise an error and halt execution. This is useful in Validation Rule Functions or when a precondition fails.

Syntax:

 

throw "<errorMessage>";

Example: Validation Before Proceeding

 

if (deal.get("Amount").toDecimal() <= 0)
{
    throw "Deal amount must be greater than zero.";
}

When throw is executed inside a try block, the catch block handles it. Outside a try block, it terminates the Function and the error appears in the execution logs.

Note:

In Workflow-triggered (Automation) Functions, an unhandled throw causes the Function to fail silently from the end user's perspective. The error is recorded only in the execution logs. In Button Functions, the thrown message may surface in the UI response depending on how the return is structured.

Data Types

Deluge is a dynamically typed language, so you do not need to declare types for local variables. However, Function signatures require explicit type annotations for arguments and return values.

TypeDescriptionCRM Field Mapping
TextSequence of characters enclosed in double quotesName, Email, Single Line, Multi Line
NumberInteger values (no decimals). Operations with decimals produce a Decimal resultNumber, Auto Number
DecimalDecimal values for currency and percentagesCurrency, Percentage
Booleantrue or false (not enclosed in quotes, not case-sensitive)Checkbox (Decision Box)
Date-TimeDate and time values enclosed in single quotes. Date without time defaults hours/mins/seconds to 0Date, Date-Time, Prediction
TimeTime values in 12-hour or 24-hour format, independent of dateTime
ListOrdered collection of elements of any type, accessed by indexMultiselect, Checkbox
Key-ValueCollection of unique key-value pairs. Duplicate keys overwrite the previous valueCRM API responses (zoho.crm.getRecord returns Key-Value)
CollectionCan act as either a List or a Key-Value, but not both at the same time
FileFile data fetched from the web or cloud service via invokeurl / invokeAPIAttachments

Note:

null is a built-in constant with no specific value and does not belong to any data type.

CRM Context: Why Key-Value and List matter

CRM API responses (zoho.crm.getRecord, zoho.crm.v8.searchRecords, etc.) return Key-Value maps and Lists of maps. Most CRM Function logic revolves around reading fields from these maps and building maps to create or update records:

 

// getRecord returns a Key-Value map
deal = zoho.crm.getRecord("Deals", dealId);
info deal.get("Deal_Name");

// searchRecords returns a List of Key-Value maps
leads = zoho.crm.v8.searchRecords("Leads", "(Company:equals:Acme)");
for each lead in leads
{
    info lead.get("Last_Name");
}

// Building a Key-Value map for record creation
data = Map();
data.put("Last_Name", "Smith");
data.put("Company", "Acme Corp");
zoho.crm.v8.createRecord("Leads", data);

For the complete data type reference, built-in methods, and collection operations, refer to the Deluge Data Types documentation.

Accessing Arguments via the input Map

In Deluge, arguments declared in the Function (via the Arguments panel or the code signature) are accessible inside the script via the input map.

How it works:

  1. Declare Function arguments either in the Arguments panel or directly in the Function signature:
 

   void automation.stamp_closure_summary(string dealId, string dealName, string amount)

  1. When the Function is triggered (by a Workflow Rule, Button, etc.), the trigger resolves each argument from the configured merge variable mapping (e.g. dealId${Deals.Deals Id}).
  2. Inside the script, arguments are available by name directly:
 

   info dealId; // the value mapped from ${Deals.Deals Id}
   info dealName; // the value mapped from ${Deals.Deal Name}
   info amount; // the value mapped from ${Deals.Amount}

  1. Alternatively, you can access arguments via the input map:
 

   info input.dealId;
   info input.dealName;

Argument types: String, Integer, Boolean, Map, List. Workflow Rule merge variables always pass values as Strings. Convert them to the required data type within the Function, if needed (e.g. amount.toLong(), amount.toDecimal()).

Important:

In Deluge, Function arguments are not passed automatically. You must declare them and map them when associating the Function with its trigger. This is different from Java, Node.js, and Python where trigger context is delivered automatically via basicIO. See Java, Node.js, Python Language Guide for that approach.

Returning Values per Category

A Deluge Function’s return type is determined by its category and declared in the Function signature. The value you return, and how Zoho CRM processes it, depends on the Function category.

CategoryReturn TypeWhat to Return
AutomationvoidNothing. The Function performs side effects only.
ButtonstringA message String displayed as a modal in the CRM UI.
SchedulevoidNothing. The Function performs batch processing silently.
StandalonestringA String value. If exposed as REST API, use crmAPIResponse for full HTTP control.
Related ListstringAn XML string that CRM parses and renders as a related list.
SignalsstringA value forwarded to the Signals API to raise a notification.
Validation RulemapA Map with pass/fail status and error message.

Example: Button Function Returning a Confirmation Message

 

string button.sync_to_erp(string dealId, string dealName)
{
    // ... sync logic here ...
    return "Deal '" + dealName + "' synced to ERP successfully.";
}

Example: Automation Function (void return)

 

void automation.stamp_closure_summary(string dealId, string dealName, string amount)
{
    summary = "Deal " + dealName + " closed for $" + amount;
    updateMap = Map();
    updateMap.put("Closure_Summary", summary);
    zoho.crm.v8.updateRecord("Deals", dealId.toLong(), updateMap);
    info "Updated closure summary.";
}

What's Next?