# Exporting companies and persons to CSV
This example shows how the Proff API can be used to generate a CSV file containing information about beneficial owners and persons in important company roles.
All Nordic countries are supported (NO, DK, SE, and FI), but beneficial owner information is available only for Norway and Denmark.
- One row is generated for each person found.
- If the company is not found, a row containing only the organization number and country code is generated.
- If the company is found but no associated persons are found, a row containing the organization number, country code, and company name is generated.
The example uses the native Fetch API in Node.js and has been tested with Node.js 21.7.3.
# Introduction
Run the program using a country code and organization number:
node persons.mjs NO 987582715
Example output:
987582715,NO,2020PARK AS,Monica Runestad,1975,Daglig leder,
987582715,NO,2020PARK AS,Rune Runestad,1954,Styrets leder,
987582715,NO,2020PARK AS,Øystein Runestad,1978,Styremedlem,
987582715,NO,2020PARK AS,Rune Runestad,1954,Beneficial owner,100
Redirect the output to a CSV file using the > operator:
node persons.mjs NO 943545634 > 943545634.csv
The generated CSV file contains the following columns:
| ID | Country | Company name | Name | Birth year | Role | Share |
|---|
If a share value is unavailable, the Share field will be empty.
# Full example
// Roles to include in the export, defined by country
const validRoles = {
NO: [
'Styrets leder',
'Daglig leder',
'Styremedlem'
],
DK: [
'Adm. direktør',
'Direktør'
]
};
const API_ENDPOINT = 'https://api.proff.no/companies';
// Set your API key in the API_KEY environment variable
const API_KEY = process.env.API_KEY;
if (!API_KEY) {
console.error('The API_KEY environment variable is required.');
process.exit(1);
}
// Read the country code and organization number from the command line
const [, , countryCode, businessId] = process.argv;
if (!countryCode || !businessId) {
console.error('Usage: node persons.mjs <COUNTRY_CODE> <ORGANIZATION_NUMBER>');
process.exit(1);
}
const httpOptions = {
headers: {
Authorization: `Token ${API_KEY}`
}
};
// Retrieve company information
const companyResponse = await fetch(
`${API_ENDPOINT}/register/${countryCode}/${businessId}`,
httpOptions
);
const company = companyResponse.ok
? await companyResponse.json()
: null;
// Retrieve beneficial owners only if the company was found
const ownersResponse = company
? await fetch(
`${API_ENDPOINT}/owner/${countryCode}/${businessId}`,
httpOptions
)
: null;
const companyOwners = ownersResponse?.ok
? await ownersResponse.json()
: null;
// In Denmark, all beneficial owners are persons.
// In Norway, only owners with a birth year are persons.
const beneficialOwners = companyOwners?.Shareholders
?.filter(owner =>
countryCode !== 'NO' || owner.BirthYear != null
)
.map(owner => ({
name: owner.NameFromShareholder,
birthYear: owner.BirthYear,
title: 'Beneficial owner',
share: owner.ShareInPercent
})) ?? [];
// Include only the configured roles.
// If no roles are configured for the country, include all roles.
const personRoles = company?.personRoles
?.filter(person =>
!validRoles[countryCode] ||
validRoles[countryCode].includes(person.title)
) ?? [];
// Combine persons in important roles with beneficial owners
const persons = [...personRoles, ...beneficialOwners];
// Generate an empty person record if no associated persons were found
const records = (persons.length > 0 ? persons : [{}]).map(person => ({
businessId,
country: countryCode,
companyName: company?.name,
personName: person.name,
birthYear:
person.birthYear ??
person.birthDate?.substring(4),
role: person.title,
share: person.share
}));
// Escape values that contain commas, quotation marks, or line breaks
function escapeCsvValue(value) {
if (value == null) {
return '';
}
const text = String(value);
if (/[",\r\n]/.test(text)) {
return `"${text.replaceAll('"', '""')}"`;
}
return text;
}
// Write all records to standard output as CSV
for (const record of records) {
const row = Object.values(record)
.map(escapeCsvValue)
.join(',');
process.stdout.write(`${row}\n`);
}
Example:
API_KEY='<YOUR_SECRET_API_KEY>' node persons.mjs NO 987582715