- Getting started
- Notifications
- Licensing
- Troubleshooting
- Coding agents
- Connector Builder
- Act! 365
- ActiveCampaign
- Active Directory - Preview
- Adobe Acrobat Sign
- Adobe PDF Services
- Agent 2 Agent - Preview
- Amazon Bedrock
- Amazon Connect
- Amazon Polly
- Amazon SES
- Amazon Transcribe
- Amazon Web Services
- Anthropic Claude
- Asana
- AWeber
- Azure AI Document Intelligence
- Azure Defender for Cloud
- Azure Maps
- BambooHR
- Box
- Brevo
- Calendly
- Campaign Monitor
- Cisco Webex Teams
- Citrix Hypervisor
- Citrix ShareFile
- Clearbit
- Confluence Cloud
- Constant Contact
- Coupa
- CrewAI – Preview
- Customer.io
- Database Hub
- Databricks - Preview
- Databricks Agent
- Datadog
- DeepSeek
- Deputy
- Discord - Preview
- DocuSign
- Drip
- Dropbox
- Dropbox Business
- Egnyte
- Epic FHIR - Preview
- Eventbrite
- Exchangerates
- Exchange Server - Preview
- Expensify
- Facebook
- Freshbooks
- Freshdesk
- Freshsales
- Freshservice
- GetResponse
- GitHub
- Gmail
- Google Cloud Platform
- Google Docs
- Google Drive
- Google Forms - Preview
- Google Maps
- Google Sheets
- Google Speech-to-Text
- Google Text-to-Speech
- Google Tasks - Preview
- Google Vertex
- Google Vision
- Google Workspace
- GoToWebinar
- Greenhouse
- Hootsuite
- HTTP
- HTTP Webhook
- Hubspot CRM
- HubSpot Marketing
- HyperV - Preview
- Icertis
- iContact
- Insightly CRM
- Intercom
- Jina.ai
- Jira
- Keap
- Klaviyo
- LinkedIn
- Mail
- Mailchimp
- Mailgun
- Mailjet
- MailerLite
- Marketo
- MCP
- Microsoft 365
- Microsoft Azure
- Microsoft Azure Active Directory
- Microsoft Azure AI Foundry
- Microsoft Azure OpenAI
- Microsoft Azure Sentinel
- Microsoft Dynamics 365 CRM
- Microsoft OneDrive & Sharepoint
- Microsoft Outlook 365
- Microsoft Power Automate
- Microsoft Sentiment
- Microsoft Sentinel Threat Intelligence
- Microsoft Teams
- Microsoft Translator
- Microsoft Vision
- Miro
- NetIQ eDirectory
- Nvidia NIM
- Okta
- OpenAI
- OpenAI V1 Compliant LLM
- Oracle Eloqua
- Oracle NetSuite
- PagerDuty
- PayPal
- PDFMonkey
- Perplexity
- Pinecone
- Pipedrive
- QuickBooksOnline
- Quip
- Salesforce
- Salesforce Agentforce & Flows
- Salesforce Marketing Cloud
- SAP BAPI
- SAP Cloud for Customer
- SAP Concur
- SAP OData
- SendGrid
- ServiceNow
- Shopify
- Slack
- SmartRecruiters
- Smartsheet
- Snowflake
- Snowflake Cortex
- Stripe
- Sugar Enterprise
- Sugar Professional
- Sugar Sell
- Sugar Serve
- System Center - Preview
- TangoCard
- Todoist
- Trello
- Twilio
- TypeSafe - Preview
- UiPath Apps - Preview
- UiPath Data Fabric
- UiPath Test Manager
- UiPath GenAI Activities
- UiPath Orchestrator
- X (formerly Twitter)
- Xero
- watsonx.ai
- WhatsApp Business
- WooCommerce
- Workable
- Workday
- Workday REST
- VMware ESXi vSphere
- YouTube
- Zendesk
- Zoho Campaigns
- Zoho Desk
- Zoho Mail
- Zoom
- ZoomInfo
Scripts
Configure Connector Builder scripts that run JavaScript before or after API requests, for every request in a connector or for a single resource, and the order in which they run.
Connector Builder lets you write JavaScript that runs before or after the API requests made by your connector. Use pre-request scripts to modify outgoing requests and post-request scripts to process incoming responses. Scripts on the Global Scripts tab run for every request the connector makes, and scripts on a resource's Scripts tab run only for that resource.
When to use scripts
Scripts are useful when you need to customize how your connector calls the provider, such as:
- Injecting or overriding request headers, parameters, or body before sending
- Dynamically constructing the vendor URL based on configuration values
- Transforming a vendor response body before it is returned to the workflow
- Stopping a request based on custom conditions without calling the vendor API
Scripts for a single resource
Each resource also has its own Scripts tab, alongside Parameters, Request fields, Response fields, and Activity designer. It provides the same Pre-request script and Post-request script editors, the same snippets, and the same variables and done() contract as the connector-level Global Scripts tab.
The difference is scope:
- A script on the Global Scripts tab runs for every request the connector makes.
- A script on a resource's Scripts tab runs only for that resource.
Use a resource script when the logic applies to one endpoint, and a global script when it applies to the whole connector.
Writing scripts
To open the Global Scripts tab:
- In Integration Service, open Connector Builder and select your custom connector.
- Select Global Scripts from the top navigation.
- Expand Pre-request script or Post-request script and enter your JavaScript.
Scripts run in a sandboxed JavaScript environment, with no network access and no way to import packages.
Standard JavaScript built-ins are available: JSON, Date, Array, Object, URL, encodeURIComponent, URLSearchParams, TextEncoder, TextDecoder, btoa, atob, crypto, Blob, FormData, Headers, Intl, and BigInt.
Buffer is not available. Use btoa and atob for base64 encoding instead.
The following are not available in the sandbox:
| Category | Not available |
|---|---|
| Evaluation and imports | eval, any require() call, a top-level import or export statement, a dynamic import(...) expression |
| Network | fetch, XMLHttpRequest, WebSocket |
| Timers and workers | setTimeout, setInterval, setImmediate, Worker, importScripts, postMessage |
| Runtime and globals | Deno, process, globalThis, self, window, WebAssembly, Buffer |
The done() function
Every script must call done() to signal completion. done() terminates execution immediately — any code written after done() is unreachable.
// Pass through unchanged
done();
// Override one or more output values
done({
request_vendor_headers: updatedHeaders
});
// Return multiple overrides
done({
request_vendor_body: newBody,
request_vendor_headers: newHeaders
});
// Stop the request — do not call the vendor API
done({ continue: false });
// Stop the request and return an error
done({
continue: false,
response_status_code: 400,
response_error_message: "Invalid action"
});
// Pass through unchanged
done();
// Override one or more output values
done({
request_vendor_headers: updatedHeaders
});
// Return multiple overrides
done({
request_vendor_body: newBody,
request_vendor_headers: newHeaders
});
// Stop the request — do not call the vendor API
done({ continue: false });
// Stop the request and return an error
done({
continue: false,
response_status_code: 400,
response_error_message: "Invalid action"
});
Using Snippets
Select Snippets in the script panel to insert code templates into the active script editor.
The Pre-request script panel offers the following templates, grouped under Prerequest scripts:
- Update provider URL — Sets
request_vendor_pathto a full URL, replacing the provider URL for that request. - Use a configuration — Reads a value from
configuration(the connector's base URL, in the sample) and sends it to the provider as a request header. - Skip a provider request — Sets
continuetofalseso the request is never sent to the provider.
The Post-request script panel offers the following templates, grouped under Postrequest scripts:
- Update the response body — Copies
response_bodyinto a local variable, adds a field to it, and returns the modified body. - SR metadata generation from vendor metadata — Builds standard resource field metadata from a vendor metadata response, deriving each custom field's type, format, display name, description, supported methods, and enum values.
Pre-request scripts
A pre-request script runs before each API call is sent to the provider. Variables with Write or Read & Write access can be set via done().
| Variable | Access | Description |
|---|---|---|
request_method | Read | HTTP method of the API call (GET, POST, etc.). |
request_vendor_method | Read & Write | HTTP method that will be passed to the provider. |
request_headers | Read | Request headers passed as part of the API call. |
request_vendor_headers | Read & Write | Headers that will be sent to the provider. |
request_path | Read | Request path of the API call. |
request_vendor_path | Read & Write | Request path that will be sent to the provider. If the path starts with http, it is used as the full request URL. |
request_path_variables | Read | Path variables extracted from the URL template. |
request_parameters | Read | Query parameters passed as part of the API call. |
request_vendor_parameters | Read & Write | Query parameters that will be sent to the provider. |
request_body | Read | Request body passed as part of the API call, as a string. |
request_body_raw | Read | Request body passed as part of the API call, as an unprocessed string. |
request_vendor_body | Read & Write | Request body that will be sent to the provider. Accepts string, list, or map on write. |
request_body_map | Read | Request body passed as part of the API call, as a map. |
request_vendor_body_map | Read | Request body that will be sent to the provider, as a map. |
request_vendor_url | Read | Fully formed endpoint URL that will be used for the vendor call. |
request_expression | Read | CEQL where parameter converted to a list of {attribute, value, operator} maps. |
request_previous_response | Read | Response body from the previous chained resource. null if not part of a chain. |
request_previous_response_headers | Read | Response headers from the previous chained resource. null if not part of a chain. |
request_root_key | Read & Write | Dot-notation path to build a sub-object in the request JSON payload (e.g. data.record). |
object_name | Read | Canonical object name for the request. |
vendor_object_name | Read | Vendor object name. Same as object_name unless overridden on the resource. |
configuration | Read | Connector configuration properties. |
response_status_code | Write | HTTP status code to return when continue is false. |
response_error_message | Write | Error message to return before the request is sent to the vendor. |
response_body | Write | Response body to return when continue is false. |
response_body_raw | Write | Response body as a string to return when continue is false. |
response_root_key | Read & Write | Dot-notation path to limit the response to a sub-object (e.g. data.records). |
multipart_hook_context_items | Read & Write | Multipart form items for file upload requests. |
continue | Write | Set to false to skip the vendor call. Defaults to true. |
Example: Inject a dynamic header from configuration
var headers = request_vendor_headers || {};
var config = configuration || {};
headers['Authorization'] = 'Bearer ' + config['oauth_token'];
done({ request_vendor_headers: headers });
var headers = request_vendor_headers || {};
var config = configuration || {};
headers['Authorization'] = 'Bearer ' + config['oauth_token'];
done({ request_vendor_headers: headers });
Example: Override the vendor URL path
var baseUrl = configuration['base_url'];
if (!baseUrl) {
done({ continue: false, response_error_message: "Missing configuration: 'base_url'" });
return;
}
var apiVersion = configuration['api_version'] || 'v1';
var modelId = request_path_variables.modelId;
var vendorUrl = baseUrl.startsWith('http') ? baseUrl : 'https://' + baseUrl;
done({
request_vendor_path: vendorUrl + '/' + apiVersion + '/models/' + modelId + '/completions'
});
var baseUrl = configuration['base_url'];
if (!baseUrl) {
done({ continue: false, response_error_message: "Missing configuration: 'base_url'" });
return;
}
var apiVersion = configuration['api_version'] || 'v1';
var modelId = request_path_variables.modelId;
var vendorUrl = baseUrl.startsWith('http') ? baseUrl : 'https://' + baseUrl;
done({
request_vendor_path: vendorUrl + '/' + apiVersion + '/models/' + modelId + '/completions'
});
Example: Modify the request body
var body = typeof request_body_map === 'string'
? JSON.parse(request_body_map)
: request_body_map;
body.max_tokens = body.max_tokens || 1024;
body.temperature = 0.7;
done({
request_vendor_headers: { 'Content-Type': 'application/json' },
request_vendor_body: JSON.stringify(body)
});
var body = typeof request_body_map === 'string'
? JSON.parse(request_body_map)
: request_body_map;
body.max_tokens = body.max_tokens || 1024;
body.temperature = 0.7;
done({
request_vendor_headers: { 'Content-Type': 'application/json' },
request_vendor_body: JSON.stringify(body)
});
Post-request scripts
A post-request script runs after a response is received from the vendor. All pre-request variables remain available as Read. The response-specific variables below are added, and configuration becomes Read & Write. Variables with Write or Read & Write access can be set via done().
| Variable | Access | Description |
|---|---|---|
response_iserror | Read | true if the vendor response indicates an error (status codes outside 200–207). |
response_status_code | Read & Write | HTTP status code from the vendor. |
response_body | Read & Write | Response body from the vendor. |
response_body_raw | Read & Write | Raw response body from the vendor, as a string. |
response_body_raw_map | Read | Raw response body from the vendor, as a map. |
response_body_map | Read | Response body from the vendor, as a map. |
response_headers | Read & Write | Response headers from the vendor. |
response_error_message | Write | Error message to return. Converts the response into an error. |
response_root_key | Read & Write | Dot-notation path to limit the response to a sub-object (e.g. data.records). |
configuration | Read & Write | Connector configuration properties. Changes persist to the connector instance. |
multipart_hook_context_items | Read & Write | Multipart form items for file upload requests. |
metadata_merge | Write | Set to true to combine vendor metadata with model metadata. |
Start every post-request script with an error guard. If the response is an error, call done() with no arguments to pass it through unchanged.
Example: Transform the response body
if (response_iserror) {
done();
return;
}
var body = typeof response_body === 'string'
? JSON.parse(response_body)
: response_body;
body.processed = true;
body.timestamp = new Date().toISOString();
done({ response_body: body });
if (response_iserror) {
done();
return;
}
var body = typeof response_body === 'string'
? JSON.parse(response_body)
: response_body;
body.processed = true;
body.timestamp = new Date().toISOString();
done({ response_body: body });
Utility functions
The following utility functions are available in both script types:
| Function | Description |
|---|---|
console.log() | Outputs a debug message. |
Bring your own LLM connector use case
If you are building a connector for an LLM provider — such as a self-hosted model or a third-party inference endpoint — Global Scripts let you adapt requests and responses to match the expected contract without modifying each resource individually.
For common LLM providers (AWS Bedrock, Azure OpenAI, Google Vertex AI, OpenAI V1 Compatible), you can start from a connector template that pre-populates the authentication setup and scripts for you. For details, see Using connector templates.
The following scripts show a complete pre-request and post-request setup for this scenario.
Pre-request: Set authentication headers
Inject the provider's API key from the connector configuration and enforce the expected Content-Type:
var headers = {
'Content-Type': 'application/json',
'x-api-key': configuration['api_key']
};
done({
request_vendor_headers: headers,
request_vendor_body: request_body_map
});
var headers = {
'Content-Type': 'application/json',
'x-api-key': configuration['api_key']
};
done({
request_vendor_headers: headers,
request_vendor_body: request_body_map
});
Pre-request: Inject a system message
Set default model parameters and ensure a system message is present in every conversation sent to the model:
var body = typeof request_body_map === 'string'
? JSON.parse(request_body_map)
: request_body_map;
body.max_tokens = body.max_tokens || 1024;
body.temperature = 0.7;
var hasSystemMessage = body.messages.some(function(msg) {
return msg.role === 'system';
});
if (!hasSystemMessage) {
body.messages.unshift({
role: 'system',
content: 'You are a helpful assistant.'
});
}
done({
request_vendor_headers: { 'Content-Type': 'application/json' },
request_vendor_body: JSON.stringify(body)
});
var body = typeof request_body_map === 'string'
? JSON.parse(request_body_map)
: request_body_map;
body.max_tokens = body.max_tokens || 1024;
body.temperature = 0.7;
var hasSystemMessage = body.messages.some(function(msg) {
return msg.role === 'system';
});
if (!hasSystemMessage) {
body.messages.unshift({
role: 'system',
content: 'You are a helpful assistant.'
});
}
done({
request_vendor_headers: { 'Content-Type': 'application/json' },
request_vendor_body: JSON.stringify(body)
});
Post-request: Process the choices array
Iterate the choices array in the vendor response and add custom metadata before returning to the workflow:
if (response_iserror) {
done();
return;
}
var body = typeof response_body === 'string'
? JSON.parse(response_body)
: response_body;
if (body.choices && body.choices.length > 0) {
body.choices.forEach(function(choice) {
choice.processed_by = 'connector-post-script';
});
}
body.custom_metadata = {
processed: true,
timestamp: new Date().toISOString()
};
done({ response_body: body });
if (response_iserror) {
done();
return;
}
var body = typeof response_body === 'string'
? JSON.parse(response_body)
: response_body;
if (body.choices && body.choices.length > 0) {
body.choices.forEach(function(choice) {
choice.processed_by = 'connector-post-script';
});
}
body.custom_metadata = {
processed: true,
timestamp: new Date().toISOString()
};
done({ response_body: body });
Best practices
- Always call
done()— a script that does not calldone()hangs the request. - Copy variables before mutating — the runtime uses strict mode. Assign to a local variable first:
var headers = request_vendor_headers;, then modifyheaders. - Do not write code after
done()— it is unreachable. - Check for
nullorundefined—request_bodyandrequest_vendor_bodyareundefinedfor GET and DELETE requests. - Use
continue: falseto short-circuit — skip the vendor call and return your own response. Post-request scripts still run on that response.
Execution order
When a connector has both a global script and a resource script for the same phase, both scripts run, in this order:
- Global pre-request script
- Resource pre-request script
- The request is sent to the provider
- Global post-request script
- Resource post-request script
The post-request chain does not run in reverse. The global post-request script receives the raw provider response first, and can change or reject it before the resource post-request script runs.
Example: a global script and a resource script on one activity
Consider a connector with the following scripts:
- Global pre-request: adds an
X-Acme-Tenantheader fromconfiguration. - Global post-request: maps the provider's error envelope onto the matching HTTP status code.
GET /contactsresource: a pre-request script that maps paging parameters, and a post-request script that reshapes the payload.
| Order | Script | What it sees |
|---|---|---|
| 1 | Global pre-request | The request as built from the activity input. |
| 2 | Resource pre-request | The request, including the tenant header added in step 1. |
| — | Provider call | — |
| 3 | Global post-request | The raw provider response. |
| 4 | Resource post-request | The response as left by step 3. |
If both pre-request scripts set Authorization, the provider receives the value from the resource script, because it runs last. If the global post-request script sets response_error_message, the request ends with that error and step 4 does not run. Setting only an error response_status_code does not stop the chain.
When a pre-request script stops the request
If a global or resource pre-request script calls done() with continue: false, the request is not sent to the provider:
- Pre-request scripts that haven't run yet are skipped. For example, if the global pre-request script stops the request, the resource pre-request script does not run.
- Both post-request scripts still run, in the usual order, on the response returned by the script that stopped the request.
- If that script returned no response body, the post-request scripts receive an empty body: an empty array for a paginated resource, and an empty response otherwise.
To end the request with an error instead, set response_error_message. In a pre-request or post-request script, it ends the request immediately with that error, and no later script runs, including post-request scripts. The status code is the value of response_status_code, or 400 if it isn't set.
- When to use scripts
- Scripts for a single resource
- Writing scripts
- The
done()function - Using Snippets
- Pre-request scripts
- Example: Inject a dynamic header from configuration
- Example: Override the vendor URL path
- Example: Modify the request body
- Post-request scripts
- Example: Transform the response body
- Utility functions
- Bring your own LLM connector use case
- Pre-request: Set authentication headers
- Pre-request: Inject a system message
- Post-request: Process the choices array
- Best practices
- Execution order
- Example: a global script and a resource script on one activity
- When a pre-request script stops the request