Zoho: Process multiple API requests in a single call
Zoho compositeRequests.createCompositeRequest: arguments, response, policy and SDK examples.
← Composite requests operations · Get started
Operation zoho.createcompositerequest
Provider route: POST /crm/v8/__composite_requests. Alter supplies the connection’s credentials and routing.
Call through Alter
Section titled “Call through Alter”Install @alter-ai/sdk @alter-ai/zoho with npm, or alter-sdk-zoho with pip. Supply your connected customer’s grant ID and the arguments described below.
import { App } from "@alter-ai/sdk";import { ZohoIntegration } from "@alter-ai/zoho";
async function execute(input: Parameters<ZohoIntegration["compositeRequests"]["createCompositeRequest"]>[0]) { const app = new App({ apiKey: process.env.ALTER_API_KEY! }); try { const provider = new ZohoIntegration(app, { grantId: process.env.PROVIDER_GRANT_ID! }); const call = await provider.compositeRequests.createCompositeRequest(input); const result = await call.wait(); return result.bodyJson(); } finally { await app.close(); }}import osfrom alter_sdk import Appfrom alter_sdk_zoho import ZohoIntegration
async def execute(arguments): async with App(api_key=os.environ["ALTER_API_KEY"]) as app: provider = ZohoIntegration(app, {"grant_id": os.environ["PROVIDER_GRANT_ID"]}) call = await provider.composite_requests.create_composite_request(arguments) result = await call.wait() return result.body_json()| Field | Type | Presence | Description and constraints |
|---|---|---|---|
$ | object | Root | Additional keys: not allowed |
body | object | Required within parent | Specify the composite request configuration, including execution options and the array of sub-requests to process. Additional keys: not allowed |
body.__composite_requests | array | Required within parent | Specify the API requests to execute as sub-requests within the composite call. Maximum items: 5 |
body.__composite_requests[] | object | Each item | Each object represents an individual API sub-request, including the HTTP method, URI, and optional headers, parameters, and body. Additional keys: not allowed |
body.__composite_requests[].body | object | Optional | Specify the request body for the sub-request. > Note > - Using References in Composite API Requests: You can reference the output of one sub-request in another within the same API call. > - Reference Structure: `@{sub_request_id:JSONPath}` > Where, > - `sub_request_id` is the ID of the sub-request whose response you want to reference. > - `JSONPath` is the path to the specific field in that response. > For example, if you create a Lead in one sub-request (sub_request_id : 1) and need to update it in another, you can use `@{1:$.data[0].details.id}` to dynamically fetch the Lead ID from sub-request 1 and use it in sub-request 2 to modify the same record. > - The `rollback_on_fail` and `parallel_execution` keys cannot both be set to `true`. If both are enabled, the API returns the `AMBIGUITY_DURING_PROCESSING` error. > - All Delete APIs (except Notification APIs) support only record IDs in the URL. Bulk delete operations are not supported. > - When `rollback_on_fail` is `false`: > - Workflows, approvals, and other automation actions are triggered as intended. > - The Composite API consumes one API credit. > - When `rollback_on_fail` is `true`: > - Workflows > - Automation actions execute only after all sub-requests complete successfully and no rollback occurs. If one or more sub-requests fail and a rollback happens, the automation actions are not triggered. > - For example, consider the case where a workflow is triggered every time a lead is created with the company name starting with ‘S’. In sub-request 1, a lead is created, whose Company name starts with ‘S’, and sub-request 2 edits the newly created record’s company name so that it does not start with ‘S’. Only after executing both the sub-requests the workflow will be executed. But in this case, the workflow will not be triggered because the newly created Lead’s company name is already updated in sub-request 2, and the criterion for the workflow is not met. Consider another case, where in sub-request 1, a lead is created, whose Company name is ‘Silicon Solutions’, and sub-request 2 edits this newly created record’s website. If none of the other sub-requests change the company name of this newly created record, after executing all the sub-requests successfully, the workflow will be triggered. > - When a rollback occurs, the Composite API consumes one API credit. > - When all sub-requests succeed, the Composite API consumes two API credits. > - Each Composite API request consumes five concurrency credits, regardless of the number of sub-requests. > - Each composite API reduces the sub-concurrency by one, while the sub-requests consume their respective sub-concurrencies. ### Allowed APIs The following table gives the list of APIs allowed in a composite request. For these APIs, there are restrictions on the number of records that you can create, update, or delete in a composite request. | API | No. of records allowed | | --- | --- | | Get Org, Get Metadata, Convert a Lead, Get Layout Rules, Get Validation Rules, Get Custom Links, Get/Add/Update Roles, Get Profiles, Get Records’ Count, Get/Update Blueprint, Get Variables/Variable Groups, Get Tags, Add/Remove Tags for a record, Get List of Attachments, Delete Photo, Get Currencies, Get Shared Record Details, Get Assignment Rules, Get/Add/Update Pipeline, Get Wizards, Get List of From Addresses, Delete Notifications | No Restriction | | Add/Update/Delete Users, Update/Delink Related Records, Add/Delete Variables, Create/Update/Delete Notes, Create/Update/Merge Tags, Add/Update Currency, Add/Update/PATCH Notifications, Create/Update/Upsert/Delete Records | 1 | | Get Territories, Get Notes, Get Email/Inventory Templates, Get Notifications, Get/Search Records, Get Related Records, Get records through a COQL query, Get Deleted Records, Get Users | 25 | Additional keys: allowed |
body.__composite_requests[].headers | object | Optional | Specify the HTTP headers for the sub-request. The authorization and x-crm-org headers are restricted and cannot be used. Additional keys: allowed |
body.__composite_requests[].method | string | Required within parent | Specify the HTTP method for the corresponding sub-request. Possible values: GET - Retrieve data from the API. POST - Create a new resource. PUT - Update an existing resource. DELETE - Remove a resource. PATCH - Partially update a resource. One of: GET, POST, PUT, DELETE, PATCH |
body.__composite_requests[].params | object | Optional | Specify the parameters for the sub-request. Additional keys: allowed |
body.__composite_requests[].sub_request_id | string | Optional | Specify a unique identifier for the sub-request. Use this ID to reference the output of this sub-request. The accepted regex is `[a-zA-Z0-9][a-zA-Z0-9_]`. Maximum length: 100 Pattern: [a-zA-Z0-9][a-zA-Z0-9_] |
body.__composite_requests[].uri | string | Required within parent | Specify the URI path of the corresponding sub-request. The URI must follow the pattern /crm/{version}/{endpoint} with the regex `/crm(/.)?/v[0-9]+([.][0-9]+)?/.`. Maximum length: 2048 Pattern: /crm(/.)?/v[0-9]+([.][0-9]+)?/. |
body.parallel_execution | boolean | Optional | Specify whether to process all independent sub-requests (sub-requests with no dependencies/references) in parallel. The default value is true. If “rollback_on_fail” is true, then the default value of this key is false. Possible values: true - Execute independent sub-requests in parallel. false - Execute sub-requests sequentially. This key cannot be true when rollback_on_fail is true. Default: true |
body.rollback_on_fail | boolean | Optional | Specify whether to rollback the composite API request if any of the sub-requests fail. The default value is false. Possible values: true - Rollback all operations if any sub-request fails. Workflow automation actions execute only after all sub-requests succeed. false - Process each sub-request independently without rollback. This key cannot be true when parallel_execution is true. Default: false |
Response
Section titled “Response”Response media type: application/json. The table describes the pinned successful response. Referenced models link to their complete fields.
| Field | Type | Presence | Description and constraints |
|---|---|---|---|
$ | JSON | Root | |
$ (anyOf 1) | object | Alternative | Contains the successful response for a composite request where all sub-requests were executed successfully. Additional keys: not allowed |
$ (anyOf 1).__composite_requests | array | Required within parent | Contains the response for each sub-request in the composite call. Maximum items: 5 |
$ (anyOf 1).__composite_requests[] | object | Each item | Each object represents the response details for an individual sub-request, including the status code, headers, and body from the wrapped API call. Additional keys: not allowed |
$ (anyOf 1).__composite_requests[].code | string | Required within parent | Represents the response code for the sub-request. Possible values: SUCCESS - The sub-request was executed successfully. Known values: SUCCESS |
$ (anyOf 1).__composite_requests[].details | object | Required within parent | Contains the detailed response information for the sub-request, including the HTTP response from the wrapped API call. Additional keys: not allowed |
$ (anyOf 1).__composite_requests[].details.response | object | Required within parent | Contains the response details from the wrapped API call, including the status code, headers, and body. Additional keys: not allowed |
$ (anyOf 1).__composite_requests[].details.response.body | object | Required within parent | Contains the response body from the wrapped API call. Additional keys: allowed |
$ (anyOf 1).__composite_requests[].details.response.headers | object | Required within parent | Contains the response headers from the wrapped API call. Additional keys: allowed |
$ (anyOf 1).__composite_requests[].details.response.status_code | JSON | Required within parent | |
$ (anyOf 1).__composite_requests[].details.response.status_code (anyOf 1) | integer | Alternative | Represents the status code from the wrapped API call. Format: int32 |
$ (anyOf 1).__composite_requests[].details.response.status_code (anyOf 2) | string | Alternative | Pattern: ^-?[0-9]+(?:.[0-9]+)?(?:[eE][+-]?[0-9]+)?$ |
$ (anyOf 1).__composite_requests[].message | string | Required within parent | Represents the response message for the sub-request. Maximum length: 1000 |
$ (anyOf 1).__composite_requests[].status | string | Required within parent | Represents the status of the sub-request execution. Possible values: success - The sub-request was processed successfully. Known values: success |
$ (anyOf 2) | object | Alternative | Contains the partial success response when some sub-requests succeed and others fail in the composite call. Additional keys: not allowed |
$ (anyOf 2).__composite_requests | array | Required within parent | Contains the mixed success and error responses for individual sub-requests. Each item corresponds to a sub-request and indicates whether it succeeded or failed. Maximum items: 5 |
$ (anyOf 2).__composite_requests[] | object | Each item | Each object represents the response for an individual sub-request, which may indicate either success or error based on the execution result. Additional keys: allowed |
Policy, approvals and errors
Section titled “Policy, approvals and errors”SDK function policy ID: zoho.createcompositerequest. Catalog operation: createCompositeRequest. Rules can name either ID; function rules distinguish managed calls and conservatively cover raw calls sharing the route. Existing grant permissions and policy rules apply. wait() returns an immediate result or waits for a required approval; it never approves the request itself. Persist the approval ID to resume after a restart.
Refused by default. This operation leaves the caller holding a credential (Marked: a sub-request can be GET /settings/variables, GET /settings/automation/webhooks/{id} or GET /actions/watch, each of which reads a stored credential, and the refusal matches the outer route only.), so Alter refuses it on every connection with credential_minting_refused unless an organization admin allows it: a credential_minting rule naming provider zoho and operation zoho.createcompositerequest (or createCompositeRequest). See Allow an operation that hands over a credential.
Provider errors retain their response; JSON decoding raises ProviderAPIError for provider failures. ManagedOperationError identifies contract/input/retention errors. See error handling and provider-specific behavior. Sensitive input may be refused before approval storage. A decoding error never resubmits a write.