REST API
On this page
- TOC
This article explains how to add the REST API enricher. The purpose of this enricher is to retrieve data from a wide variety of endpoints. It provides a flexible way to integrate diverse data sources into your golden records.
This enricher is intended for users who are comfortable writing JavaScript code, as scripting is required to customize request and response handling.
Add REST API enricher
The REST API enricher requires the URL of an external endpoint to retrieve data. You can use JavaScript to customize request construction and response processing for precise control over data extraction. You can find some examples of JavaScript code in the Sample scripts V1 and Sample scripts V2 section of this page.
To add REST API enricher
-
On the navigation pane, go to Preparation > Enrich. Then, select Add Enricher.
-
On the Choose Enricher tab, select REST API, and then select Next.

-
On the Configure tab, provide the following details:
-
Accepted Business Domain – enter the business domain to define which golden records will be enriched.
-
Version – select the version of REST API enricher.
-
Method – available only in V1. Select the HTTP method (GET or POST) that will be used to retrieve data.
-
URL – available only in V1. Enter the URL of the external endpoint. This can be:
-
An external API endpoint (for example, DuckDuckGo) that returns data directly to the enricher, where it is processed using the Process Response Script.
-
A service endpoint (for example, Power Automate, Jupyter Notebook, or a Cloud Function) that acts as a wrapper for external APIs. These endpoints can call external APIs, process the responses internally, and return the final result to the enricher.
You can use placeholders in URL to dynamically insert values at runtime:
-
{APIKey}– this placeholder will be replaced by the actual API key value provided in API Key. -
{Vocabulary:vocabularykey}– this placeholder will be replaced with the value of the specified vocabulary key from the golden record. For example, if the URL contains{Vocabulary:trainingcontact.country}and the golden record contains"trainingcontact.country": "Norway", the placeholder will be replaced withNorway.

-
-
API Key – enter the API key required to authenticate with the endpoint, if applicable. Provide this only if the API requires a key for access. Use
{APIKey}in URL (V1), Process Request Script (V1) and Process Script (V2) and the place holder will be replaced by actual API Key value provided. -
Headers – available only in V1. Enter any HTTP headers needed to call the endpoint. Enter one header per line in the format
Header-Name=value. -
Vocabulary and Properties – enter the vocabulary keys and properties to include in the request payload, with one entry per line. These will be passed to the endpoint to retrieve the relevant data.
-
Process Request Script – available only in V1. Provide the JavaScript code used to construct or modify the request before it is sent to the external endpoint. You can find an example of the process request script in the Sample scripts section of this page.
-
Process Response Script – available only in V1. Provide the JavaScript code used to process the response returned from the external endpoint. This script is required to transform the API response into a format that the enricher can understand and use. You can find an example of the process response script in the Sample scripts section of this page.
-
Process Script – available only in V2. Provide the JavaScript code used to request and process the response returned from the external endpoint. This script is required to transform the API response into a format that the enricher can understand and use. You can find an example of the process response script in the Sample scripts section of this page.
-
Include Confidence Score – decide whether the results will include a confidence score, which can be used during data processing.
-
-
Select Test Connection to make sure the enricher is properly configured, and then select Add.
The REST API enricher is added and has an active status. This means that it will enrich relevant golden records during processing or when you trigger external enrichment.
After the REST API enricher is added, you can modify its details:
-
Settings – add a user-friendly display name, select the description for data coming from the enricher, and define the source quality for determining the winning values.
-
Authentication – modify the details you provided while configuring the enricher.
View properties added by REST API enricher
You can find the properties added to golden records from the REST API enricher on the Properties page. The vocabulary keys added to golden records by the REST API enricher are grouped under No Source source type.

For a more detailed information about the changes made to a golden record by the REST API enricher, check the corresponding data part on the History page.

