N Nordic Data

Integration documentation v0.4

How to call the Nordic Data API. Two surfaces — REST and MCP — backed by the same data and the same key. Most agents need fewer than twenty lines of glue.

Quick start

Three minutes from zero to your first response.

1. Get an API key

Self-serve at nordicdata.cloud/#pricing. The free tier gives you 500 requests per month, no card required — plenty to evaluate the data. Without a key the CLI uses the public widget tier (4 lookups per IP per 24 hours).

2. Hit the API — pick your path

The same key works for cURL, the npm CLI, every official SDK, and MCP. Pick what is fastest:

cURL

curl 'https://api.nordicdata.cloud/tenders/search?country=ALL&q=construction&limit=3' \
     -H "X-API-Key: nrd_live_..."

npm CLI — fastest path for trying things from the terminal

# install once
npm install -g nordic-data

# try without a key (public widget tier — 4 lookups/IP/24h)
nordic-data lookup 923609016
nordic-data search equinor

# or run any command without installing
npx nordic-data sanctions 923609016

# wire your key for higher limits
export NORDIC_DATA_KEY=nrd_live_...
nordic-data finances 923609016 --json | jq

Run nordic-data --help for all commands. Per-command help: nordic-data lookup --help, nordic-data search --help, etc.

Python

import os, requests
r = requests.get(
    "https://api.nordicdata.cloud/companies/923609016",
    headers={"X-API-Key": os.environ["NORDIC_DATA_KEY"]},
)
print(r.json()["name"])  # EQUINOR ASA

TypeScript / Node

const r = await fetch(
  "https://api.nordicdata.cloud/companies/923609016",
  { headers: { "X-API-Key": process.env.NORDIC_DATA_KEY! } },
);
const data = await r.json();
console.log(data.name); // EQUINOR ASA

3. (Optional) wire MCP

If your agent runtime speaks MCP, point it at https://api.nordicdata.cloud/mcp with the same key. 28 tools become available across procurement, company registry, financials, officer networks, news, EU grants, and compliance. See MCP setup.

Cookbook — recipes for common use cases

12 recipes covering the most-used flows. Each shows the minimum curl needed plus the one-line description of what comes back. Substitute your own X-API-Key.

Recipe 1 — List all electricians in Stavanger with 5+ employees

Discovery via filter. Plain-text profession is auto-mapped to NACE.

curl 'https://api.nordicdata.cloud/companies/no/list?profession=elektriker&city=Stavanger&min_employees=5' \
  -H 'X-API-Key: nrd_live_…'

Returns: paginated list with name, orgnr, address, NACE codes, employees, status.

Pass a sentence — an LLM translates it to the filter spec and runs the search.

curl 'https://api.nordicdata.cloud/companies/nl-search?q=norwegian%20dentists%20in%20Oslo%20with%2010%20or%20more%20employees' \
  -H 'X-API-Key: nrd_live_…'

Returns: the parsed filter spec + list of matching companies. Great for agent flows where the user describes what they want.

Recipe 3 — Resolve any input to a company (name, orgnr, domain, or email)

The universal lookup. Pass anything; get the best match plus alternates.

curl 'https://api.nordicdata.cloud/companies/lookup?q=Cognite' \
  -H 'X-API-Key: nrd_live_…'

Returns: resolved entity, the resolution path used (orgnr/name/domain/email), and any alternates.

Recipe 4 — One-call KYB due-diligence pack

Cuts ~6 sequential calls down to 1. Identity + officers + sanctions on company AND all officers + sister companies + recent changes + shell-signals.

curl 'https://api.nordicdata.cloud/companies/923609016/kyb-pack' \
  -H 'X-API-Key: nrd_live_…'

Returns: structured bundle ready to drop into a compliance file.

Recipe 5 — Detect invoice fraud via IBAN country check

If a supposed Norwegian supplier asks you to pay a German IBAN, that's a classic CEO-fraud pattern. This endpoint flags it.

curl 'https://api.nordicdata.cloud/verify/invoice?orgnr=923609016&iban=DE89370400440532013000' \
  -H 'X-API-Key: nrd_live_…'

Returns: { risk: "high", reason: "IBAN issued in DE but company registered in NO…" }

Recipe 6 — AI-generated 3-sentence narrative about a company

Sales-prep one-pager in a single call. Uses only the structured data we have — no invented facts.

curl 'https://api.nordicdata.cloud/companies/923609016/explain' \
  -H 'X-API-Key: nrd_live_…'

Returns: { narrative: "Equinor ASA is a Norwegian state-owned oil and gas company…" }

Recipe 7 — Ask any question about a company

Q&A grounded in registry + contact + contract data.

curl 'https://api.nordicdata.cloud/companies/923609016/q?question=who%20chairs%20the%20board' \
  -H 'X-API-Key: nrd_live_…'

Returns: { answer: "Jon Erik Reinhardsen chairs the board, in office since 2026-02-17." }

Recipe 8 — Sales talking points before a meeting

curl 'https://api.nordicdata.cloud/companies/923609016/talking-points' \
  -H 'X-API-Key: nrd_live_…'

Returns: 4-5 numbered talking points referencing concrete facts (recent contract wins, new execs, growth signals).

Recipe 9 — Bulk-enrich a CSV of company names from your CRM

POST raw CSV body (first column = names or orgnrs); get enriched CSV back.

curl -X POST 'https://api.nordicdata.cloud/spreadsheet/enrich' \
  -H 'X-API-Key: nrd_live_…' \
  -H 'Content-Type: text/csv' \
  --data-binary $'Cognite\nEquinor\nSchibsted\nDNB Bank'

Returns: CSV with resolved company data for each input row. Counts as N requests against your monthly limit.

Recipe 10 — Set up a watchlist with monitoring webhooks

Create a watchlist, add companies, get webhook notifications when their state changes.

# Create watchlist
curl -X POST 'https://api.nordicdata.cloud/watchlists' \
  -H 'X-API-Key: nrd_live_…' -H 'Content-Type: application/json' \
  -d '{"name":"key suppliers","orgnrs":["918274758","923609016"]}'

