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:

FieldExampleNotes
FTFT ~ (software)Full text in every language version. Broad: the third hit in our test was a lift renewal that mentions software somewhere
notice-titlenotice-title ~ (cloud)Stricter keyword match on the title
classification-cpvclassification-cpv IN (72000000 48000000)8-digit CPV codes; a code covers the codes below it
buyer-countrybuyer-country IN (BGR ROU)Three-letter ISO codes
place-of-performanceplace-of-performance IN (BG411)Country or NUTS region codes
form-typeform-type IN (competition)planning, competition, result and others
publication-datepublication-date>=20261001YYYYMMDD
deadline-receipt-tender-date-lot…>=20261012Use it to keep only tenders still open

What you will have to handle

  • Paging. limit is 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 back iterationNextToken; 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 onlyLatestVersions or 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

  1. Open TED Tenders API on Apify.
  2. 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.
  3. Pick the period: Published in the last N days (default 7) or exact dates.
  4. 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

FieldWhat it holds
publicationNumber, noticeUrl, pdfUrl, xmlUrlTED identifiers and links
noticeType, noticeTypeLabel, formTypePlanning, contract notice, contract award and so on
title, mainCategory, titleOriginal, originalLanguageEnglish (or your chosen language) title and the original
buyerName, buyerCountry, buyerCity, buyerType, buyerWebsiteWho is buying
cpvMain, cpvCodes, placeOfPerformanceNutsWhat and where
deadline, deadlineType, daysUntilDeadline, isOpenTender 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, submissionUrlLots, 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: true keeps 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).

FieldTypeDefaultWhat it does
Keywords
keywords
arrayNotices 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
arrayCommon 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
arrayWhere the contract is carried out. Country codes (BG, DE, FR or BGR, DEU) or NUTS region codes (BG411 = Sofia, DE21 = Upper Bavaria).
Buyer countries
buyerCountries
arrayCountry of the contracting authority. Usually the same as the place of performance, but differs for EU institutions and cross-border projects.
Notice types
noticeTypes
arraycompetition = 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 types
contractTypes
arrayWorks, supplies and/or services. Empty = all.
Options: works, supplies, services
Published in the last N days
publishedWithinDays
integer7Only 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
booleanfalseKeep only notices whose deadline for tenders or requests to participate is still in the future.
More filters
Minimum estimated value (EUR)
minValueEur
integerKeep 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
integerKeep 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 keywords
excludeKeywords
arrayDrop notices that contain any of these words or phrases.
Search keywords in
searchIn
stringfulltextFull text searches the whole notice (titles, descriptions, lots) in every language. Title only is stricter.
Options: fulltext, title
Published from (date)
publishedFrom
stringStart date, for example 2026-01-01. Overrides "Published in the last N days".
Published until (date)
publishedTo
stringEnd date (inclusive), for example 2026-06-30.
TED expert query (advanced)
expertQuery
stringOptional 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
booleanfalseRemember 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 name
stateStoreName
stringted-tenders-stateNamed key-value store that remembers output notices for "Only new" mode. Each different search keeps its own memory inside it.
Preferred language for titles
language
stringenTED 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 description
includeDescription
booleantrueAdd the procurement description (original language, up to 4,000 characters). E-mail addresses and phone numbers are removed.
Include lots
includeLots
booleantrueAdd a list of lots with title, estimated value, deadline and duration.
Max notices
maxItems
integer1000Stop after this many notices (newest first). 0 = up to 200,000.
Advanced
TED search scope
scope
stringALLAll = 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 versions
onlyLatestVersions
booleantrueSkip notices that were later replaced by a change notice.
Seconds between API requests
requestIntervalSecs
integer1The TED API rate-limits bursts. 1 second (up to 250 notices per request) is safe.
Request timeout (seconds)
requestTimeoutSecs
integer60Timeout for one API request.
Max retries
maxRetries
integer5Retries 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.