Zambion Example
The code below is an example of a process connecting to Zambion. Zambion authenticates using the OAuth 2.0 client credentials grant against its own token endpoint rather than MODLR's built-in OAuth 2.0 flow, so this is an Advanced Integration.
INFO
This process requires a Zambion client ID and secret, stored as Secrets rather than hardcoded in the process.
Library Code
A small client for the Zambion API, handling authentication (requesting and refreshing an access token) and wrapping authenticated GET requests. Save this as a Process Library and load it with script.library.
js
function ZambionApi(clientId, secret, scope = "api1") {
this.baseUrl = "https://api2.zambion.com/api/SecuredApi/";
this.authUrl = "https://oauth.zambion.com/connect/token";
this.clientId = clientId;
this.secret = secret;
this.scope = scope;
this.accessToken = null;
this.accessTokenExpiry = null;
this.login = function () {
this.accessToken = this.getAccessToken();
};
this.getAccessToken = function () {
const body = `grant_type=client_credentials&client_id=${this.clientId}&client_secret=${this.secret}&scope=${this.scope}`;
const response = web.post(this.authUrl, { "Content-Type": "application/x-www-form-urlencoded" }, body);
if (response.status >= 200 && response.status < 300) {
const tokenData = JSON.parse(response.body);
// Refresh a little early so we never use a token that's about to expire mid-request.
this.accessTokenExpiry = new Date(new Date().getTime() + (tokenData.expires_in * 1000) - 100000);
return tokenData.access_token;
} else if (response.error) {
console.log(`Error occurred while authenticating with ${this.authUrl}: ${response.error}`);
return null;
} else {
console.log(`Failed to authenticate with ${this.authUrl}, status code: ${response.status}.`);
return null;
}
};
this.ensureAccessToken = function () {
if (!this.accessToken || new Date() > this.accessTokenExpiry) {
this.accessToken = this.getAccessToken();
}
};
this.getRequest = function (endpoint, parameters = []) {
this.ensureAccessToken();
const params = parameters.map(param => {
const key = Object.keys(param)[0];
return param[key] === "" ? key : `${key}=${param[key]}`;
});
let url = this.baseUrl + endpoint;
if (params.length > 0) {
url += `?${params.join("&")}`;
}
const response = web.get(url, { "Authorization": `Bearer ${this.accessToken}` });
if (response.status >= 200 && response.status < 300) {
return JSON.parse(response.body);
} else if (response.error) {
console.log(`Error occurred while requesting ${url}: ${response.error}`);
return null;
} else {
console.log(`Failed request to ${url}, status code: ${response.status}.`);
return null;
}
};
this.login();
return this;
}Process Code
This example pulls the Zambion StaffList endpoint and logs the result.
js
script.library("libraries/zambionapi.js");
function pre() {
// This function is called once before the process is executed.
// Use this to setup prompts.
script.log('process pre-execution parameters parsed.');
}
function begin() {
// This function is called once at the start of the process
script.log('process execution started.');
const api = new ZambionApi(security.getSecret("ZAMBION_CLIENT_ID"), security.getSecret("ZAMBION_CLIENT_SECRET"));
const staff = api.getRequest("StaffList");
if (!staff) {
return;
}
console.log(`Staff returned: ${staff.length}`);
console.log(staff);
}
function data(record) {
// This function is called once for each line of data on the second cycle
// Use this to build dimensions and push data into cubes
}
function end() {
// This function is called once at the end of the process
script.log('process execution finished.');
}