# Exporting company and persons to CSV
This is an example of how Proff API can be used to produce a CSV with information about beneficial owners and persons with important roles. All nordic countries are supported (NO,DK,SE,FI), but only NO and DK have information about beneficial owners.
- One line is printed for every person found
- If the company is not found a line is still printed with just the business id and country.
- If the company is found, but no associated persons are found, a line is printed with the business id, country and company name
The example uses the native Fetch API in NodeJS and has been tested with NodeJS 21.7.3.
# Introduction
The program can be run like this:
node persons.mjs NO 987582715
This will print results like this:
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
You can pipe the output to a file using the > operator (e.g. node persons.mjs NO 943545634 > 943545634.csv
).
These are the column headers:
ID | Country | Company name | Name | BirthYear | Role | Share |
---|
Note that if there is no share value an empty value is printed.
# Full example
// List of roles that we care about - defined per country
const validRoles = {
"NO": [ // Define important roles in Norway
"Styrets leder",
"Daglig leder",
"Styremedlem"
],
"DK": [ // Define important roles in Denmark
"Adm. direktør",
"Direktør"
]
}
const API_ENDPOINT = 'https://api.proff.no/companies'
// Set your API token in the environment variable API_TOKEN
const API_TOKEN = process.env.API_TOKEN
const httpOptions = {headers: {'Authorization': `Token ${API_TOKEN}`}};
// Input arguments to the program
const [, , ccTLD, id] = process.argv
const companyResponse = await fetch(`${API_ENDPOINT}/register/${ccTLD}/${id}`, httpOptions);
const company = companyResponse.ok && await companyResponse.json()
// Fetch owners only if company found
const companyOwnerResponse = company && await fetch(`${API_ENDPOINT}/owner/${ccTLD}/${id}`, httpOptions);
const companyOwners = companyOwnerResponse?.ok && await companyOwnerResponse.json()
// In DK all beneficial owners are persons, for NO only those with BirthYear are persons
const ownersFiltered = companyOwners?.Shareholders
?.filter?.(f => ccTLD !== 'NO' || ccTLD === 'NO' && f.BirthYear != null)
.map?.(o => ({name: o.NameFromShareholder, birthYear: o.BirthYear, title: 'Beneficial owner', share: o.ShareInPercent})) || []
// Combine persons with important roles and beneficial owners, and map them to records
// If there are no persons we still map an entry for the company
const personRoles = company.personRoles?.filter?.(f => !validRoles[ccTLD] || validRoles[ccTLD].indexOf(f.title) !== -1) || [{}]
const records = personRoles.concat(ownersFiltered).map(p => ({
businessId: id,
country: ccTLD,
name: company.name || null,
personName: p.name,
birthYear: p.birthYear || p.birthDate && p.birthDate.substring(4),
title: p.title,
share: p.share
}))
// Write all records to stdout (CSV)
for (let record of records) {
process.stdout.write(`${(Object.values(record).join())}\n`)
}