Event Handlers #
Events are triggered at certain points, for example when a Connector Method – or a Step using a Connector Method – runs, or when a Connector’s authentication process is executed. These events allow you to modify data using “event handlers” which are implemented as JavaScript functions.
To add an event handler, place a JavaScript function at the Connector or Method level of your Custom Connector, or in the Advanced Settings area of a Step in the Cycle Builder. Set the name of the function to exactly match the Cyclr event it should be fired for and Cyclr will automatically call it at the relevant execution point.
As JavaScript is a case-sensitive language, function names and variable names must exactly match those documented here.
For example, this is a before_action event function that Cyclr would call right before sending a request:
function before_action() {
/* Handle event here */
return true;
}
When working on a Custom Connector, event handlers entered at the Connector level will be called for all of its Methods. Event handlers entered at the Method level will only be called for that Method. Event handlers entered through a Step’s “Step Setup” popup will only be called for that one Step.
If you need to pass a value from a before_action handler to an after_action handler and you’re not able to put it in the method_request object as part of the Request (some APIs may not accept Requests containing properties they’re not expecting), you can use the method_request_mergefields object as well as the action_data object as they are both persisted across those two events, but only within the context of the Transaction they are being executed within.
The script_parameters object, for example, is not persisted across any events so changes to it are lost outside of the event function they are made in.
Event Handler Order #
If an event handler exists at more than one level for the same event, i.e. Connector level as well as Method level, both of those event handlers will be called, one after the other.
This is useful if common processing of the data is required across all Methods using a Connector level after_action handler, but some Methods need further processing so an additional Method level after_action handler can also be used.
The order that Cyclr calls handlers for the same events is as follows:
Events beginning with “before_” (such as before_action and before_webhook) fire in this order:
Method -> Connector -> Builder Step
All other events, such as after_action, fire in this order:
Connector -> Method -> Builder Step
The order is important as if you were to perhaps modify the method_request object in more than one event, you would need to know which function runs first to understand what state each event will find that object in.
Event Handler Reference #
The following describes each of the Event Functions grouped by the type of Connector Methods they’re available for.
All event functions must end with a return statement with either a true result to indicate it executed successfully and to continue, or false to indicate there was a problem and to stop.
Example:
function before_action() {
if (method_request.contactId === null)
return false; // The request is not sent and a Step Error is recorded.
return true; // Continue and send the request.
}
What actually happens when a running Transaction encounters a return false; statement on a Step in a Template or a Cycle depends on the On Step Error setting.
Standard Events #
These event functions can be used on “Action” Connector Methods (those making an HTTP Request) and “Script” Connector Methods, as well as Steps within the Builder that are using them.
They are also available when working with the Quick Connector’s “HTTP Request” Steps and the Event Triggers’ “Webhook” Steps.
When working on a Custom Connector, if the event functions are defined on the Connector-level “Script” tab, they are called at the relevant event points for all of that Connector’s Methods. See Event Handler Order earlier in this article for more details.
before_action- Enables you to make changes to a request before it is sent.
- Executed after the initial request has been built.
- If Paging is enabled on the Method, this function will be called before each page request is sent.
after_action- Enables you to access and make changes to the response data received from a single request.
- Executed after a response has been received.
- If Paging is enabled on the Method, this function will be called after each page of response data has been received.
after_action_paging- Enables you to access and make changes to the complete response data received.
- Executed once after all executions of the
after_actionevent. - Is executed regardless of whether Paging is enabled on the Method.
action_condition- Enables you to access the complete response data and to apply criteria to direct a Transaction running on its Step out through its True or False Exit.
- Executed after all other event functions for the Step have been executed.
- When present on a Connector Method, Cyclr will display True and False Exits on the Step within the Builder, similar to a Decision Step.
- Adding this function at the Step-level has no effect and the function will not be called.
- This function must end execution with a JavaScript
returnstatement to return a boolean value depending on how a Transaction passing through the Step should leave:return true– for a Transaction to leave through the Step’s True Exit.return false– for a Transaction to leave through the Step’s False Exit.
after_error- Enables you to catch and handle error responses that Cyclr may encounter after it sends a request to an external system.
- Executed if Cyclr receives a 4xx or a 5xx HTTP Status Code in the response.
- Errors can be caught and converted into successful responses or other action taken by using code to examine the error details received. Examples can be found in the Handle Errors from Third Party APIs section.
- Can be defined at both the Method and Connector level in a Custom Connector, as well as on Steps.
Webhook Events #
These event functions can be used on “Webhook” Connector Methods, as well as Steps using them.
They are also available when working with the Event Triggers’ “Webhook” Steps.
Cyclr’s Webhook Steps expect to receive HTTP POST requests.
If you instead send an HTTP GET request to a Cyclr Webhook, no Transaction will be created or run through your Cycle. If the Webhook Step has a before_webhook Script function defined however, that function will still be executed.
before_webhook- Enables you to decide whether a received request should be processed or not.
- Executed at the point Cyclr receives an inbound request to a Step’s Webhook URL.
- Executed whether the Template or Cycle with the Webhook Step is running or stopped.
- This function must end execution with a JavaScript
returnstatement that returns a boolean value:return true– the request is accepted and will be converted into a Transaction to be processed. A standard 200 OK response is sent back to the calling system with the message “Webhook accepted”.return false– the request is not accepted and you can define the response HTTP Headers (method_response_headers) and Body (method_response) that are sent back to the calling system. If anafter_webhookfunction is also present, it will be skipped.
after_webhook- Enables you to decide whether a received request should be processed or not.
- Executed after the
before_webhookevent, but not if a function was provided for that event which ended with areturn falsestatement. - Executed whether the Template or Cycle with the Webhook Step is running or stopped.
webhook_condition- Enables you to apply criteria to direct a Transaction running on its Step out through its True or False Exit.
- Executed after all other event functions for the Step have been executed.
- When present on a Connector Method, Cyclr will display True and False Exits on the Step within the Builder, similar to a Decision Step.
- Adding this function at the Step-level has no effect and the function will not be called.
- This function must end execution with a JavaScript
returnstatement to return a boolean value depending on how a Transaction passing through the Step should leave:return true– for a Transaction to leave through the Step’s True Exit.return false– for a Transaction to leave through the Step’s False Exit.
Authentication Events #
These event functions can be helpful when building a Custom Connector that authenticates with an API using OAuth 2.0.
They help you to handle “non-standard” authentication implementations that an API may use, such as the names of properties in JSON objects, or how token expiry times are provided.
Using these functions, you can ensure Cyclr sends requests as an external API expects, and also handle responses that Cyclr receives from it.
before_oauth2_token- Executed immediately before Cyclr makes an OAuth 2.0 “token” request.
- Enables you to modify the request to match how an API expects it.
after_oauth2_token- Executed immediately after Cyclr makes an OAuth 2.0 “token” request and has received a response.
- Enables you to modify the response from an API to match how Cyclr expects it.
before_oauth2_refresh- Executed immediately before Cyclr makes an OAuth 2.0 “token refresh” request.
- Enables you to modify the request to match how an API expects it.
after_oauth2_refresh- Executed immediately after Cyclr makes an OAuth 2.0 “token refresh” request and has received a response.
- Enables you to modify the response from an API to match how Cyclr expects it.
after_oauth2_refresh_error- Enables you to catch and handle error responses that Cyclr may encounter after it sends a “token refresh” request to an external system.
- Executed if Cyclr receives a 4xx or a 5xx HTTP Status Code in the response.
- Errors can be caught and converted into successful responses or other action taken by using code to examine the error details received.
Variables and Event Handler Functions #
The table below shows which Script Variables are available in which Event Handler Functions.
Click on a Variable or Event to jump to its reference.
Event Handler Functions are documented above, Script Variables are documented below.
| • | available |
| no | not available |
| Variables / Events | before_action | after_action | after_action_paging | action_condition | before_webhook | after_webhook | webhook_condition | after_error | before_oauth2_authorise | before_oauth2_token | after_oauth2_token | before_oauth2_refresh | after_oauth2_refresh | after_oauth2_refresh_error |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| service_domain | • | • | • | • | • | • | • | • | • | • | • | • | • | • |
| external_account_id | • | • | • | • | no | no | • | • | no | • | no | • | • | • |
| cyclr_account_timezone | • | • | • | • | no | no | • | • | no | • | no | • | • | • |
| cyclr_account_id | • | • | • | • | no | no | • | • | no | no | no | • | • | • |
| cycle_id | • | • | • | • | no | no | • | • | no | no | no | no | no | no |
| template_id | • | • | • | • | no | no | • | • | no | no | no | no | no | no |
| cycle_step_id | • | • | • | • | no | • | • | • | no | no | no | no | no | no |
| cyclr_transaction_id | • | • | • | • | no | no | • | • | no | no | no | no | no | no |
| method_auth_value | • | • | • | • | no | no | • | • | no | no | no | • | • | • |
| cycle_variables | • | • | • | no | no | • | no | no | no | no | no | no | no | no |
| script_parameters | • | • | • | • | • | no | • | • | • | • | • | • | • | • |
| action_data | • | • | • | • | no | no | no | • | • | • | • | • | • | • |
| last_successful_run_date | • | no | no | no | no | no | no | no | no | no | no | no | no | no |
| next_last_successful_run_date | no | no | • | no | no | no | no | no | no | no | no | no | no | no |
| script_execution_context | • | • | • | • | no | no | • | • | • | • | • | • | • | • |
| http_method | no | no | no | no | no | no | no | no | no | • | no | • | no | no |
| method_endpoint | no | • | no | no | • | no | no | no | • | • | • | • | • | no |
| method_raw_request | no | • | no | no | • | no | no | no | no | no | no | no | no | no |
| method_request | • | • | • | • | • | • | no | no | no | • | no | • | no | no |
| method_request_headers | • | • | • | • | • | no | no | no | no | • | no | • | no | no |
| method_request_mergefields | • | • | • | • | no | no | no | no | no | • | no | • | no | no |
| method_request_parameters | • | • | • | • | • | no | no | no | no | • | no | • | no | no |
| method_raw_response | no | • | no | no | no | no | no | no | no | no | no | no | no | no |
| method_response | no | • | • | • | • | no | • | no | no | no | • | no | • | no |
| method_response_fields | • | • | • | • | no | no | • | • | no | no | no | no | no | no |
| method_response_fields_in_use | • | • | • | • | no | no | • | • | no | no | no | no | no | no |
| method_response_headers | no | • | • | • | • | no | • | no | no | no | • | no | no | no |
| oauth_client_id | no | no | no | no | no | no | no | no | no | no | no | • | • | • |
| oauth_client_secret | no | no | no | no | no | no | no | no | no | no | no | • | • | • |
| auth_type | • | • | • | • | • | • | • | • | • | • | • | • | • | • |
| oauth2_type | • | • | • | • | • | • | • | • | • | • | • | • | • | • |
| method_error | no | no | no | no | no | no | no | • | no | no | no | no | no | • |
Script Variables #
This section is a reference for all of Cyclr’s Script Variables.
View the table above to see which Variables are available within which Event Handler Functions.
service_domain #
| Description | The value of the Cyclr Console’s Service Domain. |
| Type | string |
| Changes Persisted? | No |
external_account_id #
| Description | The API ID of the Cyclr Account the Script is running within. |
| Type | string |
| Changes Persisted? | No |
cyclr_account_timezone #
| Description | The Timezone set on the Cyclr Account as a TZ identifier, e.g.: “ America/New_York” or “Europe/London”.If used in a Template within the Console, it returns “ Etc/UTC” as Consoles always use UTC. |
| Type | string |
| Changes Persisted? | No |
cyclr_account_id #
| Description | The internal Account ID of the Cyclr Account the script is running within. |
| Type | string |
| Changes Persisted? | No |
cycle_id #
| Description | The ID of the Cycle the Script is running in. |
| Type | string |
| Changes Persisted? | No |
template_id #
| Description | If Script is executed within a Template – or a Cycle installed from a Template – this will contain the ID of that Template. |
| Type | string |
| Changes Persisted? | No |
cycle_step_id #
| Description | If Script is executed in the context of a Step within the Builder, this will contain the ID of that Step. |
| Type | string |
| Changes Persisted? | No |
cyclr_transaction_id #
| Description | If Script is executed in the context of a Transaction, this will contain the ID of that Transaction. |
| Type | string |
| Changes Persisted? | No |
method_auth_value #
| Description | Contains authentication details of the Connector the Method being executed relates to. Typically this is the Access Token or API Key. |
| Type | string |
| Changes Persisted? | No |
cycle_variables #
| Description | Provides access to the Variables of the Template or Cycle the Script is executed within. |
| Type | object |
| Changes Persisted? | No |
script_parameters #
| Description | Contains any available Script Parameters from the Connector and Method the Script is executed from. |
| Type | object |
| Changes Persisted? | No |
action_data #
| Description | Used to store and pass data between most event handler functions. |
| Type | object |
| Changes Persisted? | Yes |
| Event Function Notes | Not available in webhook_... Event Handler Functions.See table above. |
last_successful_run_date #
| Description | Exposes a Step’s Last Successful Run Date for use in Script, which indicates when an individual Step last ran without encountering an error. The date and time value is represented in ISO 8601 format, e.g.: 2025-12-31T16:47:58.000ZWhile changes to last_successful_run_date are not persisted, you can instead change next_last_successful_run_date which is copied to last_successful_run_date the next time the Step is executed. |
| Type | string |
| Changes Persisted? | No |
next_last_successful_run_date #
| Description | Set next_last_successful_run_date to specify the value to be used as the last_successful_run_date value when that Step is next executed.Set to a date and time value represented in ISO 8601 format, e.g.: 2025-12-31T16:47:58.000Z |
| Type | string |
| Changes Persisted? | No |
script_execution_context #
| Description | Contains a value that identifies the context that Script is being executed in. This enables you to decide when to execute parts of your code, such as not updating values held in Cyclr Storage when the Test Step button is clicked. Its value will be one of the following strings:
|
| Type | string |
| Changes Persisted? | No |
http_method #
| Description | Used during authentication calls to set the HTTP request method type to match that of an external API, e.g. “POST” or “GET”. |
| Type | string |
| Changes Persisted? | Yes |
method_endpoint #
| Description | The URL endpoint relating to the Script. Depending on the event function, it will either be the URL of a Cyclr Webhook Step, or the URL Cyclr will send a request to. |
| Type | string |
| Changes Persisted? | No |
method_raw_request #
| Description | When used in a before_webhook event function (Webhook):Contains the body of the request Cyclr received as a string. When used in an after_action event function (non-Webhook):Contains the entire request that Cyclr sent as a string, including the endpoint, HTTP Headers, and request body. Authentication values are redacted. |
| Type | string |
| Changes Persisted? | No |
method_request #
| Description | When used in before_webhook or after_webhook event functions (Webhook):Contains the body of the request Cyclr received. When used in other event functions (non-Webhook): Contains the body of the request Cyclr will send or has already sent, depending on the event function used. |
| Type | object |
| Changes Persisted? |
|
method_request_headers #
| Description | When used in before_webhook or after_webhook event functions (Webhook):Contains the HTTP Headers of the request Cyclr received. When used in other event functions (non-Webhook): Contains the HTTP Headers of the request Cyclr will send or has already sent, depending on the event function used. |
| Type | object |
| Changes Persisted? |
|
method_request_mergefields #
| Description | Contains Mergefields and their values, as defined by the context of the Connector and Method the Script is running in. |
| Type | object |
| Changes Persisted? |
|
method_request_parameters #
| Description | Contains Parameters (typically querystring items) and their values, as defined by the context of the Connector and Method the Script is running in. |
| Type | object |
| Changes Persisted? |
|
method_raw_response #
| Description | Contains the entire response that Cyclr received as a string, including the HTTP Headers and request body. |
| Type | string |
| Changes Persisted? | No |
method_response #
| Description | When used in a before_webhook event function:Enables you to set the response body to be returned if the function returns false. See before_webhook for more.When used in other event functions: Contains the body of the response Cyclr received. In after_action, that is the response body of a single page of data.In after_action_paging, that is the entire compiled response body content of all pages of data. |
| Type | object |
| Changes Persisted? | Yes |
method_response_fields #
| Description | Contains a list of Field Locations for all the Response Fields defined on the current Method. |
| Type | array |
| Changes Persisted? | No |
method_response_fields_in_use #
| Description | Contains a list of Field Locations for any Response Fields of the current Method that have been mapped on subsequent Steps in a Template or Cycle. |
| Type | array |
| Changes Persisted? | No |
method_response_headers #
| Description | When used in a before_webhook event function:Enables you to set the response HTTP Headers to be returned if the function returns false. See before_webhook for more.When used in other event functions: Contains the HTTP Headers of the response Cyclr received. |
| Type | object |
| Changes Persisted? | No |
oauth_client_id #
| Description | Used in OAuth 2.0 ..._refresh event functions and contains the Client ID value. |
| Type | string |
| Changes Persisted? | No |
oauth_client_secret #
| Description | Used in OAuth 2.0 ..._refresh event functions and contains the Client Secret value. |
| Type | string |
| Changes Persisted? | No |
auth_type #
| Description | Contains the Authentication Type of the Connector the Script is being executed against as one of the following values:
|
| Type | string |
| Changes Persisted? | No |
oauth2_type #
| Description | If the Connector the Script is being executed against is using an Authentication Type of OAuth 2.0, this variable will contain the flow type, if applicable, e.g.:
If OAuth 2.0 is not being used, accessing oauth2_type will result in a Script exception. |
| Type | string |
| Changes Persisted? | No |
method_error #
| Description | Contains details relating to an error Cyclr has received from an external system after sending a request, e.g. when any 4xx/5xx HTTP Status code is received as a response. Only available in the after_error event function.method_error is an object with the following 6 properties:
false and the property indicating the new result of the call to true. Cyclr will throw an error if more than one of these properties is set to true:
|
| Type | object |
| Changes Persisted? | No |
Exceptions #
These are special Cyclr “Exceptions” that can be raised within your own Script using the JavaScript throw keyword to trigger Cyclr to take action relating to authentication.
AuthRefreshException #
When thrown, the AuthRefreshException triggers Cyclr to obtain a new OAuth 2.0 token.
Useful when an API’s OAuth 2.0 endpoint doesn’t return a token expiry time so you have to continue to use a token until that API responds with an error. At that point you should obtain a new token.
When this exception is thrown, Cyclr will call the OAuth 2.0 Access Token URL defined on the Connector to obtain a new access token.
For example, if an API indicated a token as having expired by returning a Response with a 200 HTTP Status Code and an error property with the value “invalid_grant”, you could test for that in a Connector-level after_action event, and throw the AuthRefreshException to have Cyclr obtain a new one:
function after_action() {
if (typeof method_response.error !== 'undefined' &&
method_response.error === 'invalid_grant') {
throw new AuthRefreshException();
}
return true;
}
If an API returns a Response with a non-2xx HTTP Status Code when an access token becomes invalid, you could catch that and check it before throwing the AuthRefreshException in a Connector-level after_error event:
function after_error() {
if (method_error.statusCode === 403) {
throw new AuthRefreshException();
}
return true;
}
AuthSessionException #
When thrown, the AuthSessionException triggers Cyclr to force the authentication session to be refreshed.
Cyclr will call the Post Install Property Value Lookup Method (if set) as defined on a Connector under its “Settings” tab to start a new session.
For example, if an API returns a 200 HTTP Status Code with an error in the response when the session expires, you could catch that in an after_action event:
function after_action() {
if (typeof method_response.error_code !== 'undefined' &&
method_response.error_code === 'You are not logged on.') {
throw new AuthSessionException();
}
return true;
}
If an API returns a non-2xx HTTP status code when the auth session expires, you could throw AuthSessionException in a Connector-level after_error function:
function after_error() {
if (method_error.statusCode === 403) {
throw new AuthSessionException();
}
return true;
}
Connector Script Examples #
Make External Requests #
You can write a script to call external API endpoints. This is especially useful if an API returns a URL which contains the real response object.
For example, a webhook might send the following JSON object to Cyclr:
{
"event": "object.updated",
"api_url": "http://httpbin.org/get"
}
You can then use the http_request() function on the Webhook Step or Connector Method to call api_url and replace the webhook response with the updated object:
function after_webhook() {
var request = {
'method': 'GET',
'url': method_response.api_url,
'headers': {
'Accept': 'application/json'
}
};
var content = http_request(request).content;
method_response = content;
return true;
}
After calling api_url, Cyclr will then replace method_response with the content of the HTTP call.
Return false in the after_webhook function will stop Cyclr from running the webhook. You can use this trick to filter webhook events.
Transform Key Value Pairs #
Making use of key/value pair responses from external APIs can require the use of scripting to convert into useable data. Consider an API that returns the below representation of a contact.
{
"properties": [{
"key": "email",
"value": "example@example.com"
}]
}
To access the “email” field’s value we would add a field in the method response with a connector location of properties.email. However this would not work as the Cyclr is looking in the response for a properties object with a property named “email” to get the value from.
To solve this we could add the following function onto the Step or the Connector Method to transform the properties array into an object with properties for each key/value pair:
function after_action() {
var original = method_response.properties;
method_response.properties = {};
for (var i = 0; i < original.length; i++) {
var item = original[i];
if (item['key'] == void(0))
continue;
var val = item['value'];
if (val == void(0))
continue;
method_response.properties[item['key']] = val;
}
return true;
}
Now when Cyclr runs the method if will get the following result back and the properties.email field will work as expected:
{
"properties": {
"email": "example@example.com"
}
}
For a corresponding request method, e.g. creating a contact, we could use this function to perform that data transformation in reverse:
function before_action() {
var original = method_request.properties;
method_request.properties = [];
for (var p in original) {
method_request.properties.push({
'key': p,
'value': original[p]
});
}
return true;
}
Modify Parameters #
Besides the HTTP request body, you can also use scripting to modify HTTP headers (method_request_headers) and query string parameters (method_request_parameters).
function before_action() {
var xmlData = '<Records><Record>';
for (var p in method_request) {
xmlData += '<Field val=""' + p + '"">' + method_request[p] + '</Field>';
}
xmlData += '</Record></Records>';
method_request_parameters.xmlData = xmlData;
return true;
}
In this example, we transformed the method request body to a XML string and saved the string as a new parameter called xmlData.
Action Condition #
When working with a Custom Connector, you can add True/False Exits to a Step if you put an action_condition event function on your Custom Connector’s Method.
Note: Adding the function at the Step-level has no effect and the function will not be called.
// Any Transactions that pass the condition will continue down the green "True" path.
// Those that do not will take the red "False" path.
function action_condition() {
if ([some test])
return true;
return false;
}
// If you want to send errored transactions (as opposed to successful calls that
// fail the condition) down the false path, you will need to add after_error script.
Handle Errors from Third Party APIs #
The scripting engine can be used to catch and handle errors returned from third party APIs.
Cyclr exposes a received error response in the after_error function through the method_error object, which has these properties:
- statusCode – (number) the HTTP status code returned by the third party API.
- reasonPhrase – (string) the reason phrase returned by the third party API.
- content – (string) the body content of the response from the third party API. Could contain JSON or XML.
- isError – indicates that the error is an error. default: true, set to false if using isWarning or isSuccess.
- isWarning – set to true for Cyclr to log the error as a warning.
- isSuccess – set to true to change the error to success. This will result in the value of
method_error.contentbeing provided as the data to be returned. Alternatively, you can assign a string to provide your own data as the response, e.g.:method_error.content = '{"result": "An error occurred."}'
Example: change an error to a warning
function after_error() {
if (method_error.statusCode != null &&
method_error.statusCode === 400 &&
method_error.reasonPhrase == 'Email Address not valid') {
method_error.isError = false;
method_error.isWarning = true;
}
return true;
}
Example: change an error to success
function after_error() {
if (method_error.statusCode != null &&
method_error.statusCode === 400 &&
method_error.reasonPhrase == 'Email Address not valid') {
method_error.isError = false;
method_error.isSuccess = true;
method_error.content = '{}';
}
return true;
}
Example: change an error to success and also include details of the error in the new response
function after_error() {
if (method_error.statusCode === 404) {
// Catch the error and convert it to "success":
method_error.isError = false;
method_error.isSuccess = true;
// Include details of the error as the new Response Body, which could then be inspected by later Steps:
method_error.content = JSON.stringify({
"errorCaught": true,
"originalResponse": {
"statusCode": method_error.statusCode,
"reasonPhrase": method_error.reasonPhrase,
"responseBody": method_error.content
}
});
}
return true;
}