Sample (V1)
This section provides some sample configuration and scripts that you can use to configure the V1 REST API enricher.
Sample process request script
// sample request that can be accessed in the script
// let request = {
// ApiKey: "testApiKey",
// Url: "testUrl",
// Headers: [
// { Key: "TestHeader", Value: "123"}
// ],
// Body: {
// Properties: [{Key: "organization.name", Value: "CluedIn"}]
// }
// };
// Add Header
request.AddHeader("TestHeader2", "456");
let detailsArray = [];
request.Body.Properties.forEach((x) => {
detailsArray.push(x.Value);
});
// Update Body that will be sent to external api
request.Body = {
names: detailsArray,
};
//modified request
// let request = {
// ApiKey: "testArray",
// Url: "testUrl",
// Headers: [
// { Key: "TestHeader", Value: "123"},
// { Key: "TestHeader2", Value: "456"}
// ],
// Body: {
// name: ["CluedIn"]
// }
// };
Sample process response script
// Sample response that returned from external api to enricher
// const response = {
// HttpStatus: "OK".
// Content: "{\"fullName\": \"CluedIn ApS\"}",
// Headers: [
// { Key: "Connection", Value: "keep-alive"},
// { Key: "Content-Type, Value "application/x-javascript"}",
// ],
// };
let parsedContent = JSON.parse(response.Content);
let newContent = {
"organization.fullName": parsedContent.fullName,
};
// Data must be returned in the following format to be processed by enricher
// Score can be assigned with external api response
response.Content = JSON.stringify([{ Data: newContent, Score: 0 }]);
// Sample response after executing the script
// const response = {
// HttpStatus: "OK",
// Content: "[{\"Data\":{\"organization.fullName\":\"CluedIn Aps\"}, \"Score\":0}]",
// ContentType: "application/x-javascript",
// Headers: [
// { Key: "Connection", Value: "keep-alive"},
// { Key: "Content-Type", Value: "application/x-javscript",
// ],
Accessing and modifying request and response objects in process request and response scripts
| Name | Type | Description |
|---|---|---|
request | Request | The current HTTP request object that can be modified during script execution. |
originalRequest | Request | The original, unmodified HTTP request for reference purposes. Available in Process Response Script. |
response | Response | The response from external endpoint that can be populated or modified by the script. |
vocabularies | Property[] | The list of vocabularies and properties from enricher configuration. |
Request
| Property | Type | Description |
|---|---|---|
Method | string | The HTTP request method (e.g. GET, POST). |
Url | string | The target URL for the HTTP request. |
Headers | Header[] | List of HTTP headers included in the request. |
ApiKey | string | API key used for authenticating the request. |
Body | object | The body content of the HTTP request. |
| Method | Signature | Description |
|---|---|---|
addHeader | addHeader(key: string, value: string): void | Adds a new header to the request. |
Response
| Property | Type | Description |
|---|---|---|
HttpStatus | string | The HTTP status code of the response (e.g. 200 OK). |
Content | string | The raw response body content. Must be converted into a string value with the Result type when returned to the enricher for processing. |
ContentType | string | The response content type (e.g. application/json). |
Headers | Header[] | List of HTTP headers included in the response. |
Header
| Property | Type | Description |
|---|---|---|
Key | string | Header name. |
Value | string | Header value. |
Property
| Property | Type | Description |
|---|---|---|
Key | string | Property name. |
Value | string | Property value. |
Result
| Property | Type | Description |
|---|---|---|
Data | object | Key-value data extracted from the response. Each key represents a vocabulary key. |
Score | number | A numeric score indicating the relevance or confidence of the results. |
Clearbit
This script takes a company name as input and sends it to the Clearbit Autocomplete API. Then, it extracts the domain and logo of the top matching company and returns that data in a structured format usable by the enricher.
Method: GET
URL
https://autocomplete.clearbit.com/v1/companies/suggest?query={Vocabulary:organization.name}
Process response script
let parsedContent = JSON.parse(response.Content);
let content = parsedContent[0];
let image = {
"clearbit.organization.domain": content.domain,
"clearbit.organization.logo": content.logo,
};
response.Content = JSON.stringify([{ Data: image, Score: 0 }]);
log(JSON.stringify(response));
Azure OpenAI
This scripts take an organization’s name and sends a request to Azure OpenAI GPT-4 asking it to translate the name into Japanese. Then, it ensures the model responds in a defined JSON format and parses and returns the result in a structure compatible with the enricher. Note that you can use the Azure Open AI enricher for the same task.
Method: POST
URL
https://copilot2.openai.azure.com/openai/deployments/gpt-4-32k/chat/completions?api-version=2024-06-01
Vocabulary key and properties
organization.name
Headers
api-key={APIKey}
Process request script
let prompt = String.raw`Please get {organization.japaneseNameRestApi} by translating {Vocabulary:organization.name} into Japanese.
Response in JSON using the following template
###
{
"organization.japaneseNameRestApi": ""
}
###
`;
request.Body.Properties.forEach((x) => {
prompt = prompt.replace("{Vocabulary:" + x.Key + "}", x.Value);
});
request.Body = {
messages: [{ role: "user", content: prompt }],
temperature: 0,
};
Process response script
let parsedContent = JSON.parse(response.Content);
let content = parsedContent.choices[0].message.content.trimEnd();
response.Content = JSON.stringify([{ Data: JSON.parse(content), Score: 0 }]);
log(JSON.stringify(response));
DuckDuckGo
This script handles the JSON response returned by a DuckDuckGo API call. The main purpose is to extract useful information from the API response and transform it into a format usable by the enricher.
Method: GET
URL
https://api.duckduckgo.com?q={Vocabulary:organization.name}&format=json
Process response script
function extractStringValues(obj, dict = new Map()) {
for (const [key, value] of Object.entries(obj)) {
if (value && typeof value !== "object" && !Array.isArray(value)) {
dict.set("duckDuckGo.organization." + key, value.toString());
}
}
return dict;
}
function extractInfobox(content, dict = new Map()) {
content?.forEach((x) => {
dict.set("duckDuckGo.organization.infobox." + x.label, x.value);
});
}
function extractRelatedTopics(relatedTopics, dict = new Map()) {
for (let i = 0; i < relatedTopics.length; i++) {
dict.set(
"duckDuckGo.organization.relatedTopics" + i + ".firstUrl",
relatedTopics[i]?.FirstURL
);
dict.set(
"duckDuckGo.organization.relatedTopics" + i + ".text",
relatedTopics[i]?.Text
);
dict.set(
"duckDuckGo.organization.relatedTopics" + i + ".icon",
relatedTopics[i]?.Icon?.Url
);
}
}
try {
// Update the content here
let parsedContent = JSON.parse(response.Content);
let vocabularyKeysWithValue = extractStringValues(parsedContent);
extractInfobox(parsedContent.Infobox?.content, vocabularyKeysWithValue);
extractRelatedTopics(parsedContent.RelatedTopics, vocabularyKeysWithValue);
response.Content = JSON.stringify([
{ Data: Object.fromEntries(vocabularyKeysWithValue), Score: 0 },
]);
log(response);
} catch (error) {
const errorDetails = {
name: error?.name,
message: error?.message,
stack: error?.stack,
};
log("Error caught:" + JSON.stringify(errorDetails));
}
REST Countries
This script extracts the official name of a country from the response and formats it into a new JSON structure.
Method: GET
URL
https://restcountries.com/v3.1/name/{Vocabulary:country.country}?fullText=true
Process response script
let parsedContent = JSON.parse(response.Content);
let content = parsedContent[0];
let officialName = {
"country.officialName": content.name.official,
};
response.Content = JSON.stringify([{ Data: officialName, Score: 0 }]);
log(JSON.stringify(response));
Melissa
Melissa is a widely used address validation and data quality service that helps organizations keep address data accurate, standardized, and up to date.
CluedIn can connect to Melissa through its REST API, sending address data for validation. The API responds with standardized and enriched results, which CluedIn processes and maps to the appropriate vocabulary keys for storage and further use.
In the following example, ingested company data contains missing or incorrect address details. We will use Melissa REST API calls to send address-related data stored in different vocabulary keys and enrich golden records with validated and parsed addresses.

