TED tenders API: how to search EU public procurement notices
TED (Tenders Electronic Daily) is the EU's official journal for public procurement: calls for tenders, prior information notices and contract award notices from public buyers across the EU and beyond. Its Search API is free and needs no key for searching. This guide shows a working query, the quirks you will meet when you build on it, and TED Tenders API – EU Public Procurement Search, an Apify actor that turns the results into clean rows with English titles, EUR values, deadlines, lots and winners, plus an "only new" mode for daily tender alerts.
Run it on Apify Opens the actor's page on apify.com. A free Apify account is needed to run it.
Only need one quick search right now? Try the free TED tender search: it runs on this site with no sign-up.
Call the TED Search API yourself
The endpoint is POST https://api.ted.europa.eu/v3/notices/search (official docs). You send an expert-search query and the list of fields you want back. This query asks for open calls for tenders mentioning software from German and Austrian buyers published since 5 October 2026:
curl -s -X POST https://api.ted.europa.eu/v3/notices/search \
-H 'Content-Type: application/json' \
-d '{
"query": "FT ~ (software) AND form-type IN (competition) AND buyer-country IN (DEU AUT) AND publication-date>=20261005 SORT BY publication-number DESC",
"fields": ["publication-number", "notice-title", "buyer-name", "deadline-receipt-tender-date-lot", "estimated-value-proc"],
"limit": 3,
"scope": "ACTIVE"
}'
On 2026-10-12 it reported 225 matching notices. The first one came back like this:
{
"publication-number": "704126-2026",
"notice-title": {"eng": "Germany – Software supply services – VEEAM Handelspartnervergabe", "deu": "…"},
"buyer-name": {"deu": ["Die Autobahn GmbH des Bundes"]},
"deadline-receipt-tender-date-lot": ["2026-11-10+01:00"]
}
Useful query fields:
| Field | Example | Notes |
|---|---|---|
FT | FT ~ (software) | Full text in every language version. Broad: the third hit in our test was a lift renewal that mentions software somewhere |
notice-title | notice-title ~ (cloud) | Stricter keyword match on the title |
classification-cpv | classification-cpv IN (72000000 48000000) | 8-digit CPV codes; a code covers the codes below it |
buyer-country | buyer-country IN (BGR ROU) | Three-letter ISO codes |
place-of-performance | place-of-performance IN (BG411) | Country or NUTS region codes |
form-type | form-type IN (competition) | planning, competition, result and others |
publication-date | publication-date>=20261001 | YYYYMMDD |
deadline-receipt-tender-date-lot | …>=20261012 | Use it to keep only tenders still open |
What you will have to handle
- Paging.
limitis at most 250, and (number of fields + 1) × limit must stay at or below 10,000. For big result sets use"paginationMode": "ITERATION"and pass backiterationNextToken; the API returns a token even on the last page, so stop on a short page. - Rate limits. In our tests, bursts of about 25 requests in 10 seconds got HTTP 429. One request per second is safe.
- Multilingual fields. Names, titles and descriptions come back as
{"deu": [...], "eng": [...]}maps. TED translates titles into all languages as "Country – CPV category – original title"; descriptions and buyer names stay in the original language. - Currencies. Values are in the buyer's currency (PLN, CZK, SEK…). Comparing them needs exchange rates.
- Lots and winners. Deadlines, values and winners can sit at lot level, spread across parallel arrays.
- Change notices. Corrections create new versions; set
onlyLatestVersionsor you will count the same tender twice. - Alerts need memory. To send only new notices you must store what you already delivered.
None of this is hard, but it adds up to a few days of work and some upkeep. That is the gap the actor fills.
Search TED without code
- Open TED Tenders API on Apify.
- Set any filters: keywords, CPV codes, countries or NUTS regions, notice types, value range, "Only open tenders". Filters combine with AND; several values inside one filter combine with OR.
- Pick the period: Published in the last N days (default 7) or exact dates.
- Click Start. Results come newest first; export CSV or Excel, or use the Tenders and Contract awards views.
Your filters become a TED expert query, shown in the log and the SUMMARY record, so you can always check what was asked. Advanced users can add conditions in the TED expert query field. Values are converted to EUR with the latest ECB reference rates.
A call for tenders from a real run on 2026-10-03, shortened:
{
"publicationNumber": "681471-2026",
"noticeUrl": "https://ted.europa.eu/en/notice/-/detail/681471-2026",
"noticeTypeLabel": "Contract notice",
"title": "Bulgaria – Motor vehicles – PPD26-110 „Доставка на нови неупотредявани автомобили“",
"buyerName": "Електроразпределителни мрежи Запад ЕАД",
"buyerCountry": "BGR",
"cpvMain": "34100000",
"deadline": "2026-11-03T23:59:59+02:00",
"daysUntilDeadline": 31,
"isOpen": true,
"estimatedValueEur": 2545000.0,
"submissionUrl": "https://app.eop.bg/today/608285",
"lotCount": 5
}
And a contract award with its winner:
{
"publicationNumber": "681004-2026",
"noticeTypeLabel": "Contract award notice",
"buyerName": "Państwowy Fundusz Rehabilitacji Osób Niepełnosprawnych",
"awardedValue": 13884357.4, "awardedValueCurrency": "PLN", "awardedValueEur": 3171754.97,
"winners": [{"name": "SOFTIQ Sp. z o.o.", "country": "POL", "size": "medium"}]
}Worked examples with real numbers
1. Every open tender in one country
{
"countries": [
"BG"
],
"noticeTypes": [
"competition"
],
"publishedWithinDays": 14,
"onlyOpen": true,
"maxItems": 200
}
On 2026-10-03 this matched 298 notices; the first 200 were output in 2 API requests. Of those 200: 105 supplies, 62 services and 33 works contracts; 192 open procedures. All 200 had an estimated value, a median of about €230,000 and €521 million in total. The most common categories were construction work (10), electricity (8) and medical consumables (8).
2. Who won IT contracts above €100,000?
{
"cpvCodes": [
"72",
"48"
],
"countries": [
"DE",
"AT",
"FR",
"PL"
],
"noticeTypes": [
"result"
],
"publishedWithinDays": 7,
"minValueEur": 100000,
"maxItems": 300
}
42 award notices matched; 36 remained after the EUR value filter (Polish zloty converted at ECB rates): 15 from Poland, 13 Germany, 7 France, 1 Austria, worth €67.1 million together. 7 of the 35 winner names were withheld because they could be sole traders (see limits).
3. A daily tender alert
{
"keywords": [
"software",
"cloud computing"
],
"cpvCodes": [
"72",
"48"
],
"countries": [
"BG",
"RO"
],
"noticeTypes": [
"competition"
],
"onlyOpen": true,
"publishedWithinDays": 7,
"onlyNew": true
}
Schedule it every weekday morning and connect an integration (email, Slack, Google Sheets or a webhook) to the run's dataset. In our alert test the first run output 476 notices, an immediate second run 0, and after we deleted 3 entries from the alert memory exactly those 3 came back. The 7-day window means a missed run never loses notices.
Handy CPV prefixes: 72 IT services, 48 software, 45 construction, 33 medical equipment, 79 business services, 71 architecture and engineering, 90 environmental services, 34 transport equipment, 30 office and computing machinery, 09 fuels and energy.
What each row contains
| Field | What it holds |
|---|---|
publicationNumber, noticeUrl, pdfUrl, xmlUrl | TED identifiers and links |
noticeType, noticeTypeLabel, formType | Planning, contract notice, contract award and so on |
title, mainCategory, titleOriginal, originalLanguage | English (or your chosen language) title and the original |
buyerName, buyerCountry, buyerCity, buyerType, buyerWebsite | Who is buying |
cpvMain, cpvCodes, placeOfPerformanceNuts | What and where |
deadline, deadlineType, daysUntilDeadline, isOpen | Tender or request-to-participate deadline |
estimatedValue…, awardedValue… (with …Eur) | Original values and EUR conversions |
winnerNames, winners[] | Company winners with country, size and registration number |
lots[], procedureType, contractNature, submissionUrl | Lots, procedure and the e-tendering link |
Honest limits
- TED is not every tender. It carries notices above the EU thresholds plus some voluntary ones. Many smaller tenders appear only on national portals.
- Translation is title-only. Descriptions and lot titles stay in the original language. Full-text search works in any EU language.
- Values are what buyers publish. Some notices have none, or only per lot or per framework agreement; value filters drop notices without a value.
- Winner names are withheld when they might be a person. A name is shown only if it contains a company or organisation marker (GmbH, Sp. z o.o., S.A., Ltd, University…); otherwise
nameWithheld: truekeeps country and size. In a 3,000-notice test, 14% of winner entries were withheld. - No contact persons. E-mail addresses and phone numbers are removed from descriptions.
TED notices are official EU publications reusable for commercial and non-commercial purposes under Commission Decision 2011/833/EU. Not affiliated with the EU Publications Office.
All input fields
Generated from the actor's live input schema (build 1.0.3).
| Field | Type | Default | What it does |
|---|---|---|---|
Keywordskeywords | array | Notices matching ANY of these words or phrases. Searches the full notice text in all languages (or only titles, see below). Supports * wildcards, for example soft*. | |
CPV codes (business sectors)cpvCodes | array | Common Procurement Vocabulary codes. A short code covers everything below it: 72 = all IT services, 45 = all construction work, 33 = medical equipment, 48 = software packages. | |
Place of performance (countries or NUTS regions)countries | array | Where the contract is carried out. Country codes (BG, DE, FR or BGR, DEU) or NUTS region codes (BG411 = Sofia, DE21 = Upper Bavaria). | |
Buyer countriesbuyerCountries | array | Country of the contracting authority. Usually the same as the place of performance, but differs for EU institutions and cross-border projects. | |
Notice typesnoticeTypes | array | competition = calls for tenders (contract notices), result = contract awards with winners, planning = prior information notices, dir-awa-pre = direct award announcements, cont-modif = contract modifications, consultation = pre-market consultations. Empty = all types. Options: competition, result, planning, dir-awa-pre, cont-modif, consultation | |
Contract typescontractTypes | array | Works, supplies and/or services. Empty = all. Options: works, supplies, services | |
Published in the last N dayspublishedWithinDays | integer | 7 | Only notices published in the last N days. 0 = no date limit (use with other filters). Ignored when "Published from" is set. |
Only open tenders (deadline not passed)onlyOpen | boolean | false | Keep only notices whose deadline for tenders or requests to participate is still in the future. |
| More filters | |||
Minimum estimated value (EUR)minValueEur | integer | Keep only notices with an estimated (or awarded) value of at least this amount, converted to EUR with ECB rates. Notices without a published value are dropped when this is set. | |
Maximum estimated value (EUR)maxValueEur | integer | Keep only notices with an estimated (or awarded) value of at most this amount in EUR. Notices without a published value are dropped when this is set. | |
Exclude keywordsexcludeKeywords | array | Drop notices that contain any of these words or phrases. | |
Search keywords insearchIn | string | fulltext | Full text searches the whole notice (titles, descriptions, lots) in every language. Title only is stricter. Options: fulltext, title |
Published from (date)publishedFrom | string | Start date, for example 2026-01-01. Overrides "Published in the last N days". | |
Published until (date)publishedTo | string | End date (inclusive), for example 2026-06-30. | |
TED expert query (advanced)expertQuery | string | Optional extra condition in TED expert search syntax, combined with AND, for example: buyer-legal-type IN (cga) AND procedure-type = open. See https://ted.europa.eu/en/help/expert-search | |
| Alerts and output | |||
Only new notices since the last run (alerts)onlyNew | boolean | false | Remember which notices were already output for this search and skip them next time. Schedule the actor daily to get tender alerts. The first run outputs all matches in the date window. |
Alert memory store namestateStoreName | string | ted-tenders-state | Named key-value store that remembers output notices for "Only new" mode. Each different search keeps its own memory inside it. |
Preferred language for titleslanguage | string | en | TED translates notice titles into all EU languages. Descriptions stay in the original language. Options: en, de, fr, es, it, nl, pl, pt, ro, bg, cs, da, el, et, fi, ga, hr, hu, lt, lv, mt, sk, sl, sv |
Include descriptionincludeDescription | boolean | true | Add the procurement description (original language, up to 4,000 characters). E-mail addresses and phone numbers are removed. |
Include lotsincludeLots | boolean | true | Add a list of lots with title, estimated value, deadline and duration. |
Max noticesmaxItems | integer | 1000 | Stop after this many notices (newest first). 0 = up to 200,000. |
| Advanced | |||
TED search scopescope | string | ALL | All = everything published in the last 10 years. Active = planning notices of the last 364 days, competition notices with an open deadline and results of the last 99 days. Latest = only the latest daily edition. Options: ALL, ACTIVE, LATEST |
Only latest notice versionsonlyLatestVersions | boolean | true | Skip notices that were later replaced by a change notice. |
Seconds between API requestsrequestIntervalSecs | integer | 1 | The TED API rate-limits bursts. 1 second (up to 250 notices per request) is safe. |
Request timeout (seconds)requestTimeoutSecs | integer | 60 | Timeout for one API request. |
Max retriesmaxRetries | integer | 5 | Retries for network errors, HTTP 429 and 5xx responses, with backoff. |
Call it from code
Start a run and get the results in one HTTP request with the Apify API (your token is under Console, Settings, API & Integrations):
curl -X POST "https://api.apify.com/v2/acts/adamhaleworks~ted-tenders-api/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"cpvCodes":["45"],"countries":["BG"],"noticeTypes":["competition"],"onlyOpen":true}'The run's Output tab offers 2 ready-made views; every view exports to CSV, Excel, JSON or XML:
- Tenders:
publicationDate,title,buyerName,buyerCountry,noticeTypeLabel,contractNature,cpvMain,deadline,daysUntilDeadline,estimatedValueEur,noticeUrl - Contract awards:
publicationDate,title,buyerName,buyerCountry,winnerNames,winnerCount,awardedValueEur,awardedValue,awardedValueCurrency,noticeUrl
What it costs
Free to run right now. The actor charges no fee of its own today. Apify bills only the compute a run uses against your account's platform credit, and the free Apify plan includes $5 of usage every month. For scale: building all five of our actors and test-running each once on its default input used $0.03 of credit in total (2026-10-12).
Planned: pay-per-event pricing of $0.0025 per notice in the output ($2.50 per 1,000) once the account's payout setup is finished. This page and the Apify page will show the change, and Apify notifies existing users before a price change takes effect.
With the planned price, notices dropped by your filters and notices already delivered in "only new" mode would not be charged. Our EU-wide "software" or "cloud computing" alert matched about 160 new calls for tenders a day, about $0.40 a day; one country or a CPV filter brings it to cents.
FAQ
Is the TED API free?
Yes. The TED Search API needs no key for searching and the data is reusable commercially. You pay nothing to TED; the effort is in paging, translating multilingual fields, currency conversion and deduplication.
Why do I get fewer results than on the TED website?
The actor skips notices replaced by a later version by default (Only latest notice versions), and value filters drop notices with no published value.
How do I search one region instead of a whole country?
Use NUTS codes in Place of performance, for example BG411 for Sofia, DE21 for Upper Bavaria or FR10 for Ile-de-France.
Can I search in my own language?
Yes. Full-text search covers every language version of a notice, and Preferred language sets the language of the returned titles.
How is this different from a tender alert subscription?
Subscriptions such as TenderPulse or Tendium (EUR 19 to 125 a month when checked on 2026-10-03) add curation and a web app. The actor gives you raw, structured data on a schedule that you route to email, Slack, a spreadsheet or your CRM yourself.
Try it on your own data
TED tenders API for EU public procurement: search tenders and contract awards from TED (Tenders Electronic Daily) by keyword, CPV code, country, value and deadline. Clean rows with English titles, buyer, deadline, EUR values, lots and winners. Only-new mode for daily tender alerts.
Open TED Tenders API – EU Public Procurement Search Opens the actor's page on apify.com. A free Apify account is needed to run it.