UiPath Documentation
integration-service
latest
false
Integration Service user guide

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:

  1. In Integration Service, open Connector Builder and select your custom connector.
  2. Select Global Scripts from the top navigation.
  3. 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.

Important:

Buffer is not available. Use btoa and atob for base64 encoding instead.

The following are not available in the sandbox:

CategoryNot available
Evaluation and importseval, any require() call, a top-level import or export statement, a dynamic import(...) expression
Networkfetch, XMLHttpRequest, WebSocket
Timers and workerssetTimeout, setInterval, setImmediate, Worker, importScripts, postMessage
Runtime and globalsDeno, 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_path to 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 continue to false so 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_body into 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().

VariableAccessDescription
request_methodReadHTTP method of the API call (GET, POST, etc.).
request_vendor_methodRead & WriteHTTP method that will be passed to the provider.
request_headersReadRequest headers passed as part of the API call.
request_vendor_headersRead & WriteHeaders that will be sent to the provider.
request_pathReadRequest path of the API call.
request_vendor_pathRead & WriteRequest path that will be sent to the provider. If the path starts with http, it is used as the full request URL.
request_path_variablesReadPath variables extracted from the URL template.
request_parametersReadQuery parameters passed as part of the API call.
request_vendor_parametersRead & WriteQuery parameters that will be sent to the provider.
request_bodyReadRequest body passed as part of the API call, as a string.
request_body_rawReadRequest body passed as part of the API call, as an unprocessed string.
request_vendor_bodyRead & WriteRequest body that will be sent to the provider. Accepts string, list, or map on write.
request_body_mapReadRequest body passed as part of the API call, as a map.
request_vendor_body_mapReadRequest body that will be sent to the provider, as a map.
request_vendor_urlReadFully formed endpoint URL that will be used for the vendor call.
request_expressionReadCEQL where parameter converted to a list of {attribute, value, operator} maps.
request_previous_responseReadResponse body from the previous chained resource. null if not part of a chain.
request_previous_response_headersReadResponse headers from the previous chained resource. null if not part of a chain.
request_root_keyRead & WriteDot-notation path to build a sub-object in the request JSON payload (e.g. data.record).
object_nameReadCanonical object name for the request.
vendor_object_nameReadVendor object name. Same as object_name unless overridden on the resource.
configurationReadConnector configuration properties.
response_status_codeWriteHTTP status code to return when continue is false.
response_error_messageWriteError message to return before the request is sent to the vendor.
response_bodyWriteResponse body to return when continue is false.
response_body_rawWriteResponse body as a string to return when continue is false.
response_root_keyRead & WriteDot-notation path to limit the response to a sub-object (e.g. data.records).
multipart_hook_context_itemsRead & WriteMultipart form items for file upload requests.
continueWriteSet 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().

VariableAccessDescription
response_iserrorReadtrue if the vendor response indicates an error (status codes outside 200–207).
response_status_codeRead & WriteHTTP status code from the vendor.
response_bodyRead & WriteResponse body from the vendor.
response_body_rawRead & WriteRaw response body from the vendor, as a string.
response_body_raw_mapReadRaw response body from the vendor, as a map.
response_body_mapReadResponse body from the vendor, as a map.
response_headersRead & WriteResponse headers from the vendor.
response_error_messageWriteError message to return. Converts the response into an error.
response_root_keyRead & WriteDot-notation path to limit the response to a sub-object (e.g. data.records).
configurationRead & WriteConnector configuration properties. Changes persist to the connector instance.
multipart_hook_context_itemsRead & WriteMultipart form items for file upload requests.
metadata_mergeWriteSet to true to combine vendor metadata with model metadata.
Tip:

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:

FunctionDescription
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.

Tip:

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 call done() hangs the request.
  • Copy variables before mutating — the runtime uses strict mode. Assign to a local variable first: var headers = request_vendor_headers;, then modify headers.
  • Do not write code after done() — it is unreachable.
  • Check for null or undefined — request_body and request_vendor_body are undefined for GET and DELETE requests.
  • Use continue: false to 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:

  1. Global pre-request script
  2. Resource pre-request script
  3. The request is sent to the provider
  4. Global post-request script
  5. Resource post-request script
Important:

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-Tenant header from configuration.
  • Global post-request: maps the provider's error envelope onto the matching HTTP status code.
  • GET /contacts resource: a pre-request script that maps paging parameters, and a post-request script that reshapes the payload.
OrderScriptWhat it sees
1Global pre-requestThe request as built from the activity input.
2Resource pre-requestThe request, including the tenant header added in step 1.
—Provider call—
3Global post-requestThe raw provider response.
4Resource post-requestThe 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.

Was this page helpful?

Connect

Need help? Support

Want to learn? UiPath Academy

Have questions? UiPath Forum

Stay updated