Configure Melissa REST API enricher
To add the Melissa REST API enricher, on the Configure tab, provide the following information:
Accepted Business Domain: In this example, /Address.
Method: GET.
URL:
In this example, the URL references several vocabulary keys that store address-related data.
https://address.melissadata.net/V3/WEB/GlobalAddress/doGlobalAddress?id={APIKey}&a1={Vocabulary:company.address.streetAddress}&loc={Vocabulary:company.address.city}&admarea={Vocabulary:company.address.state}&ctry={Vocabulary:company.address.country}&postal={Vocabulary:company.address.zipcode}
Headers:
Content-Type=application/json
Process response script:
This script transforms the raw response into a structured format that fits CluedIn’s schema.
let parsedContent = JSON.parse(response.Content);
let content = parsedContent.Records[0];
let melissaCountryName = content.CountryName;
let melissaCountryISO = content.CountryISO3166_1_Alpha3;
let melissaZipcode = content.PostalCode;
let melissaFullAddress = content.FormattedAddress;
let melissaCity = content.Locality;
let melissaState = content.AdministrativeArea;
let melissaDeliveryIndicator = content.DeliveryIndicator;
let newContent = {
"company.address.city": melissaCity,
"company.address.zipcode": melissaZipcode,
"company.address.state": melissaState,
"company.address.country": melissaCountryISO,
"company.address.vocabKey2": melissaCountryName,
"company.address.vocabKey1": melissaFullAddress,
"company.address.type": melissaDeliveryIndicator,
};
//apply conditions if required
if (melissaDeliveryIndicator === "B") {
newContent["company.address.type"] = "Business";
} else if (melissaDeliveryIndicator === "R") {
newContent["company.address.type"] = "Residential";
} else {
newContent["company.address.type"] = "Unknown";
}
response.Content = JSON.stringify([{ Data: newContent, Score: 0 }]);
//log(JSON.stringify(response));

Example of golden record before and after enrichment
An example of a golden record before enrichment:

Same record after enrichment:
-
The values for the Type and Zipcode properties were updated.
-
Two new vocabulary keys (Vocab Key 1 and Vocab Key 2 were added).