# Subscribe to events on those entities
curl -X POST 'https://api.nordicdata.cloud/webhooks' \
  -H 'X-API-Key: nrd_live_…' -H 'Content-Type: application/json' \
  -d '{"url":"https://your-app/hook","event_types":["company.bankruptcy","sanctions.added"]}'

Recipe 11 — Find all companies within 5km of a coordinate

curl 'https://api.nordicdata.cloud/companies/near?lat=58.97&lng=5.73&radius_km=5&profession=rorlegger' \
  -H 'X-API-Key: nrd_live_…'

Returns: companies within radius, sorted by distance, optionally filtered by industry.

Recipe 12 — Look up a US public company + its SEC filings

~10K US public companies via SEC EDGAR (free, no signup).

# By name
curl 'https://api.nordicdata.cloud/companies/us/search?q=Apple' \
  -H 'X-API-Key: nrd_live_…'

# Full identity by CIK
curl 'https://api.nordicdata.cloud/companies/us/0000320193' \
  -H 'X-API-Key: nrd_live_…'

# Recent 10-K filings
curl 'https://api.nordicdata.cloud/companies/us/0000320193/filings?type=10-K' \
  -H 'X-API-Key: nrd_live_…'

Recipe 13 — Filter US businesses by industry × state × size

Returns verified active US businesses. Every result has a payroll history (real, operating business). Filter by NAICS code (e.g. 511210 = software publishers), US state, and employee count.

curl 'https://api.nordicdata.cloud/companies/us/list?naics=511210&state=CA&min_employees=50&max_employees=200&limit=10' \
  -H 'X-API-Key: nrd_live_...'

Returns 10 California software companies with 50–200 employees, including name, address, NAICS code, employee count, and verifiable business signals.

Recipe 14 — Sales-shaped: industry + role + region → flat contact list

The endpoint a sales rep actually wants. Filter on plain-English industry + role + region + size, get back a flat list of named decision-makers with email + phone + company context. When small SMBs don't publish executives, falls back to a company general-inbox contact so you always get something usable.

curl 'https://api.nordicdata.cloud/contacts/discover?industry=software&role=vp&state=CA&min_employees=50&max_employees=500&limit=25' \
  -H 'X-API-Key: nrd_live_...'

Returns up to 25 named VPs at California software companies (50–500 employees) with email + phone + company. Industries supported: software, saas, fintech, finance, healthcare, biotech, marketing, advertising, consulting, real_estate, retail, ecommerce, manufacturing, construction, education, legal, accounting, media, logistics, food, energy, hr, recruiting. Roles: ceo, founder, cto, cfo, coo, cmo, cro, cpo, cio, chro, vp, director, sales, marketing, engineering, product, finance, hr, operations.

Recipe 15 — Enrich a US business lead end-to-end

Given a US business id (from Recipe 13), auto-discover their website, then return: identity, description, tech stack, email provider (Google Workspace / Microsoft 365 / Zoho / etc.), social URLs (LinkedIn / Twitter / GitHub), public emails (with labels), phone numbers, and named executives. ~30–60s per call.

curl 'https://api.nordicdata.cloud/companies/us/smb/<id>/enrich' \
  -H 'X-API-Key: nrd_live_...'

Recipe 16 — Enrich any company from just a domain

Domain-first composite enrichment. Pass any website URL, get back identity match (Nordic registry, US public-company, or US SMB) + tech stack + sanctions screen + contacts + email provider + social URLs + optional AI narrative.

curl 'https://api.nordicdata.cloud/enrich/all?domain=cognite.com' \
  -H 'X-API-Key: nrd_live_...'

Recipe 17 — Enrich a company from just a name (no domain needed)

Pass a company name (and optional city + state), and we auto-discover the website then run full enrichment. Useful when your CRM has a name but not the domain.

curl 'https://api.nordicdata.cloud/enrich/by-name?name=Lever&city=San%20Francisco&state=CA&country=US' \
  -H 'X-API-Key: nrd_live_...'

New endpoint families (May 2026 expansion)

85 new endpoints across these families. Full reference is integrated below; this is a quick map of where to look:

Authentication

