Data source: Doffin, TED
Overview
Public Procurement searches across 2 data sources (Doffin, TED) in a single query. It deduplicates and normalizes results, saving you from building 2 separate integrations. This tutorial walks through all 4 tools with working code examples.
Prerequisites
- Sign up at https://context.gnist.ai/signup for a free API key (100 calls/day).
- Choose your integration method: MCP protocol or REST API.
Connect via MCP
Add to your MCP client config (Claude Desktop, Cursor, etc.):
{
"mcpServers": {
"gnist-public-procurement": {
"url": "https://context.gnist.ai/mcp/public-procurement/",
"headers": {
"Gnist-API-Key": "YOUR_API_KEY"
}
}
}
}
Tools (4)
search_tenders
Search for public procurement tenders across Doffin (Norway) and TED (EU/EEA). Results are deduplicated when the same tender appears on both platforms. Sorted by publication date (most recent first). Examples: search_tenders(query="software development") search_tenders(query="construction", country="NOR", cpv_code="45000000") search_tenders(query="IT consulting", published_after="2026-01-01", max_results=10)
| Parameter | Type | Required | Description |
|---|---|---|---|
query | string | required | Search query — keywords, buyer name, or topic. |
max_results | integer | optional | Maximum number of results. (default: 20) |
country | any | optional | ISO 3166-1 alpha-3 country code (e.g. NOR, DEU, FRA). Omit for all countries. |
cpv_code | any | optional | CPV code to filter by sector (8 digits, e.g. 72000000 for IT). |
published_after | any | optional | Only tenders published after this date (YYYY-MM-DD). |
published_before | any | optional | Only tenders published before this date (YYYY-MM-DD). |
curl -X POST "https://context.gnist.ai/mcp/public-procurement/" \
-H "Content-Type: application/json" \
-H "Gnist-API-Key: YOUR_API_KEY" \
-d '{"jsonrpc": "2.0", "method": "tools/call", "id": 1, "params": {"name": "search_tenders", "arguments": {"query": "renewable energy"}}}'
import httpx
resp = httpx.post(
"https://context.gnist.ai/mcp/public-procurement/",
headers={"Gnist-API-Key": "YOUR_API_KEY"},
json={'id': 1,
'jsonrpc': '2.0',
'method': 'tools/call',
'params': {'arguments': {'query': 'renewable energy'},
'name': 'search_tenders'}},
)
print(resp.json())
get_tender
Look up a specific procurement notice by ID across all sources. Accepts either a Doffin notice ID (e.g. '2026-105515') or a TED publication number (e.g. '555-2026'). If the tender exists on both platforms, the results are merged into a single enriched record. Examples: get_tender(notice_id="2026-105515") get_tender(notice_id="555-2026")
| Parameter | Type | Required | Description |
|---|---|---|---|
notice_id | string | required | Notice ID — Doffin format (YYYY-NNNNNN) or TED format (NNNN-YYYY). |
curl -X POST "https://context.gnist.ai/mcp/public-procurement/" \
-H "Content-Type: application/json" \
-H "Gnist-API-Key: YOUR_API_KEY" \
-d '{"jsonrpc": "2.0", "method": "tools/call", "id": 1, "params": {"name": "get_tender", "arguments": {"notice_id": "12345"}}}'
import httpx
resp = httpx.post(
"https://context.gnist.ai/mcp/public-procurement/",
headers={"Gnist-API-Key": "YOUR_API_KEY"},
json={'id': 1,
'jsonrpc': '2.0',
'method': 'tools/call',
'params': {'arguments': {'notice_id': '12345'}, 'name': 'get_tender'}},
)
print(resp.json())
list_procurement_sources
List all registered procurement data sources and their status. Shows which sources are available and whether they are currently enabled. Examples: list_procurement_sources()
curl -X POST "https://context.gnist.ai/mcp/public-procurement/" \
-H "Content-Type: application/json" \
-H "Gnist-API-Key: YOUR_API_KEY" \
-d '{"jsonrpc": "2.0", "method": "tools/call", "id": 1, "params": {"name": "list_procurement_sources", "arguments": {}}}'
import httpx
resp = httpx.post(
"https://context.gnist.ai/mcp/public-procurement/",
headers={"Gnist-API-Key": "YOUR_API_KEY"},
json={'id': 1,
'jsonrpc': '2.0',
'method': 'tools/call',
'params': {'arguments': {}, 'name': 'list_procurement_sources'}},
)
print(resp.json())
report_feedback
Report a bug, feature request, or general feedback for this data source. Use this when something doesn't work as expected, when you'd like a new feature, or when you have suggestions for improvement. Args: feedback: Describe the issue or suggestion. feedback_type: One of 'bug', 'feature_request', or 'general'.
| Parameter | Type | Required | Description |
|---|---|---|---|
feedback | string | required | |
feedback_type | string | optional | (default: general) |
curl -X POST "https://context.gnist.ai/mcp/public-procurement/" \
-H "Content-Type: application/json" \
-H "Gnist-API-Key: YOUR_API_KEY" \
-d '{"jsonrpc": "2.0", "method": "tools/call", "id": 1, "params": {"name": "report_feedback", "arguments": {"feedback": "example"}}}'
import httpx
resp = httpx.post(
"https://context.gnist.ai/mcp/public-procurement/",
headers={"Gnist-API-Key": "YOUR_API_KEY"},
json={'id': 1,
'jsonrpc': '2.0',
'method': 'tools/call',
'params': {'arguments': {'feedback': 'example'}, 'name': 'report_feedback'}},
)
print(resp.json())
Common Patterns
Use
search_tenders to find items, then get_tender to get full details. This two-step pattern is common for exploring data before drilling down.Several tools support
limit, offset, or page parameters. Start with small limits during development, then increase for production queries.FAQ
What data does Public Procurement provide?
Public procurement — unified search across Doffin (Norwegian) and TED (EU/EEA) tender databases. It exposes 4 tools: search_tenders, get_tender, list_procurement_sources, report_feedback.
What do I need to get started?
A Gnist API key (free tier: 100 calls/day). Sign up at https://context.gnist.ai/signup.
What format does the Public Procurement API return?
JSON, via either MCP protocol (JSON-RPC 2.0) or REST API.
Which data sources does Public Procurement aggregate?
Doffin, TED. Results are deduplicated and normalized into a consistent format.