Sample response
Provided below is an example of the response you would receive for the same request in Postman. If you need an additional address line in your golden records, select the relevant fields from the response and add them to the process response script provided earlier on this page. For example, you could include the Latitude and Longitude fields.
URL:
https://address.melissadata.net/V3/WEB/GlobalAddress/doGlobalAddress?id=key&org=Walmart Inc.&a1=702 S.W. 8th St.&loc=Bentonville&admarea=AR&ctry=USA&postal=72716&act=check,verify&format=JSON
Response:
{
"Version": "9.4.1.1228",
"TransmissionReference": "",
"TransmissionResults": "",
"TotalRecords": "1",
"Records": [
{
"RecordID": "1",
"Results": "AC16,AV24,GS05",
"FormattedAddress": "Walmart Inc.;702 SW 8th St;Bentonville AR 72716-6299",
"Organization": "Walmart Inc.",
"AddressLine1": "702 SW 8th St",
"AddressLine2": "Bentonville AR 72716-6299",
"AddressLine3": "",
"AddressLine4": "",
"AddressLine5": "",
"AddressLine6": "",
"AddressLine7": "",
"AddressLine8": "",
"SubPremises": "",
"DoubleDependentLocality": "",
"DependentLocality": "",
"Locality": "Bentonville",
"SubAdministrativeArea": "Benton",
"AdministrativeArea": "AR",
"PostalCode": "72716-6299",
"PostalCodeType": "U",
"AddressType": "F",
"AddressKey": "72716629902",
"SubNationalArea": "",
"CountryName": "United States of America",
"CountryISO3166_1_Alpha2": "US",
"CountryISO3166_1_Alpha3": "USA",
"CountryISO3166_1_Numeric": "840",
"CountrySubdivisionCode": "US-AR",
"Thoroughfare": "SW 8th St",
"ThoroughfarePreDirection": "SW",
"ThoroughfareLeadingType": "",
"ThoroughfareName": "8th",
"ThoroughfareTrailingType": "St",
"ThoroughfarePostDirection": "",
"DependentThoroughfare": "",
"DependentThoroughfarePreDirection": "",
"DependentThoroughfareLeadingType": "",
"DependentThoroughfareName": "",
"DependentThoroughfareTrailingType": "",
"DependentThoroughfarePostDirection": "",
"Building": "",
"PremisesType": "",
"PremisesNumber": "702",
"SubPremisesType": "",
"SubPremisesNumber": "",
"PostBox": "",
"Latitude": "36.363516",
"Longitude": "-94.183177",
"DeliveryIndicator": "U",
"MelissaAddressKey": "2153275541",
"MelissaAddressKeyBase": "",
"PostOfficeLocation": "",
"SubPremiseLevel": "",
"SubPremiseLevelType": "",
"SubPremiseLevelNumber": "",
"SubBuilding": "",
"SubBuildingType": "",
"SubBuildingNumber": "",
"UTC": "UTC-06:00",
"DST": "Y",
"DeliveryPointSuffix": "",
"CensusKey": "050070205041002",
"Extras": {}
}
]
}
AddressBase (OSData)
AddressBase is a set of diverse APIs one of which is address verification, like OS Places API (https://osdatahub.os.uk/).
METHOD: GET URL: https://api.os.uk/search/places/v1/find?key={APIKey}&query={Vocabulary:address.fu[…]s}%20{Vocabulary:address.locality}&maxresults=1&matchprecision=1 API Key: create your own, premium has 60 day trial
Process Response Script:
// Expects an input object named `response` like:
// {
// HttpStatus: "OK",
// Content: "{...OS Places JSON...}",
// Headers: [{ Key: "Content-Type", Value: "application/json" }, ...]
// }
//
// Output will be:
// response.Content = "[{\"Data\":{...},\"Score\":0}]"
(function () {
function asStr(v) {
if (v === undefined || v === null) return null;
v = String(v);
return v.length ? v : null;
}
function asNum(v) {
if (v === undefined || v === null || v === "") return null;
var n = Number(v);
return isFinite(n) ? n : null;
}
function setHeader(key, value) {
if (!response.Headers) response.Headers = [];
var i;
for (i = 0; i < response.Headers.length; i++) {
if (
response.Headers[i] &&
typeof response.Headers[i].Key === "string" &&
response.Headers[i].Key.toLowerCase() === key.toLowerCase()
) {
response.Headers[i].Value = value;
return;
}
}
response.Headers.push({ Key: key, Value: value });
}
// Parse incoming OS Places content
var parsed;
try {
parsed = JSON.parse(response.Content || "{}");
} catch (e) {
// If Content isn't valid JSON, return a safe empty payload
response.HttpStatus = response.HttpStatus || "OK";
response.Content = JSON.stringify([
{
Data: { "osPlaces.error": "Invalid JSON in response.Content" },
Score: 0,
},
]);
response.ContentType = "application/x-javascript";
setHeader("Content-Type", "application/x-javascript");
return;
}
var first =
parsed && parsed.results && parsed.results.length
? parsed.results[0]
: null;
if (!first || typeof first !== "object") {
response.HttpStatus = response.HttpStatus || "OK";
response.Content = JSON.stringify([
{ Data: { "osPlaces.found": false }, Score: 0 },
]);
response.ContentType = "application/x-javascript";
setHeader("Content-Type", "application/x-javascript");
return;
}
var source = first.DPA ? "DPA" : first.LPI ? "LPI" : null;
var src = source ? first[source] : null;
if (!src) {
response.HttpStatus = response.HttpStatus || "OK";
response.Content = JSON.stringify([
{ Data: { "osPlaces.found": false }, Score: 0 },
]);
response.ContentType = "application/x-javascript";
setHeader("Content-Type", "application/x-javascript");
return;
}
// Build normalized dotted-key output (first result only)
var newContent = {
"osPlaces.found": true,
"osPlaces.source": source,
"osPlaces.uprn": null,
"osPlaces.fullAddress": null,
"osPlaces.postcode": null,
"osPlaces.town": null,
"osPlaces.street": null,
"osPlaces.building": null,
"osPlaces.subBuilding": null,
"osPlaces.organisation": null,
"osPlaces.department": null,
"osPlaces.easting": null,
"osPlaces.northing": null,
"osPlaces.latitude": null,
"osPlaces.longitude": null,
};
if (source === "DPA") {
newContent["osPlaces.uprn"] = asStr(src.UPRN);
newContent["osPlaces.fullAddress"] = asStr(src.ADDRESS);
newContent["osPlaces.postcode"] = asStr(src.POSTCODE);
newContent["osPlaces.town"] = asStr(src.POST_TOWN);
newContent["osPlaces.street"] =
asStr(src.THOROUGHFARE) || asStr(src.DEPENDENT_THOROUGHFARE);
newContent["osPlaces.building"] =
asStr(src.BUILDING_NAME) || asStr(src.BUILDING_NUMBER);
newContent["osPlaces.subBuilding"] = asStr(src.SUB_BUILDING_NAME);
newContent["osPlaces.organisation"] = asStr(src.ORGANISATION_NAME);
newContent["osPlaces.department"] = asStr(src.DEPARTMENT_NAME);
newContent["osPlaces.easting"] = asNum(src.X_COORDINATE);
newContent["osPlaces.northing"] = asNum(src.Y_COORDINATE);
newContent["osPlaces.latitude"] = asNum(src.LAT);
newContent["osPlaces.longitude"] = asNum(src.LNG);
} else {
// LPI
newContent["osPlaces.uprn"] = asStr(src.UPRN);
newContent["osPlaces.fullAddress"] = asStr(src.ADDRESS); // may be missing in some LPI responses
newContent["osPlaces.postcode"] =
asStr(src.POSTCODE_LOCATOR) || asStr(src.POSTCODE);
newContent["osPlaces.town"] = asStr(src.TOWN_NAME) || asStr(src.POST_TOWN);
newContent["osPlaces.street"] = asStr(src.STREET_DESCRIPTION);
newContent["osPlaces.building"] =
asStr(src.PAO_TEXT) ||
asStr(src.PAO_START_NUMBER) ||
asStr(src.PAO_START_SUFFIX);
newContent["osPlaces.subBuilding"] =
asStr(src.SAO_TEXT) ||
asStr(src.SAO_START_NUMBER) ||
asStr(src.SAO_START_SUFFIX);
newContent["osPlaces.organisation"] = asStr(src.ORGANISATION);
newContent["osPlaces.department"] = asStr(src.DEPARTMENT);
newContent["osPlaces.easting"] = asNum(src.X_COORDINATE);
newContent["osPlaces.northing"] = asNum(src.Y_COORDINATE);
newContent["osPlaces.latitude"] = asNum(src.LAT);
newContent["osPlaces.longitude"] = asNum(src.LNG);
}
// Wrap into enricher output format
response.HttpStatus = response.HttpStatus || "OK";
response.Content = JSON.stringify([{ Data: newContent, Score: 0 }]);
// Keep response format consistent with your sample
response.ContentType = "application/x-javascript";
setHeader("Content-Type", "application/x-javascript");
})();
Sample (V2)
This section provides some sample configuration and scripts that you can use to configure the V2 REST API enricher.
Sample process script
// companies.country vocabulary key added to Vocabulary and Properties field can be accessed using .find
const country = vocabularies.find((x) => x.Key === "companies.country")?.Value;
const url = `https://restcountries.com/v3.1/name/${country}?fullText=true`;
// usee http.send() to make an API call
const countryResponse = http.send({
url: url,
method: "GET",
// sample headers and body
// headers: [
// {Key: 'Content-Type', Value: 'application/json'},
// {Key: 'Authorization', Value: `Bearer ${token}`}
// ],
// body: { name: 'testName' }
});
log(JSON.stringify(countryResponse));
let parsedContent = JSON.parse(countryResponse?.Content);
let results = {
"country.officialName": parsedContent[0]?.name?.official,
};
response = JSON.stringify([{ Data: results, Score: 100 }]);
Dun & Bradstreet
Vocabulary key and properties
companies.dunsnumber
Process script
// REST API Enricher V2 - DnB Search by DUNS - Process Response Script
function populateIndustryCodes(results, parsedContent) {
const selectedTypes = ["19295", "37788"];
const industryCodeValues =
parsedContent?.organization?.industryCodes?.filter(
(x) => x?.typeDnBCode > 0 && selectedTypes.includes(String(x.typeDnBCode))
) ?? [];
if (industryCodeValues.length === 0) return;
let industryCodesIndex = 0;
for (const industryCode of industryCodeValues) {
results[`Industry_${industryCodesIndex}_Description`] =
industryCode.description;
results[`Industry_${industryCodesIndex}_TypeDescription`] =
industryCode.typeDescription;
results[`Industry_${industryCodesIndex}_TypeDnBCode`] =
industryCode.typeDnBCode;
results[`Industry_${industryCodesIndex}_Priority`] = industryCode.priority;
results[`Industry_${industryCodesIndex}_Code`] = industryCode.code;
industryCodesIndex++;
}
}
function populateOrganizationInfo(results, parsedContent) {
const org = parsedContent?.organization;
// DUNS Control Status
if (org?.dunsControlStatus) {
const status = org.dunsControlStatus;
results.DunsControlStatusFullReportDate = status.fullReportDate;
results.DunsControlStatusLastUpdateDate = status.lastUpdateDate;
results.DunsControlStatusOperatingStatusDescription =
status.operatingStatus?.description;
results.DunsControlStatusOperatingStatusDnbCode =
status.operatingStatus?.dnbCode;
results.DunsControlStatusIsMarketable = status.isMarketable;
results.DunsControlStatusIsMailUndeliverable = status.isMailUndeliverable;
results.DunsControlStatusIsTelephoneDisconnected =
status.isTelephoneDisconnected;
results.DunsControlStatusIsDelisted = status.isDelisted;
if (status?.operatingStatus) {
results.OperatingStatusCode = status.operatingStatus?.dnbCode;
results.OperatingStatusDescription = status.operatingStatus?.description;
}
}
// DUNS Numbers
results.Duns = org?.duns;
results.DomesticUltimateDuns = org?.corporateLinkage?.domesticUltimate?.duns;
results.GlobalUltimateDuns = org?.corporateLinkage?.globalUltimate?.duns;
results.ParentDuns = org?.corporateLinkage?.parent?.duns;
results.HeadQuarterDuns = org?.corporateLinkage?.headQuarter?.duns;
// Business Information
results.PrimaryBusinessName = org?.primaryName;
results.BusinessEntityTypeDnbCode = org?.businessEntityType?.dnbCode;
results.BusinessEntityTypeDescription = org?.businessEntityType?.description;
// Trade Style Names
const tradeStyleNames =
org?.tradeStyleNames
?.map((t) => t?.name)
?.filter((n) => n && n.length > 0) ?? [];
if (tradeStyleNames.length > 0) {
results.TradeStyleNames = tradeStyleNames.join(" | ");
}
// Website
const website = org?.websiteAddress?.[0];
if (website) {
results.WebsiteUrl = website.url;
}
// Telephone
const telephone = org?.telephone?.[0];
if (telephone?.isdCode && telephone?.telephoneNumber) {
results.Telephone = `+${telephone.isdCode} ${telephone.telephoneNumber}`;
}
// Fax
const fax = org?.fax?.[0];
if (fax?.isdCode && fax?.faxNumber) {
results.Fax = `+${fax.isdCode} ${fax.faxNumber}`;
}
// Stock Exchange
const primaryStockExchange = org?.stockExchanges?.find(
(x) => x?.isPrimary === true
);
if (primaryStockExchange) {
results.StockExchangeTickerName = primaryStockExchange.tickerName;
results.StockExchangeName = primaryStockExchange.exchangeName?.description;
results.StockExchangeCountryCode =
primaryStockExchange.exchangeCountry?.isoAlpha2Code;
}
// Registration Numbers
const selectedRegistrationNumberTypes = ["2541"];
if (selectedRegistrationNumberTypes.length > 0) {
const registrationNumbers =
org?.registrationNumbers?.filter(
(x) =>
x?.typeDnBCode > 0 &&
selectedRegistrationNumberTypes.includes(String(x.typeDnBCode))
) ?? [];
let index = 0;
for (const reg of registrationNumbers) {
results[`RegistrationNumbers_${index}_RegistrationNumber`] =
reg.registrationNumber;
results[`RegistrationNumbers_${index}_TypeDescription`] =
reg.typeDescription;
results[`RegistrationNumbers_${index}_TypeDnBCode`] = reg.typeDnBCode;
results[
`RegistrationNumbers_${index}_RegistrationNumberClassDescription`
] = reg.registrationNumberClass?.description;
results[`RegistrationNumbers_${index}_RegistrationNumberClassDnbCode`] =
reg.registrationNumberClass?.dnbCode;
index++;
}
}
// Corporate Linkage - Family Tree Roles Played
let familyIndex = 0;
for (const role of org?.corporateLinkage?.familytreeRolesPlayed ?? []) {
results[
`CorporateLinkageFamilyTreeRolesPlayedVocabulary_${familyIndex}_Description`
] = role.description;
results[
`CorporateLinkageFamilyTreeRolesPlayedVocabulary_${familyIndex}_DnbCode`
] = role.dnbCode;
familyIndex++;
}
results.HierarchyLevel = org?.corporateLinkage?.hierarchyLevel;
results.GlobalUltimateFamilyTreeMembersCount =
org?.corporateLinkage?.globalUltimateFamilyTreeMembersCount;
// Number of Employees
results.NumberOfEmployees = org?.numberOfEmployees?.[0]?.value;
results.GlobalUltimateNumberOfEmployees =
org?.corporateLinkage?.globalUltimate?.numberOfEmployees?.[0]?.value;
results.DomesticUltimateNumberOfEmployees =
org?.corporateLinkage?.domesticUltimate?.numberOfEmployees?.[0]?.value;
// Yearly Revenue
const orgFinancial = org?.financials?.[0];
const orgRevenue = orgFinancial?.yearlyRevenue?.[0];
results.YearlyRevenue =
orgRevenue && orgRevenue.currency
? `${orgRevenue.value} ${orgRevenue.currency}`
: null;
const globalUltimateFinancial = org?.globalUltimate?.financials?.[0];
const globalUltimateRevenue = globalUltimateFinancial?.yearlyRevenue?.[0];
results.GlobalUltimateYearlyRevenue =
globalUltimateRevenue && globalUltimateRevenue.currency
? `${globalUltimateRevenue.value} ${globalUltimateRevenue.currency}`
: null;
const domesticUltimateFinancial = org?.domesticUltimate?.financials?.[0];
const domesticUltimateRevenue = domesticUltimateFinancial?.yearlyRevenue?.[0];
results.DomesticUltimateYearlyRevenue =
domesticUltimateRevenue && domesticUltimateRevenue.currency
? `${domesticUltimateRevenue.value} ${domesticUltimateRevenue.currency}`
: null;
}
function populatePrimaryAddresses(results, parsedContent) {
const org = parsedContent?.organization;
const domesticUltimateDuns = org?.corporateLinkage?.domesticUltimate?.duns;
const globalUltimateDuns = org?.corporateLinkage?.globalUltimate?.duns;
const parentDuns = org?.corporateLinkage?.parent?.duns;
const headQuarterDuns = org?.corporateLinkage?.headQuarter?.duns;
const duns = org?.duns;
// Domestic Ultimate
if (
org?.corporateLinkage?.domesticUltimate?.primaryAddress &&
domesticUltimateDuns &&
domesticUltimateDuns !== duns
) {
const addr = org.corporateLinkage.domesticUltimate.primaryAddress;
results.DomesticUltimatePrimaryAddressCountry = addr.addressCountry?.name;
results.DomesticUltimateISO2CountryCode =
addr.addressCountry?.isoAlpha2Code;
results.DomesticUltimatePrimaryAddressCountyName = addr.addressCounty?.name;
results.DomesticUltimatePrimaryAddressLocality = addr.addressLocality?.name;
results.DomesticUltimatePrimaryAddressPostalCode = addr.postalCode;
results.DomesticUltimatePrimaryAddressRegionName = addr.addressRegion?.name;
results.DomesticUltimatePrimaryAddressRegionAbbreviatedName =
addr.addressRegion?.abbreviatedName;
results.DomesticUltimatePrimaryAddressStreetLine1 =
addr.streetAddress?.line1;
results.DomesticUltimatePrimaryAddressStreetLine2 =
addr.streetAddress?.line2;
}
// Global Ultimate
if (
org?.corporateLinkage?.globalUltimate?.primaryAddress &&
globalUltimateDuns &&
globalUltimateDuns !== duns
) {
const addr = org.corporateLinkage.globalUltimate.primaryAddress;
results.GlobalUltimatePrimaryAddressCountry = addr.addressCountry?.name;
results.GlobalUltimateISO2CountryCode = addr.addressCountry?.isoAlpha2Code;
results.GlobalUltimatePrimaryAddressCountyName = addr.addressCounty?.name;
results.GlobalUltimatePrimaryAddressLocality = addr.addressLocality?.name;
results.GlobalUltimatePrimaryAddressPostalCode = addr.postalCode;
results.GlobalUltimatePrimaryAddressRegionName = addr.addressRegion?.name;
results.GlobalUltimatePrimaryAddressRegionAbbreviatedName =
addr.addressRegion?.abbreviatedName;
results.GlobalUltimatePrimaryAddressStreetLine1 = addr.streetAddress?.line1;
results.GlobalUltimatePrimaryAddressStreetLine2 = addr.streetAddress?.line2;
}
// Parent
if (
org?.corporateLinkage?.parent?.primaryAddress &&
parentDuns &&
parentDuns !== duns
) {
const addr = org.corporateLinkage.parent.primaryAddress;
results.ParentPrimaryAddressCountry = addr.addressCountry?.name;
results.ParentISO2CountryCode = addr.addressCountry?.isoAlpha2Code;
results.ParentPrimaryAddressCountyName = addr.addressCounty?.name;
results.ParentPrimaryAddressLocality = addr.addressLocality?.name;
results.ParentPrimaryAddressPostalCode = addr.postalCode;
results.ParentPrimaryAddressRegionName = addr.addressRegion?.name;
results.ParentPrimaryAddressRegionAbbreviatedName =
addr.addressRegion?.abbreviatedName;
results.ParentPrimaryAddressStreetLine1 = addr.streetAddress?.line1;
results.ParentPrimaryAddressStreetLine2 = addr.streetAddress?.line2;
}
// HeadQuarter
if (
org?.corporateLinkage?.headQuarter?.primaryAddress &&
headQuarterDuns &&
headQuarterDuns !== duns
) {
const addr = org.corporateLinkage.headQuarter.primaryAddress;
results.HeadQuarterPrimaryAddressCountry = addr.addressCountry?.name;
results.HeadQuarterISO2CountryCode = addr.addressCountry?.isoAlpha2Code;
results.HeadQuarterPrimaryAddressCountyName = addr.addressCounty?.name;
results.HeadQuarterPrimaryAddressLocality = addr.addressLocality?.name;
results.HeadQuarterPrimaryAddressPostalCode = addr.postalCode;
results.HeadQuarterPrimaryAddressRegionName = addr.addressRegion?.name;
results.HeadQuarterPrimaryAddressRegionAbbreviatedName =
addr.addressRegion?.abbreviatedName;
results.HeadQuarterPrimaryAddressStreetLine1 = addr.streetAddress?.line1;
results.HeadQuarterPrimaryAddressStreetLine2 = addr.streetAddress?.line2;
}
// Self
if (!org?.primaryAddress) return;
const primary = org.primaryAddress;
results.PrimaryAddressCountry = primary.addressCountry?.name;
results.ISO2CountryCode = primary.addressCountry?.isoAlpha2Code;
results.PrimaryAddressCountyName = primary.addressCounty?.name;
results.PrimaryAddressLocality = primary.addressLocality?.name;
results.PrimaryAddressPostalCode = primary.postalCode;
results.PrimaryAddressRegionName = primary.addressRegion?.name;
results.PrimaryAddressRegionAbbreviatedName =
primary.addressRegion?.abbreviatedName;
results.PrimaryAddressStreetLine1 = primary.streetAddress?.line1;
results.PrimaryAddressStreetLine2 = primary.streetAddress?.line2;
}
function searchByDuns(token) {
// Get DUNS Number from vocabularies passed in Vocabulary and Properties control, please change the key as needed
const dunsNumber = vocabularies.find(
(x) => x.Key === "companies.dunsnumber"
)?.Value;
const dnbResponse = http.send({
url: `https://plus.dnb.com/v1/data/duns/${dunsNumber}?blockIDs=companyfinancials_L1_v3,hierarchyconnections_L1_v1,companyinfo_L3_v1,companyinfo_identifiers_v1,esginsight_L3_v1`,
method: "GET",
headers: [{ Key: "Authorization", Value: `Bearer ${token}` }],
});
let parsedContent = JSON.parse(dnbResponse.Content);
let results = {};
const confidenceScore =
parsedContent?.matchCandidates?.[0]?.matchQualityInformation
?.confidenceCode;
populatePrimaryAddresses(results, parsedContent);
populateOrganizationInfo(results, parsedContent);
populateIndustryCodes(results, parsedContent);
return JSON.stringify([
{ Data: results, Score: confidenceScore ? confidenceScore * 10 : 100 },
]);
}
try {
const authCacheKey = "dnb_auth_token";
const cachedAuthToken = cache.Get(authCacheKey);
const key = "{key}";
const secret = "{secret}";
const credentials = `${key}:${secret}`;
const base64 = stringEncoder.toBase64(credentials);
const token = cache.GetOrSetFactory(
"dnb_auth_token",
() => {
const tokenResponse = http.Send({
url: `https://plus.dnb.com/v2/token`,
method: "POST",
headers: [
{ Key: "Content-Type", Value: "application/json" },
{ Key: "Authorization", Value: `Basic ${base64}` },
],
body: { grant_type: "client_credentials" },
});
return JSON.parse(tokenResponse.Content).access_token;
},
3000000
);
log(JSON.stringify(token));
response = searchByDuns(token);
} catch (error) {
const errorDetails = {
name: error?.name,
message: error?.message,
stack: error?.stack,
};
log("Authentication failed :" + JSON.stringify(errorDetails));
}
REST Countries
This script extracts the official name of a country from the response and formats it into a new JSON structure.
Vocabulary and Properties
companies.country
Process script
const country = vocabularies.find((x) => x.Key === "companies.country")?.Value;
const url = `https://restcountries.com/v3.1/name/${country}?fullText=true`;
const countryResponse = http.send({
url: url,
method: "GET",
});
log(JSON.stringify(countryResponse));
let parsedContent = JSON.parse(countryResponse?.Content);
let results = {
"country.officialName": parsedContent[0]?.name?.official,
};
response = JSON.stringify([{ Data: results, Score: 100 }]);
Helper functions
You can use the following helper functions in your scripts to facilitate common tasks.
Logging
| Function | Signature | Description |
|---|---|---|
log | log(value) | Writes a message to the application log at Information level. Useful for debugging scripts. |
Example:
log("Processing response from API");
String Encoding
| Function | Signature | Description |
|---|---|---|
toBase64 | toBase64(value: string): string | Encodes a UTF-8 string into Base64 format. |
fromBase64 | fromBase64(value: string): string | Decodes a Base64-encoded string back to UTF-8. |
urlEncode | urlEncode(value: string): string | Encodes a string for safe use in a URL. |
urlDecode | urlDecode(value: string): string | Decodes a URL-encoded string. |
Example:
// use stringEncoder object
var encoded = stringEncoder.toBase64("hello");
var decoded = stringEncoder.fromBase64(encoded);
Cache
| Function | Signature | Description |
|---|---|---|
get | get(key: string): object | Retrieves a cached value for the current organization. Returns null if not found. |
set | set(key: string, value: object, expiration: number): void | Stores a value in cache with an expiration time (in milliseconds). Does nothing if the key already exists. It is recommended to use getOrSetValue or getOrSetFactory instead, as they use distributed locks to prevent race conditions. |
getOrSetValue | getOrSetValue(key: string, value: object, expiration: number): object | Returns the cached value if it exists; otherwise, stores the provided value with the given expiration time (in milliseconds) and returns it. |
getOrSetFactory | getOrSetFactory(key: string, factory: function, expiration: number): object | Returns the cached value if it exists; otherwise, calls the factory function to produce the value, stores it with the given expiration time (in milliseconds), and returns it. |
Example:
// use cache object (using )
var token = cache.get("authToken");
if (!token) {
token = "new-token";
cache.getOrSetValue("authToken", token, 60000);
}
Http (V2)
| Function | Signature | Description |
|---|---|---|
send | send(request: object): Response | Sends an HTTP request based on the provided request object and return the response. Refer to request Request and Response Type |
Example:
const tokenResponse = http.send({
url: `https://plus.dnb.com/v2/token`,
method: "POST",
headers: [
{ Key: "Content-Type", Value: "application/json" },
{ Key: "Authorization", Value: `Basic ${base64}` },
],
body: { grant_type: "client_credentials" },
});