Every request to /tenders/*, /me, and /mcp requires an API key in the X-API-Key header.

X-API-Key: nrd_live_w_5SLGEXXTOk9omCneKPN_4AAsR6Kh-g

Keys are scoped to the issuing account. Each call is recorded against your monthly request budget. Hit the cap and you get 429 Too Many Requests with the budget reflected in the body.

Don't commit keys to source control or paste them into agent system prompts that ship with your code. The key is a bearer credential — anyone holding it can spend your monthly quota.

What you can get from this API

Everything we deliver, mapped to the REST endpoint and the MCP tool that returns it. Look up a capability here, jump to the section, copy the call.

Companies (Norway, primary)

What you wantRESTMCP tool
Find a company by name or industryGET /companies/searchsearch_companies
Full profile (identity, NACE, address, logo, founded year, description, official website, LEI)GET /companies/:orgnrget_company
Enrichment only — logo, description, founded year, website, industry, LEIGET /companies/:orgnr/enrichmentget_company_enrichment
AI bio / "tell me about X" — 3-4 sentence narrativeGET /companies/:orgnr/narrativeget_company_narrative
Financials — revenue, profit, balance sheet, ratiosGET /companies/:orgnr/accountsget_company_accounts
Peer-cohort benchmarks (percentile rank vs sector)GET /companies/:orgnr/peer-benchmarksget_company_peers
Email + phone (verified, MX-checked)GET /companies/:orgnr/contactget_company_contact
Officers — board, directors, executives, signatoriesGET /companies/:orgnr/officersvia get_company with include_officers
Shareholders — full cap table + ownership %GET /companies/:orgnr/shareholdersget_company_shareholders
Subsidiaries / daughter companiesGET /companies/:orgnr/subsidiariesget_company_subsidiaries
Registry change history (status changes, address moves, etc.)GET /companies/:orgnr/changesget_company_changes
Tech stack — what SaaS / CMS / payments tools they useGET /companies/:orgnr/techvia get_company_snapshot
News + press mentionsGET /companies/:orgnr/newsget_company_news
EU R&D grants this company receivedGET /companies/:orgnr/eu-grantsget_company_eu_grants
Tenders this public-sector entity published (as buyer)GET /companies/:orgnr/noticesvia search_tenders with buyer_orgnr
Tenders / contracts this company has WON (as supplier)GET /companies/:orgnr/contract-winsget_company_contract_wins or search_tenders with winner_orgnr
Monthly tender velocity (for a public buyer)GET /companies/:orgnr/tender-velocityget_company_tender_velocity
Sanctions / AML / KYC check (company + auto-fetched officers)GET /companies/:orgnr/sanctions-checkcheck_company_sanctions
Everything in one call — snapshot across all dataGET /companies/:orgnr/snapshotget_company_snapshot
Bulk enrich up to 100 companiesPOST /companies/bulkbulk_get_companies
Recent bankruptcies (credit-risk early warning)GET /companies/bankruptcieslist_recent_bankruptcies

United States — business discovery + lead enrichment

People, ownership & network graph

What you wantRESTMCP tool
Search persons in the officer networkGET /persons/searchsearch_persons
Person — full role history across companiesGET /persons/:idget_person
Who is this person connected to (shared boards)?GET /persons/:id/networkget_person_network
Single-person sanctions checkGET /persons/:id/sanctions-checkcheck_person_sanctions
Are two companies connected via shared officers?GET /companies/:orgnr/path-to/:otherfind_company_path
Reverse shareholder lookup — what does X own?GET /shareholders/portfolioget_shareholder_portfolio

Public procurement (5 Nordic countries)

What you wantRESTMCP tool
Search tenders by country / industry / keyword / companyGET /tenders/searchsearch_tenders
Single tender by IDGET /tenders/:idget_tender
Top public-sector buyers (leaderboard)GET /tenders/leaderboardget_tender_leaderboard
Search awarded contracts (winner / value / period)GET /awards/searchsearch_awards
Top suppliers winning contracts (leaderboard)GET /awards/leaderboardget_award_leaderboard

Sanctions / AML

What you wantRESTMCP tool
Screen any free-text name (person or org, any nationality)GET /sanctions/screenscreen_for_sanctions
Bulk screen many names in one callPOST /sanctions/screen-bulk
One-call company + all-officers AMLGET /companies/:orgnr/sanctions-checkcheck_company_sanctions
Single-person AMLGET /persons/:id/sanctions-checkcheck_person_sanctions

EU R&D grants

What you wantRESTMCP tool
Search grants (country / framework / topic / amount)GET /grants/searchsearch_eu_grants
Single grant project — full participant rosterGET /grants/:idget_eu_grant
Grants for one Norwegian companyGET /companies/:orgnr/eu-grantsget_company_eu_grants

Tech-stack intelligence

What you wantRESTMCP tool
What tech does company X use?GET /companies/:orgnr/techvia get_company_snapshot
Reverse — which Norwegian companies use technology Y?GET /tech/:tech/companiesfind_companies_using_tech

News

What you wantRESTMCP tool
Free-text search Norwegian newsGET /news/searchsearch_news
News mentioning a specific companyGET /companies/:orgnr/newsget_company_news

Other Nordic registries

What you wantRESTMCP tool
Sweden — identity by 10-digit orgnrGET /companies/se/:orgnrget_company with country=SWE
Sweden — enriched contacts (emails, phones, named execs)GET /companies/se/:orgnr/contactget_company_se_contact
Denmark — identity + phone + employeesGET /companies/dk/:cvrget_company with country=DNK
Finland — identity + name historyGET /companies/fi/:idget_company with country=FIN
Iceland — name searchGET /companies/is/search

Countries

Five Nordic registers are indexed. Use the country parameter on search:

CodeNameSource register
NORNorwayFull coverage including below-EU-threshold municipal/county notices that no other Nordic API exposes cleanly.
SWESwedenEU-tier coverage of above-EU-threshold notices.
DNKDenmarkEU-tier coverage of above-EU-threshold notices.
FINFinlandEU-tier coverage of above-EU-threshold notices.
ISLIcelandEU-tier coverage of above-EU-threshold notices.
ALLCross-NordicAll five, sorted by publication date

GET /countries returns the live indexed counts and the latest publication date per country. No key required — call it from a browser to inspect.

Returns tenders sorted by publication date, newest first. Combine any of the filters below.

ParamTypeDescription
countrystring

NOR, SWE, DNK, FIN, ISL, or ALL. Defaults to NOR. Case-insensitive.

qstring

Full-text search across title and description (PostgreSQL english dictionary).

cpvstring

CPV classification code, e.g. 45000000 (construction) or 72000000 (IT). See CPV reference.

fromYYYY-MM-DD

Earliest publication date to include.

toYYYY-MM-DD

Latest publication date to include.

limitinteger

1–100. Default 20.

pageinteger

1-based pagination. Default 1.

Example

# Recent Swedish IT-services tenders
curl 'https://api.nordicdata.cloud/tenders/search?country=SWE&cpv=72000000&limit=10' \
     -H "X-API-Key: $NORDIC_KEY"

Response

{
  "page": 1,
  "limit": 10,
  "total": 412,
  "count": 10,
  "results": [
    {
      "id": "318369-2026",
      "title": "Sweden – Architectural, construction, engineering and inspection services – Ramavtal teknisk konsulttjänst Akustik",
      "buyer": { "name": "Örebroporten Fastigheter AB", "city": "ÖREBRO", "country": "SWE" },
      "publication_date": "2026-05-08",
      "deadline": "2026-05-31",
      "contract_nature": ["services"],
      "cpv_codes": ["71000000"],
      "description": "Örebroporten avser upphandla ramavtal för teknisk konsulttjänst akustik.",
      "total_value": 4000000,
      "procedure_type": "open",
      "notice_url": "https://ted.europa.eu/en/notice/-/detail/318369-2026"
    }
  ]
}

Get one tender GET/tenders/:id

Fetch a single tender by its EU publication number. Format: {number}-{year}, e.g. 317565-2026.

curl 'https://api.nordicdata.cloud/tenders/317565-2026' \
     -H "X-API-Key: $NORDIC_KEY"

Returns the same shape as a single result inside /tenders/search. If the tender is not in the local cache, the server makes a synchronous fallthrough call to TED, caches the result, and returns it. Subsequent requests are fast.

Account info GET/me

Returns your plan, monthly limit, and usage so far this calendar month. Useful for agent runtimes that want to display remaining quota.

{ "label": "founder-test", "plan": "pro", "monthly_limit": 50000, "used_this_month": 412 }

Search the Norwegian company registry by name, organisation number, or NACE industry code. Norway search supports full-text matching. Sweden lookup is by exact orgnr only — see /companies/se/:orgnr below. Denmark/Finland search on roadmap.

ParamTypeDescription
qstring

Fuzzy name match. e.g. q=equinor.

orgnrstring

9-digit Norwegian organisation number for direct lookup. Skips name search and returns the single matching company.

nacestring

NACE industry code, e.g. 06.100 (oil extraction) or 72 (IT). Leading-subset broadens.

limitinteger

1–100. Default 20.

pageinteger

1-based pagination. Default 1.

# Search by name
curl 'https://api.nordicdata.cloud/companies/search?q=equinor&limit=3' \
     -H "X-API-Key: $NORDIC_KEY"

# All companies in oil & gas extraction (NACE 06)
curl 'https://api.nordicdata.cloud/companies/search?nace=06&limit=20' \
     -H "X-API-Key: $NORDIC_KEY"

# Direct orgnr lookup (single result)
curl 'https://api.nordicdata.cloud/companies/search?orgnr=923609016' \
     -H "X-API-Key: $NORDIC_KEY"

Get one company GET/companies/:orgnr

Full company profile by 9-digit organisation number.

curl 'https://api.nordicdata.cloud/companies/923609016' \
     -H "X-API-Key: $NORDIC_KEY"
{
  "orgnr": "923609016",
  "name": "EQUINOR ASA",
  "legal_form": { "code": "ASA", "description": "Allmennaksjeselskap" },
  "registered": "1995-03-12",
  "in_business_registry": true,
  "in_vat_registry": true,
  "status": "active",
  "nace": [
    { "code": "06.100", "description": "Utvinning av råolje" },
    { "code": "06.200", "description": "Utvinning av naturgass" }
  ],
  "employees": 21376,
  "business_address": { "street": "Forusbeen 50", "postal_code": "4035", "city": "STAVANGER", "country": "Norge" },
  "website": "www.equinor.com",
  "sector": { "code": "1110", "description": "Statens forretningsdrift" },
  "parent_orgnr": null
}

Officers and roles GET/companies/:orgnr/officers

Current and historical board members, daily leader (CEO), deputies, signatories, and other registered roles for a company. Names, birth dates, and resigned/deregistered status.

curl 'https://api.nordicdata.cloud/companies/923609016/officers' \
     -H "X-API-Key: $NORDIC_KEY"
{
  "orgnr": "923609016",
  "count": 16,
  "officers": [
    { "role": "Daglig leder", "role_code": "DAGL",
      "person": { "name": "Anders Opedal", "born": "1968-05-04" },
      "resigned": false },
    { "role": "Styrets leder", "role_code": "LEDE",
      "person": { "name": "Jon Erik Reinhardsen", "born": "1956-11-30" },
      "resigned": false }
  ]
}

Common role_code values: DAGL (CEO), LEDE (Chair), NEST (Deputy chair), MEDL (Board member), VARA (Deputy member), REGN (Accountant), REVI (Auditor), KONT (Contact).

Contact info GET/companies/:orgnr/contact

Verified business emails and phone numbers, plus named key personnel (executives, IR, media) when publicly documented. Aggregated from four sources and cached per company for 30 days.

How the data is built (four layers, each adding precision):

  1. Website crawl — fetches the company's own contact / about / press / investor-relations pages and pulls emails, phones, and JSON-LD Organization schema.
  2. Directory fallback — phonebook lookup for the registered company name + city. Catches switchboards and direct lines missing from the website.
  3. LLM extraction — runs over the already-loaded HTML when layers 1+2 found nothing. Strict anti-hallucination: every returned contact must appear in the source text.
  4. AI enrichment layer — runs in the background for every company. Finds role-tagged emails (IR, media, press, pension, owner relations), phone numbers with their context, and named executives (CEO, CFO, head of IR, etc.) with full role/title attribution from across the open web.

Async behavior: the first request for a company returns the layer-1+2+3 result fast (under 5s). Layer 4 runs in the background and updates the cache; the next request returns the fully-enriched data in under 100 ms. The enrichment_in_progress response field signals whether background enrichment is still running.

curl 'https://api.nordicdata.cloud/companies/923609016/contact' \
     -H "X-API-Key: $NORDIC_KEY"

Response (Equinor ASA):

{
  "orgnr": "923609016",
  "company_name": "EQUINOR ASA",
  "website": "https://www.equinor.com",
  "emails": [
    "[email protected]",
    "[email protected]",
    "[email protected]",
    "[email protected]"
  ],
  "phones": [
    "+47 519 90 000",
    "+47 412 60 584",
    "+47 480 80 212",
    "+47 918 01 791"
  ],
  "labels": {
    "email:[email protected]": "Investor Relations",
    "email:[email protected]": "Authorities Contact (Norway)",
    "email:[email protected]": "Methanol Enquiries",
    "phone:+47 519 90 000": "Investor Relations / Main Switchboard",
    "phone:+47 412 60 584": "Vice President Media Relations: Sissel Rinde",
    "phone:+47 480 80 212": "Press Spokesperson: Ola Morten Aanestad",
    "phone:+47 918 01 791": "SVP Investor Relations: Bård Glad Pedersen"
  },
  "named_contacts": [
    { "name": "Anders Opedal", "role": "Chief Executive Officer" },
    { "name": "Torgrim Reitan", "role": "Chief Financial Officer" },
    { "name": "Bård Glad Pedersen", "role": "Senior Vice President Investor Relations",
      "phone": "+47 918 01 791" },
    { "name": "Sissel Rinde", "role": "Vice President Media Relations",
      "phone": "+47 412 60 584" },
    { "name": "Jon Erik Reinhardsen", "role": "Chairman of the Board" }
  ],
  "candidates": [
    "[email protected]",
    "[email protected]",
    "[email protected]"
  ],
  "cached": true,
  "fetched_at": "2026-05-12T09:00:00.000Z"
}

Field reference:

FieldDescription
emailsVerified business email addresses. Excludes form-only inboxes, recruiters, third-party SaaS domains, placeholders.
phonesPhone numbers in +47 XXX XX XXX format. Aggregated from company website, structured page data, directory lookup, and AI enrichment.
labelsPer-contact role/department hint, keyed "email:..." or "phone:...". Examples: "Investor Relations", "Switchboard", "CEO: Jane Doe".
named_contactsArray of key personnel sourced via web search. Each entry: name, role, optional email, optional phone. Filtered to current-role only — no former/retired employees.
candidatesPattern-guessed emails (post@, kontakt@, info@) at the company's domain. Not verified — probe before transactional use.
cachedtrue if served from cache (TTL 30 days), false if freshly crawled.
enrichment_in_progressPresent and true when web-search enrichment is running in the background for this company. Refresh in 30 s for the fully-enriched data.
Honesty notice: the named-contact data is sourced from public web pages and is best-effort. Verify before high-stakes use (KYC onboarding, contract signing) — same caveat that applies to Bisnode/D&B/BvD. Empty arrays mean we couldn't find anything publicly; that's not a bug, just an honest "no data".

Sweden — basic identity GET/companies/se/:orgnr

Look up a Swedish company by 10-digit organisation number (with or without dash). Returns name, VAT number, registered address, and VAT validity. Cached 7 days.

Full Swedish registry data (officers, accounts, shareholders) is on the roadmap.

# IKEA of Sweden AB
curl 'https://api.nordicdata.cloud/companies/se/5560747551' \
     -H "X-API-Key: $NORDIC_KEY"
{
  "country": "SE",
  "orgnr": "5560747551",
  "orgnr_formatted": "556074-7551",
  "vat_number": "SE556074755101",
  "name": "IKEA of Sweden AB",
  "address": "Box 702, 343 81 ÄLMHULT",
  "registered_for_vat": true,
  "source": "EU VAT (live)"
}

Sweden — contact enrichment GET/companies/se/:orgnr/contact

Same identity as /companies/se/:orgnr plus AI-enriched contact data: verified business emails, switchboard and department phones, named-executive list with role labels and personal emails where publicly documented. Counts against your /contact monthly credit allowance.

Discovery uses a layered pipeline: identity resolution → company-website domain detection with MX-record verification → SMTP-level mailbox verification → AI-driven citation extraction from the open web. Catch-all hosts and anti-enumeration mail servers (Microsoft 365, Google Workspace) are labelled explicitly rather than dropped silently.

# Spotify AB
curl 'https://api.nordicdata.cloud/companies/se/5567037485/contact' \
     -H "X-API-Key: $NORDIC_KEY"
{
  "country": "SE",
  "orgnr": "5567037485",
  "name": "Spotify AB",
  "address": "Regeringsgatan 19, 111 53 Stockholm",
  "emails": ["[email protected]", "[email protected]", "[email protected]"],
  "phones": [],
  "labels": {
    "email:[email protected]": "Head of Investor Relations: Bryan Goldberg",
    "email:[email protected]": "Head of Public Relations: Dustee Jenkins"
  },
  "named_contacts": [
    { "name": "Daniel Ek", "role": "Founder and Executive Chairman" },
    { "name": "Alex Norström", "role": "Co-CEO" },
    { "name": "Bryan Goldberg", "role": "Head of Investor Relations", "email": "[email protected]" }
  ],
  "candidates": [],
  "cached": false
}
Honest signal: emails in emails are either cited from real public sources or SMTP-probe-verified deliverable. Pattern guesses on catch-all domains (Google Workspace, Microsoft 365) appear in candidates with a label noting the verifier cannot confirm specific addresses on that host. Empty arrays mean we found no public data — not a bug.

Tenders by company GET/companies/:orgnr/notices

Cross-product join: every public tender in our index where this company is the contracting authority (buyer). Useful for competitive intel, lead generation, KYC, and "what is this company up to" questions.

# All tenders where Statsbygg is the buyer
curl 'https://api.nordicdata.cloud/companies/971278374/notices' \
     -H "X-API-Key: $NORDIC_KEY"
v0.5 caveat: matched by buyer-name string (case-insensitive substring). Some false positives are possible for very common names. v0.6 will switch to exact orgnr-keyed linking via TED's OPT-301-Organization-Identifier field.

Company object schema

FieldTypeDescription
orgnrstring

9-digit Norwegian organisation number. Stable identifier.

namestring

Registered legal name.

legal_formobject

{ code, description } — e.g. ASA, AS, ANS, ENK, ORGL, STAT.

registeredYYYY-MM-DD

Date the entity was first registered in Norwegian registry.

in_business_registryboolean

Listed in Foretaksregisteret (commercial entities).

in_vat_registryboolean

VAT-registered (Mva-registeret).

statusstring

One of active, bankrupt, dissolving, forced-dissolution, deleted.

nacearray

Up to three NACE industry codes with descriptions, in declared priority order.

employeesinteger?

Reported employee count. null if not registered.

business_addressobject?

Physical address.

postal_addressobject?

Postal address.

websitestring?

Self-declared website.

sectorobject?

Institutional sector code per Statistics Norway, with description.

parent_orgnrstring?

Organisation number of the parent entity, if any.

bankruptcyboolean

True if currently in bankruptcy proceedings.

Tender object schema

Two coverage tiers, one table. The /tenders/* endpoints return notices across two procurement layers: above-EU-threshold contracts for all 5 Nordic countries, and Norway-only below-threshold municipal/county procurements that the EU layer never sees. Each result includes a source field; filter by it via ?source=… on search, or by Norwegian buyer org-number via ?buyer_orgnr=941827195. (API field values use legacy upstream identifiers — see Stability notes.)
FieldTypeDescription
idstring

Stable identifier. EU-tier format: 317565-2026 (number-year). Norway-tier format: 2026-108414 (year-number).

sourcestring

Indicates which coverage tier the notice came from. Use this for downstream routing or display.

titlestring

Notice title. EU-tier titles are English-first multilingual. Norway-tier titles are Norwegian.

buyer.namestring

Contracting authority name.

buyer.orgnrstring?

9-digit Norwegian organisation number. Always present for Norway-tier notices; null for non-Norwegian EU-tier notices.

buyer.citystring

City or region of the contracting authority (granularity varies by coverage tier).

buyer.countrystring

ISO 3166-1 alpha-3 country code. Norway-tier notices are always NOR.

publication_dateYYYY-MM-DD

Date the notice was first published.

deadlineYYYY-MM-DD?

Tender response deadline. null for prior-information notices.

contract_naturestring[]

One or more of works, services, supplies. EU-tier coverage only.

cpv_codesstring[]

CPV (Common Procurement Vocabulary) codes. EU-tier coverage only.

descriptionstring?

Description summary. EU-tier coverage is multilingual joined with | if no English; Norway-tier coverage is Norwegian.

total_valuenumber?

Estimated or awarded total value. EU-tier coverage normalises to EUR; Norway-tier coverage returns the original currency (see currency).

currencystring?

ISO 4217 currency code (e.g. NOK) when total_value is in non-EUR. Norway-tier coverage only.

procedure_typestring?

EU-tier: procedure code (open, restricted, negotiated, etc.). Norway-tier: notice type (ANNOUNCEMENT_OF_COMPETITION, ANNOUNCEMENT_OF_CONCLUSION_OF_CONTRACT, etc.).

notice_urlURL

Direct link to the original TED notice in English.

Agent buying — quick start

Nordic Data is one of the few APIs an autonomous agent can buy and use without a human in the loop. Three endpoints are designed for this:

No browser. No hosted Checkout page. No email round-trip. No Customer Portal.

What still needs a human (today): creating the Stripe pm_xxx token. Stripe requires either browser Elements, Stripe Issuing, or a virtual-card service like Privacy.com to mint a payment method. Once an agent has a card token (typically provisioned once by its operator), the rest of the lifecycle is fully autonomous.

End-to-end, an agent goes from "no account" to "calling tools" in a single API request:

curl -X POST https://api.nordicdata.cloud/agent/subscribe \
  -H "Content-Type: application/json" \
  -d '{
    "email":          "[email protected]",
    "plan":           "starter",
    "payment_method": "pm_xxx_from_stripe",
    "country":        "NO",
    "agent_name":     "my-procurement-agent"
  }'

# →
{
  "api_key":         "nrd_live_...",
  "plan":            "starter",
  "monthly_limit":   25000,
  "subscription_id": "sub_...",
  "customer_id":     "cus_...",
  "next_renewal":    "2026-06-09T19:48:07.000Z",
  "usage": "Send X-API-Key: <api_key> on every request to /tenders/*, /companies/*, /me, /mcp."
}

Discover plans GET/agent/plans

Public endpoint — no auth. Use this to enumerate plans before subscribing.

curl https://api.nordicdata.cloud/agent/plans

# →
{
  "plans": [
    { "id": "free",     "price_eur_month": 0,   "monthly_limit": 5000,   "buy_via": "website (email verification required)" },
    { "id": "starter",  "price_eur_month": 29,  "monthly_limit": 25000,  "buy_via": "POST /agent/subscribe" },
    { "id": "builder",  "price_eur_month": 99,  "monthly_limit": 60000,  "buy_via": "POST /agent/subscribe" },
    { "id": "pro",      "price_eur_month": 149, "monthly_limit": 100000, "buy_via": "POST /agent/subscribe" },
    { "id": "business", "price_eur_month": 499, "monthly_limit": 500000, "buy_via": "POST /agent/subscribe" }
  ],
  "currency": "EUR",
  "vat_note": "Norwegian MVA / EU VAT added at checkout based on customer country."
}

Subscribe POST/agent/subscribe

Public endpoint — no auth. Creates (or upgrades from free) a Stripe subscription with auto-charge on renewal, and returns a fresh API key.

FieldTypeDescription
emailstring

Required. Owner email — also used to deduplicate (one active subscription per email).

planstring

Required. One of starter, builder, pro, business.

payment_methodstring

Required. Stripe PaymentMethod ID (pm_xxx). The card is attached to the customer and set as default for renewals.

countrystring

Required. ISO 3166-1 alpha-2 code (e.g. NO, SE, DE, US). Stored as the billing country and used to compute MVA/VAT on the invoice.

agent_namestring?

Optional. Free-text label (≤80 chars) — stored on both the API key and the Stripe customer for your own bookkeeping.

Response: {api_key, plan, monthly_limit, subscription_id, customer_id, next_renewal, usage}. The API key is shown once — store it.

Errors:

Change plan POST/agent/change-plan

Authenticated with X-API-Key. Upgrades or downgrades the subscription in place. Stripe applies a prorated charge for the current period — no Customer Portal required.

curl -X POST https://api.nordicdata.cloud/agent/change-plan \
  -H "X-API-Key: nrd_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "plan": "pro" }'

# →
{
  "ok":              true,
  "plan":            "pro",
  "monthly_limit":   100000,
  "subscription_id": "sub_...",
  "next_renewal":    "2026-06-09T19:48:07.000Z",
  "message": "Plan changed from starter to pro. Prorated charge applied to current period."
}

The API key is unchanged after a plan change — agents can keep using the same X-API-Key on every subsequent call. Only the plan and monthly_limit on GET /me reflect the new tier.

Model Context Protocol

The MCP server exposes the same data as the REST API, but in a form your agent can discover and call automatically. Transport is Streamable HTTP. URL: https://api.nordicdata.cloud/mcp. Authenticate with your API key in the X-API-Key header — same key as REST. 28 tools are registered, grouped below.

ToolUse for
Procurement
search_tenders

Search public tenders. Filter by source to scope to above-EU-threshold coverage (all 5 Nordic countries) or Norway-only coverage including below-threshold municipal tenders. Filter by buyer_orgnr to find every tender from a specific Norwegian buyer.

get_tender

Full details by ID. Accepts both EU-tier format (317565-2026) and Norway-tier format (2026-108414).

search_awards

Search contract awards (who won what, for how much).

get_tender_leaderboard

Top public-sector buyers in a Nordic country.

get_company_contract_wins

Public-sector contracts won by a Norwegian company.

Norwegian company registry
search_companies

Search by name, industry (NACE), or location.

get_company

Full registry record by orgnr.

get_company_contact

Verified emails + phones with role labels (Investor Relations, Switchboard, Media, etc.), plus named_contacts array of current key personnel (CEO, CFO, head of IR, head of communications) with role and direct contact info where publicly documented. Pattern-matched candidates included separately as candidates.

get_company_narrative

AI-generated executive summary.

get_company_peers

Peer-cohort benchmarks.

get_company_snapshot

One-call snapshot across every data source.

get_company_changes

Registry change history.

get_company_subsidiaries

Subsidiaries registered under this orgnr.

bulk_get_companies

Enrich up to 100 companies in one call.

Financials & ownership
get_company_accounts

Annual accounts (revenue, profit, equity).

get_company_shareholders

Full shareholder list (3M+ positions across 396K companies).

get_shareholder_portfolio

Reverse: all companies a person/entity owns shares in.

Officer & network graph
search_persons

Search persons in the Norwegian officer network.

get_person

Full role history across Norwegian companies.

find_company_path

Shortest path between two Norwegian companies via shared officers.

get_person_network

Who shares boards with this person (1st-degree).

News
get_company_news

Recent Norwegian-language news mentioning a company.

search_news

Free-text Norwegian news search.

EU R&D
search_eu_grants

Search EU R&D grant participations.

get_company_eu_grants

Norwegian company's Horizon Europe participations.

Tech intelligence
find_companies_using_tech

Norwegian companies using a specific technology.

Compliance
screen_for_sanctions

Screen any name against global sanctions.

check_company_sanctions

Sanctions screening for a Norwegian company + its officers.

What an agent sees: a tools/list call returns all 28 tools with input/output schemas. Each tool description is written for LLM consumption — every parameter has a hint explaining when to use it. Tools share auth, rate limit, and quota under one API key, so an agent can chain them freely (e.g. search_tendersget_company on the buyer's orgnr → get_company_shareholders) without worrying about per-tool credentials.

Setup: Claude Desktop

Edit ~/Library/Application Support/Claude/claude_desktop_config.json on macOS, or %APPDATA%\Claude\claude_desktop_config.json on Windows:

{
  "mcpServers": {
    "nordic-data": {
      "transport": "streamableHttp",
      "url":       "https://api.nordicdata.cloud/mcp",
      "headers":   { "X-API-Key": "nrd_live_..." }
    }
  }
}

Restart Claude Desktop. All 28 tools appear in the MCP picker, grouped automatically by Claude. Try a prompt like:

"Find Norwegian municipal tenders for snow clearing under 5M NOK with deadlines this month, then pull the latest accounts and shareholders for the buyer."

This single prompt will chain search_tenders (with source: DOFFIN), get_company_accounts, and get_company_shareholders automatically.

Setup: Cursor

Cursor >= 0.45 supports remote MCP servers. Edit ~/.cursor/mcp.json:

{
  "mcpServers": {
    "nordic-data": {
      "url":     "https://api.nordicdata.cloud/mcp",
      "headers": { "X-API-Key": "nrd_live_..." }
    }
  }
}

Reload the window. The tools become available to Cursor's chat agent.

Setup: any MCP-aware client

The endpoint is standards-compliant Streamable HTTP. Any client that implements the protocol can connect:

URL:     https://api.nordicdata.cloud/mcp
Method:  POST
Headers: Content-Type: application/json
         Accept: application/json, text/event-stream
         X-API-Key: nrd_live_...
Body:    JSON-RPC 2.0 messages — initialize, tools/list, tools/call, etc.

Sessions are tracked server-side via the Mcp-Session-Id response header on the initialize call. Send that header back on subsequent calls.

Build agents in code

If you're building your own agent (TypeScript, Python, etc.), connect via the official MCP SDKs.

TypeScript
Python
Anthropic SDK + MCP
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';

const client = new Client({ name: 'my-agent', version: '1.0' });
await client.connect(new StreamableHTTPClientTransport(
  new URL('https://api.nordicdata.cloud/mcp'),
  { requestInit: { headers: { 'X-API-Key': process.env.NORDIC_KEY } } }
));

const result = await client.callTool({
  name: 'search_tenders',
  arguments: { country: 'NOR', q: 'fishing', limit: 5 },
});
console.log(result.content);
from mcp import ClientSession
from mcp.client.streamable_http import streamablehttp_client
import os, asyncio

async def main():
    headers = {"X-API-Key": os.environ["NORDIC_KEY"]}
    async with streamablehttp_client("https://api.nordicdata.cloud/mcp", headers=headers) as (read, write, _):
        async with ClientSession(read, write) as session:
            await session.initialize()
            tools = await session.list_tools()
            result = await session.call_tool("search_tenders", {"country": "ALL", "q": "renewable"})
            print(result.content)

asyncio.run(main())
# Connect Claude directly to the MCP server.
import anthropic

client = anthropic.Anthropic()

response = client.messages.create(
    model="claude-opus-4-7",
    max_tokens=2048,
    mcp_servers=[{
        "type": "url",
        "url": "https://api.nordicdata.cloud/mcp",
        "name": "nordic-data",
        "authorization_token": "nrd_live_...",  # sent as Bearer; we accept X-API-Key
    }],
    messages=[{"role": "user", "content": "Find Norwegian green-energy tenders from this month."}],
)
print(response.content)

Error codes

StatusBodyMeaning
400invalid_email

Email is malformed or from a disposable provider.

400invalid_id

Tender ID does not match {number}-{year}.

401unauthorized

Missing or invalid X-API-Key.

404not_found

Tender ID did not match any record in TED.

429rate_limited

Monthly request budget exhausted.

502ted_upstream_error

TED returned an error on a fall-through fetch. Includes upstream details.

503degraded

Database is unreachable. Status mirrored at /health.

Rate limits

Limits are per calendar month, reset at midnight UTC on the first of each month.

PlanMonthlyPer-second burstMCP sessions
Starter1,0002 / sec2 concurrent
Pro50,00020 / sec10 concurrent
Business500,000200 / sec50 concurrent

If you need higher limits — e.g. you're building a real-time procurement-monitoring product — email [email protected] with your expected RPS.

CPV reference

CPV (Common Procurement Vocabulary) is the EU's classification system for procurement. Codes are 8 digits + a 1-digit checksum. The first two digits identify the broad category. Common ones:

CodeCategory
03000000

Agricultural, farming, fishing, forestry products

09000000

Petroleum products, fuel, electricity, energy sources

33000000

Medical equipment, pharmaceuticals, personal care

45000000

Construction work

50000000

Repair and maintenance services

71000000

Architectural, engineering, technical consulting

72000000

IT services: consulting, software development, internet

79000000

Business services: legal, marketing, consulting

80000000

Education and training services

85000000

Health and social work services

90000000

Sewage, refuse, cleaning, environmental services

Full reference at simap.ted.europa.eu/cpv. You can pass any leading subset: cpv=45 matches every 45xxxxxx construction code, cpv=4521 narrows to building work, cpv=45211000 is exact.

Changelog

v0.5 — 2026-05-08

v0.4 — 2026-05-08

v0.3 — 2026-05-08

v0.2 / v0.1

v0.5.0 · canonical layer

v2 endpoints + universal resolver

All v2 endpoints work against the canonical layer (38M+ companies, 78 MCP tools). Legacy /companies/{orgnr} still works — internally resolves to canonical_id, returns same shape.

Canonical company lookup

curl -H "X-API-Key: $KEY" \
  https://api.nordicdata.cloud/v2/companies/8b0a130f-e6e9-4ed6-97f3-8ebbe06dfac3

Returns canonical record + every fact + _provenance block listing source, confidence, fetched_at per field. No other provider exposes this.

Fuzzy search (38M+ companies)

curl -H "X-API-Key: $KEY" \
  "https://api.nordicdata.cloud/v2/companies/search?q=equinor&country=NO&limit=10"

Universal external-ID resolver

# Norwegian orgnr → canonical_id
curl -H "X-API-Key: $KEY" https://api.nordicdata.cloud/resolve/orgnr_no/923609016

# UK Companies House
curl -H "X-API-Key: $KEY" https://api.nordicdata.cloud/resolve/ch_uk/12424506

# US Florida state registry (prefix with state)
curl -H "X-API-Key: $KEY" https://api.nordicdata.cloud/v2/companies/us/fl/P99000055174

# LEI
curl -H "X-API-Key: $KEY" https://api.nordicdata.cloud/resolve/lei/213800OW6OFBNCKXC4US5C7523

310 schemes resolvable: orgnr_no, orgnr_se, business_id_fi, cvr_dk, ch_uk, us_registry, lei, ein, duns, sanctions_id, etc.

1.6M-entity sanctions screen

# Single name
curl -H "X-API-Key: $KEY" "https://api.nordicdata.cloud/sanctions/search?q=putin"

# Bulk (up to 100 names)
curl -X POST -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
  -d '{"names":["Vladimir Putin","Alexander Lukashenko","Kim Jong-un"]}' \
  https://api.nordicdata.cloud/sanctions/screen-bulk

Cross-jurisdiction officer match

curl -H "X-API-Key: $KEY" \
  https://api.nordicdata.cloud/v2/companies/{canonical_id}/global-officers

Returns every company every director of this company sits on, across jurisdictions. The killer KYB signal — surface directors holding 200+ seats across registries.

Per-fact provenance

curl -H "X-API-Key: $KEY" \
  https://api.nordicdata.cloud/v2/companies/{canonical_id}/provenance

Tell auditors exactly where each address, employee count, industry code came from and when. Required for SOC2 / ISO 27001 customer questionnaires.

Async bulk export

# Submit job
curl -X POST -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
  -d '{"filter":{"country":"NO","industry_code":"64.20"},"format":"jsonl"}' \
  https://api.nordicdata.cloud/exports/companies
# → { "job_id": 42, "status": "pending", "check_url": "/exports/42" }

# Poll for status
curl -H "X-API-Key: $KEY" https://api.nordicdata.cloud/exports/42

# Webhook fires on completion if subscribed to export.completed

GDPR self-serve

# Article 17 (erasure)
curl -X POST -H "Content-Type: application/json" \
  -d '{"name":"Jane Doe","country":"NO","reason":"private"}' \
  https://api.nordicdata.cloud/gdpr/opt-out

# Article 15 (subject access)
curl -X POST -H "Content-Type: application/json" \
  -d '{"email":"[email protected]","subject_name":"Jane Doe","country":"NO"}' \
  https://api.nordicdata.cloud/gdpr/access

MCP — point Claude Desktop at us

{
  "mcpServers": {
    "nordic-data": {
      "url": "https://api.nordicdata.cloud/mcp",
      "headers": { "X-API-Key": "your_key" }
    }
  }
}

78 tools. Get a free key at nordicdata.cloud. Sandbox key for evaluation: sandbox_try_2026 (30 calls/hour).

OpenAPI 3.0

Machine-readable API spec

Full OpenAPI 3.0 spec at /openapi.json. Use it to auto-generate SDKs (Stainless, Speakeasy, openapi-typescript-codegen, openapi-python-client), import into Postman/Insomnia/Bruno, or feed to your AI agent for instant familiarity with every endpoint.

# Generate a TypeScript SDK
npx openapi-typescript-codegen --input https://nordicdata.cloud/openapi.json --output ./nordic-data-sdk

# Generate a Python SDK
openapi-python-client generate --url https://nordicdata.cloud/openapi.json

# Or just import into Postman: File → Import → URL → https://nordicdata.cloud/openapi.json