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 1,000 requests per month — plenty to evaluate the data.

2. Hit the API

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

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.

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.

Countries

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

CodeNameSource register
NORNorwayDoffin (above-EU-threshold notices via TED)
SWESwedenMercell.se / TED
DNKDenmarkUdbud.dk / TED
FINFinlandHilma / TED
ISLIcelandÚtboðsvefur / TED
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/318369-2026/eng"
    }
  ]
}

Get one tender GET/tenders/:id

Fetch a single tender by its TED 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 Brønnøysund business registry by name, organisation number, or NACE industry code. Norway-only in v0.5; Sweden, Denmark, Finland, Iceland coming.

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,
  "source": "brreg",
  "source_urls": { "registry": "https://w2.brreg.no/enhet/sok/detalj.jsp?orgnr=923609016" }
}

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. 1881.no fallback — directory listing for the registered company name + city. Catches switchboards and direct lines missing from the website.
  3. LLM extraction (Haiku 4.5) — 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. Web-search enrichment (Sonnet 4.5) — fires for every company in the background. Uses Anthropic's web_search tool to find 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.

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": [
    "apost@equinor.com",
    "irpost@equinor.com",
    "methanol@equinor.com",
    "safetyandenvironment@equinor.com"
  ],
  "phones": [
    "+47 519 90 000",
    "+47 412 60 584",
    "+47 480 80 212",
    "+47 918 01 791"
  ],
  "labels": {
    "email:irpost@equinor.com": "Investor Relations",
    "email:apost@equinor.com": "Authorities Contact (Norway)",
    "email:methanol@equinor.com": "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": [
    "post@equinor.com",
    "kontakt@equinor.com",
    "info@equinor.com"
  ],
  "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. Sources: company website, JSON-LD, 1881.no, web search.
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".

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 Enhetsregisteret.

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 sources, one table. The /tenders/* endpoints return notices from TED (above-EU-threshold, all 5 Nordic countries) and Doffin (Norway-only, including below-threshold municipal/county procurements that TED never sees). Each result includes a source field ("TED" or "DOFFIN"). Filter by source via ?source=DOFFIN on search, or by Norwegian buyer org-number via ?buyer_orgnr=941827195.
FieldTypeDescription
idstring

Stable identifier. TED format: 317565-2026 (number-year). Doffin format: 2026-108414 (year-number).

sourcestring

"TED" or "DOFFIN". Indicates which database the notice came from.

titlestring

Notice title. TED titles are English-first multilingual. Doffin titles are Norwegian.

buyer.namestring

Contracting authority name.

buyer.orgnrstring?

9-digit Norwegian organisation number. Always present for Doffin notices; null for non-Norwegian TED notices.

buyer.citystring

City (TED) or region (Doffin) of the contracting authority.

buyer.countrystring

ISO 3166-1 alpha-3 country code. Doffin 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. TED only — Doffin search-API does not expose this yet.

cpv_codesstring[]

CPV (Common Procurement Vocabulary) codes. TED only — Doffin search-API does not expose CPV.

descriptionstring?

Description summary. TED is multilingual joined with | if no English; Doffin is Norwegian.

total_valuenumber?

Estimated or awarded total value. TED normalises to EUR; Doffin returns the original currency (see currency).

currencystring?

ISO 4217 currency code (e.g. NOK) when total_value is in non-EUR. Doffin only — TED values are always EUR.

procedure_typestring?

TED: procedure code (open, restricted, negotiated, etc.). Doffin: 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":          "agent@example.com",
    "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 (TED + Doffin)
search_tenders

Search public tenders. Filter by source: TED (above-EU-threshold, all 5 Nordic countries) or source: DOFFIN (Norway only, includes 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 TED format (317565-2026) and Doffin 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 from Aksjonærregisteret (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 Horizon Europe grants (Cordis).

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 OFAC SDN + EU 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 support@nordicdata.cloud 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