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.
Recipe 2 — Discover companies via natural language
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:
- Discovery + filter:
/companies/{no|se|us}/list,/companies/lookup,/companies/near,/companies/nl-search,/companies/bulk-lookup - Resolvers:
/resolve/{email,domain,phone,iban,vat,lei,address,person,wikipedia} - KYB / Compose / Verify:
/companies/{orgnr}/{kyb-pack,diff,timeline,onboarding-form,credit-application-pack,supplier-form,proposal-context},/verify/{invoice,email,officer} - AI / NL:
/companies/{orgnr}/{q,explain,talking-points,risk-narrative} - Cross-entity:
/companies/similar/{orgnr},/companies/{orgnr}/{sister-companies,group-structure,decision-makers,buying-committee,shell-likelihood} - Signals (rule-based):
/companies/{orgnr}/{health-score,growth-signals,distress-signals,buyer-intent-score,employee-history,board-stability} - Procurement intel:
/tenders/{active-by-buyer,predict-winner,expiring-soon},/buyers/.../typical-suppliers,/suppliers/.../typical-buyers,/contracts/renewal-radar - Monitoring:
/watchlistsCRUD,/portfoliosCRUD,/triggersCRUD - Outputs:
/exports/{csv,excel},/spreadsheet/enrich - Audit / trust:
/audit/{data-provenance,freshness-report,citations} - Time-series & geo:
/companies/{orgnr}/revenue-trajectory,/companies/heatmap,/regions/{code}/economic-profile - US extension:
/companies/us/{search,lookup,list,{cik},{cik}/{filings,contracts,sanctions,contact,kyb-pack,explain,q}}
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.
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 want | REST | MCP tool |
|---|---|---|
| Find a company by name or industry | GET /companies/search | search_companies |
| Full profile (identity, NACE, address, logo, founded year, description, official website, LEI) | GET /companies/:orgnr | get_company |
| Enrichment only — logo, description, founded year, website, industry, LEI | GET /companies/:orgnr/enrichment | get_company_enrichment |
| AI bio / "tell me about X" — 3-4 sentence narrative | GET /companies/:orgnr/narrative | get_company_narrative |
| Financials — revenue, profit, balance sheet, ratios | GET /companies/:orgnr/accounts | get_company_accounts |
| Peer-cohort benchmarks (percentile rank vs sector) | GET /companies/:orgnr/peer-benchmarks | get_company_peers |
| Email + phone (verified, MX-checked) | GET /companies/:orgnr/contact | get_company_contact |
| Officers — board, directors, executives, signatories | GET /companies/:orgnr/officers | via get_company with include_officers |
| Shareholders — full cap table + ownership % | GET /companies/:orgnr/shareholders | get_company_shareholders |
| Subsidiaries / daughter companies | GET /companies/:orgnr/subsidiaries | get_company_subsidiaries |
| Registry change history (status changes, address moves, etc.) | GET /companies/:orgnr/changes | get_company_changes |
| Tech stack — what SaaS / CMS / payments tools they use | GET /companies/:orgnr/tech | via get_company_snapshot |
| News + press mentions | GET /companies/:orgnr/news | get_company_news |
| EU R&D grants this company received | GET /companies/:orgnr/eu-grants | get_company_eu_grants |
| Tenders this public-sector entity published (as buyer) | GET /companies/:orgnr/notices | via search_tenders with buyer_orgnr |
| Tenders / contracts this company has WON (as supplier) | GET /companies/:orgnr/contract-wins | get_company_contract_wins or search_tenders with winner_orgnr |
| Monthly tender velocity (for a public buyer) | GET /companies/:orgnr/tender-velocity | get_company_tender_velocity |
| Sanctions / AML / KYC check (company + auto-fetched officers) | GET /companies/:orgnr/sanctions-check | check_company_sanctions |
| Everything in one call — snapshot across all data | GET /companies/:orgnr/snapshot | get_company_snapshot |
| Bulk enrich up to 100 companies | POST /companies/bulk | bulk_get_companies |
| Recent bankruptcies (credit-risk early warning) | GET /companies/bankruptcies | list_recent_bankruptcies |
United States — business discovery + lead enrichment
- 1.26M+ verified active US businesses — every one has a payroll history. Filterable by industry (NAICS code or 2-5 digit prefix), US state, city, and employee count.
- Lead enrichment per company — auto-discover the company's website, scrape contacts (emails + phones with labels), detect tech stack, identify email provider (Google Workspace / Microsoft 365 / Zoho / Proton / etc.), extract LinkedIn + Twitter + GitHub URLs, surface named executives when available.
- Sales-shaped contact discovery — plain-English filter (industry + role + region + size) returns a flat list of contacts ready to import into your CRM, with verified emails and direct phones where available.
- Public-company depth — SEC-registered companies get identity, recent filings, and federal contract history.
People, ownership & network graph
| What you want | REST | MCP tool |
|---|---|---|
| Search persons in the officer network | GET /persons/search | search_persons |
| Person — full role history across companies | GET /persons/:id | get_person |
| Who is this person connected to (shared boards)? | GET /persons/:id/network | get_person_network |
| Single-person sanctions check | GET /persons/:id/sanctions-check | check_person_sanctions |
| Are two companies connected via shared officers? | GET /companies/:orgnr/path-to/:other | find_company_path |
| Reverse shareholder lookup — what does X own? | GET /shareholders/portfolio | get_shareholder_portfolio |
Public procurement (5 Nordic countries)
| What you want | REST | MCP tool |
|---|---|---|
| Search tenders by country / industry / keyword / company | GET /tenders/search | search_tenders |
| Single tender by ID | GET /tenders/:id | get_tender |
| Top public-sector buyers (leaderboard) | GET /tenders/leaderboard | get_tender_leaderboard |
| Search awarded contracts (winner / value / period) | GET /awards/search | search_awards |
| Top suppliers winning contracts (leaderboard) | GET /awards/leaderboard | get_award_leaderboard |
Sanctions / AML
| What you want | REST | MCP tool |
|---|---|---|
| Screen any free-text name (person or org, any nationality) | GET /sanctions/screen | screen_for_sanctions |
| Bulk screen many names in one call | POST /sanctions/screen-bulk | — |
| One-call company + all-officers AML | GET /companies/:orgnr/sanctions-check | check_company_sanctions |
| Single-person AML | GET /persons/:id/sanctions-check | check_person_sanctions |
EU R&D grants
| What you want | REST | MCP tool |
|---|---|---|
| Search grants (country / framework / topic / amount) | GET /grants/search | search_eu_grants |
| Single grant project — full participant roster | GET /grants/:id | get_eu_grant |
| Grants for one Norwegian company | GET /companies/:orgnr/eu-grants | get_company_eu_grants |
Tech-stack intelligence
| What you want | REST | MCP tool |
|---|---|---|
| What tech does company X use? | GET /companies/:orgnr/tech | via get_company_snapshot |
| Reverse — which Norwegian companies use technology Y? | GET /tech/:tech/companies | find_companies_using_tech |
News
| What you want | REST | MCP tool |
|---|---|---|
| Free-text search Norwegian news | GET /news/search | search_news |
| News mentioning a specific company | GET /companies/:orgnr/news | get_company_news |
Other Nordic registries
| What you want | REST | MCP tool |
|---|---|---|
| Sweden — identity by 10-digit orgnr | GET /companies/se/:orgnr | get_company with country=SWE |
| Sweden — enriched contacts (emails, phones, named execs) | GET /companies/se/:orgnr/contact | get_company_se_contact |
| Denmark — identity + phone + employees | GET /companies/dk/:cvr | get_company with country=DNK |
| Finland — identity + name history | GET /companies/fi/:id | get_company with country=FIN |
| Iceland — name search | GET /companies/is/search | — |
Countries
Five Nordic registers are indexed. Use the country parameter on search:
| Code | Name | Source register |
|---|---|---|
| NOR | Norway | Full coverage including below-EU-threshold municipal/county notices that no other Nordic API exposes cleanly. |
| SWE | Sweden | EU-tier coverage of above-EU-threshold notices. |
| DNK | Denmark | EU-tier coverage of above-EU-threshold notices. |
| FIN | Finland | EU-tier coverage of above-EU-threshold notices. |
| ISL | Iceland | EU-tier coverage of above-EU-threshold notices. |
| ALL | Cross-Nordic | All 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.
Search tenders GET/tenders/search
Returns tenders sorted by publication date, newest first. Combine any of the filters below.
| Param | Type | Description |
|---|---|---|
| country | string | NOR, SWE, DNK, FIN, ISL, or ALL. Defaults to |
| q | string | Full-text search across title and description (PostgreSQL |
| cpv | string | CPV classification code, e.g. |
| from | YYYY-MM-DD | Earliest publication date to include. |
| to | YYYY-MM-DD | Latest publication date to include. |
| limit | integer | 1–100. Default 20. |
| page | integer | 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 companies GET/companies/search
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.
| Param | Type | Description |
|---|---|---|
| q | string | Fuzzy name match. e.g. |
| orgnr | string | 9-digit Norwegian organisation number for direct lookup. Skips name search and returns the single matching company. |
| nace | string | NACE industry code, e.g. |
| limit | integer | 1–100. Default 20. |
| page | integer | 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):
- Website crawl — fetches the company's own contact / about / press / investor-relations pages and pulls emails, phones, and JSON-LD
Organizationschema. - Directory fallback — phonebook lookup for the registered company name + city. Catches switchboards and direct lines missing from the website.
- 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.
- 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:
| Field | Description |
|---|---|
emails | Verified business email addresses. Excludes form-only inboxes, recruiters, third-party SaaS domains, placeholders. |
phones | Phone numbers in +47 XXX XX XXX format. Aggregated from company website, structured page data, directory lookup, and AI enrichment. |
labels | Per-contact role/department hint, keyed "email:..." or "phone:...". Examples: "Investor Relations", "Switchboard", "CEO: Jane Doe". |
named_contacts | Array of key personnel sourced via web search. Each entry: name, role, optional email, optional phone. Filtered to current-role only — no former/retired employees. |
candidates | Pattern-guessed emails (post@, kontakt@, info@) at the company's domain. Not verified — probe before transactional use. |
cached | true if served from cache (TTL 30 days), false if freshly crawled. |
enrichment_in_progress | Present and true when web-search enrichment is running in the background for this company. Refresh in 30 s for the fully-enriched 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
}
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"
OPT-301-Organization-Identifier field.
Company object schema
| Field | Type | Description |
|---|---|---|
| orgnr | string | 9-digit Norwegian organisation number. Stable identifier. |
| name | string | Registered legal name. |
| legal_form | object |
|
| registered | YYYY-MM-DD | Date the entity was first registered in Norwegian registry. |
| in_business_registry | boolean | Listed in Foretaksregisteret (commercial entities). |
| in_vat_registry | boolean | VAT-registered (Mva-registeret). |
| status | string | One of |
| nace | array | Up to three NACE industry codes with descriptions, in declared priority order. |
| employees | integer? | Reported employee count. |
| business_address | object? | Physical address. |
| postal_address | object? | Postal address. |
| website | string? | Self-declared website. |
| sector | object? | Institutional sector code per Statistics Norway, with description. |
| parent_orgnr | string? | Organisation number of the parent entity, if any. |
| bankruptcy | boolean | True if currently in bankruptcy proceedings. |
Tender object schema
/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.)
| Field | Type | Description |
|---|---|---|
| id | string | Stable identifier. EU-tier format: |
| source | string | Indicates which coverage tier the notice came from. Use this for downstream routing or display. |
| title | string | Notice title. EU-tier titles are English-first multilingual. Norway-tier titles are Norwegian. |
| buyer.name | string | Contracting authority name. |
| buyer.orgnr | string? | 9-digit Norwegian organisation number. Always present for Norway-tier notices; null for non-Norwegian EU-tier notices. |
| buyer.city | string | City or region of the contracting authority (granularity varies by coverage tier). |
| buyer.country | string | ISO 3166-1 alpha-3 country code. Norway-tier notices are always |
| publication_date | YYYY-MM-DD | Date the notice was first published. |
| deadline | YYYY-MM-DD? | Tender response deadline. |
| contract_nature | string[] | One or more of |
| cpv_codes | string[] | CPV (Common Procurement Vocabulary) codes. EU-tier coverage only. |
| description | string? | Description summary. EU-tier coverage is multilingual joined with |
| total_value | number? | Estimated or awarded total value. EU-tier coverage normalises to EUR; Norway-tier coverage returns the original currency (see |
| currency | string? | ISO 4217 currency code (e.g. |
| procedure_type | string? | EU-tier: procedure code ( |
| notice_url | URL | 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:
GET /agent/plans— discover plans + pricesPOST /agent/subscribe— subscribe with a Stripe payment method, get a working API key in the responsePOST /agent/change-plan— upgrade or downgrade in place using the API key as auth
No browser. No hosted Checkout page. No email round-trip. No Customer Portal.
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.
| Field | Type | Description |
|---|---|---|
| string | Required. Owner email — also used to deduplicate (one active subscription per email). | |
| plan | string | Required. One of |
| payment_method | string | Required. Stripe PaymentMethod ID ( |
| country | string | Required. ISO 3166-1 alpha-2 code (e.g. |
| agent_name | string? | 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:
400 invalid_email/invalid_plan/invalid_payment_method— bad input402 card_declined— Stripe refused the card. Body includes Stripe'scode.402 payment_incomplete— subscription created but card needs 3DS or extra auth. Body includessubscription_idandstatus.409 already_subscribed— this email already has an active paid subscription. Use/agent/change-planwith the existing key instead.503 stripe_not_configured— server misconfiguration.
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.
| Tool | Use for |
|---|---|
| Procurement | |
| search_tenders | Search public tenders. Filter by |
| get_tender | Full details by ID. Accepts both EU-tier format ( |
| 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 |
| 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. |
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_tenders → get_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.
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
| Status | Body | Meaning |
|---|---|---|
| 400 | invalid_email | Email is malformed or from a disposable provider. |
| 400 | invalid_id | Tender ID does not match |
| 401 | unauthorized | Missing or invalid |
| 404 | not_found | Tender ID did not match any record in TED. |
| 429 | rate_limited | Monthly request budget exhausted. |
| 502 | ted_upstream_error | TED returned an error on a fall-through fetch. Includes upstream details. |
| 503 | degraded | Database is unreachable. Status mirrored at /health. |
Rate limits
Limits are per calendar month, reset at midnight UTC on the first of each month.
| Plan | Monthly | Per-second burst | MCP sessions |
|---|---|---|---|
| Starter | 1,000 | 2 / sec | 2 concurrent |
| Pro | 50,000 | 20 / sec | 10 concurrent |
| Business | 500,000 | 200 / sec | 50 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:
| Code | Category |
|---|---|
| 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
- Companies API (Norway) — search, lookup, officers, tender-history join, all unified by Norwegian organisation number.
- Two new MCP tools:
search_companies,get_company. - Cross-product join:
GET /companies/{orgnr}/noticesreturns tenders where a company is the buyer. - Same API key works across both products. Pooled monthly limit.
v0.4 — 2026-05-08
- Cross-Nordic search:
country=ALLacross NOR/SWE/DNK/FIN/ISL. - SWE, DNK, FIN, ISL bootstrapped with 90-day history.
- Background sync now covers all 5 countries every 30 min.
/countriesendpoint with live counts per country.- Disposable-email blocking on key issuance.
- Public
/signupwith email verification + Stripe checkout for paid plans. - CPV leading-subset filter:
cpv=45matches every45xxxxxxcode. - This documentation page.
v0.3 — 2026-05-08
- API key auth on
/tenders/*and/mcp. - MCP server with stateful sessions over Streamable HTTP.
- Local DB cache with 30-min TED sync.
v0.2 / v0.1
- Initial REST API: search, get-by-id. Norwegian tenders only.