TED (Tenders Electronic Daily) Notice Feed, unofficial
Pricing
from $3.00 / 1,000 notices
TED (Tenders Electronic Daily) Notice Feed, unofficial
Unofficial feed of public procurement notices from the TED Search API. Filter by notice type, buyer country, CPV code and contract nature. Each run resumes from the last saved publication day.
Pricing
from $3.00 / 1,000 notices
Rating
0.0
(0)
Developer
Ample Labs
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
TED Notice Feed, unofficial (Ample Labs)
Unofficial. This Actor is an independent product of Ample Labs. It is not affiliated with, endorsed by, sponsored by, or operated by the Publications Office of the European Union, the European Commission, or TED. Data is provided as is, without warranty, and may be incomplete or out of date. Only notices published in the Supplement to the Official Journal of the European Union are authentic.
Source: © European Union, TED (Tenders Electronic Daily), https://ted.europa.eu. Reused under Commission Decision 2011/833/EU (https://eur-lex.europa.eu/eli/dec/2011/833/oj/eng). Modified by Ample Labs: fields selected and normalized.
Do not use this output for unsolicited direct marketing to individuals (natural persons, including sole traders).
Incremental feed of procurement notices from the TED Search API. Each run fetches the notices itself and writes them to your Apify dataset. Customers pay for scheduling, normalization and delivery, not for the data, which is free from TED.
The title on each notice keeps TED's own "Country – CPV description –" prefix. That prefix is TED's own text, not ours. Only HTML entities are decoded.
Pay per event: $0.01 per run start (one start event up to 1 GB of memory), $0.003 per notice delivered, $0.005 per Extra publication day (a non-empty publication day beyond the first), and $0.001 per Page scanned (a result page that contains at least one notice).
Who it is for
Teams that want new TED procurement notices in an Apify dataset on a schedule, filtered by notice type, buyer country, CPV code and contract nature. The output is notice data. It is not legal, bidding or investment advice. Read the authentic notice on TED before you act on it. Each item links to it in notice_url.
1. What it does
The Actor sends POST https://api.ted.europa.eu/v3/notices/search and nothing else. There is no key, no login, and no browser. Requests go one at a time, at most one per second, with User-Agent AmpleLabs-TEDFeed/<version> (support@haveample.com).
A run reads publication days in Europe/Brussels, from the day after the saved day through today, and stops after maxBackfillDays. Each day is read in scroll mode (paginationMode ITERATION, 250 notices per page). A page that returns no notices ends that day. An empty day that is already in the past is saved and is not charged. Today is not saved when it has no notices, so a later run can pick it up.
State is kept in the named key-value store ted-notice-feed-state-<feed name>, under STATE-<feed name>-<filter hash>. The default store holds HTTP_STATUS_SUMMARY (status-code counts for this run), RUN_METADATA (the attribution, where the notice URL came from, and the User-Agent), RESET_APPLIED after this run has applied resetState, RUN_PROGRESS (notices pushed so far in this run), and STATUS_ROW after this run has pushed the free status row. State is never written to the default store.
2. Inputs
| Input | Default | What it does |
|---|---|---|
| stateKey | default | Feed name. Same name and filters share one saved position. Pattern ^[a-z0-9-]{3,40}$. |
| noticeTypes | competition, award | competition = cn-; award = can-standard, can-social, can-desg, veat; modification = can-modif; planning = pin-; other = the remaining known codes. |
| buyerCountries | empty | ISO 3166 alpha-3. Empty means all. Checked against ^[A-Z]{3}$ before the query is built. |
| cpvCodes | empty | 2–8 digits. Matched as a prefix (72 becomes classification-cpv = 72*). |
| contractNature | empty | works, supplies, or services. Empty means all. |
| minEstimatedValue | unset | Applied after download. The highest lot value is compared. Currencies are not converted. |
| includeUnknownValue | true | Keep notices with no estimated value when a minimum is set. |
| includeWinnerNames | false | Winner and tenderer organisation names. Off unless you opt in. Do not use this output for unsolicited direct marketing to individuals (natural persons, including sole traders). |
| dateFrom | unset | First publication day when there is no saved position, or when resetState is true. Otherwise ignored. |
| maxBackfillDays | 1 | At most this many publication days in one run. 1–30. |
| maxResults | 1000 | Stop after this many notices. 1–50000. |
| resetState | false | Forget the saved position for this feed name and these filters. Applied once per run, including after a restart of that same run. |
There is no free-text query input. Values that fail the pattern are rejected before a request is sent.
Runs with no new notices
If a run delivers no notices, the dataset holds one status row with eventType "no-new-notices" instead of notice records. That includes nothing new since the saved position, a page whose notices were already seen, and a stop before any notice: the spending limit, the run timeout, TED blocking access, a query TED rejects, the feed switch being off, or an abort that leaves the run time to finish. stopReason says which. A run that ends in an unhandled error writes no row, and neither does a run that is stopped before it can finish. A process that is migrating writes no row, because that run continues.
The row is free. It is not a notice and it is not charged. It does not move the saved position and it does not count toward maxResults. To keep only notices, drop rows where eventType is "no-new-notices".
Example status row (illustrative values, not from a live run):
{"eventType": "no-new-notices","feedName": "store-test","filters": {"noticeTypes": ["competition"],"buyerCountries": ["DEU", "FRA"],"cpvCodes": ["72"],"contractNature": [],"minEstimatedValue": null,"includeUnknownValue": true},"stopReason": "completed","runAt": "2026-10-31T23:00:00.000Z"}
3. Data dictionary
The field table is also in DATA_DICTIONARY.md.
| Field | Meaning |
|---|---|
| publication_number | TED publication number. Charged once per feed. |
| notice_version | notice-version from TED. |
| notice_type, form_type | Notice and form codes. |
| publication_date | Publication day, YYYY-MM-DD. Derived only as a calendar date from the API value. |
| title | notice-title for the first official-language value that has an entry. HTML entities are decoded. TED's own "Country – CPV description –" prefix is kept. It is TED's own text, not ours. |
| title_lang | Derived. The lower-cased official-language code used for title. Null when title is null. |
| original_language | official-language codes as TED returned them. Null only when that list is missing or empty. A list with no matching notice-title still keeps the codes, and title is null. |
| buyer_name, buyer_city | Selected text: English when TED sent it, otherwise the first language. Not translated. |
| buyer_country | Buyer country codes. |
| cpv_codes | CPV codes, duplicates removed. |
| contract_nature | works, supplies, services. Duplicates removed. |
| procedure_type, procedure_identifier | Procedure. The identifier links an award to an earlier call. |
| place_of_performance | NUTS or country codes. Duplicates removed. |
| deadline_tender | Tender deadlines as TED returned them. |
| estimated_value, currency | Lot values parsed as numbers, with one currency code per lot. Not converted. |
| framework_agreement, lot_ids | Framework flags and lot ids. |
| change_of | change-notice-version-identifier. |
| modifies | modification-previous-notice-identifier. The API accepts the field. A value has not been seen in recorded responses. Empty when absent. |
| result_value, result_currency | Award value and its currency. |
| winner_country, winner_size, winner_decision_date | Not names. |
| winner_name, tenderer_name | Present only when includeWinnerNames is true. A name can be a sole trader. |
| notice_url | links.htmlDirect.ENG from the response. Not links.html. |
| xml_url | links.xml.MUL from the response. |
| first_seen_at | When this run emitted the item. |
| source_attribution | The attribution sentence above, on every item. |
| redelivered | True on a free replay after a crash. |
4. Example input and output
This is the Console prefill. It reads competition notices for German and French buyers in CPV division 72, up to 10 notices, starting on 2026-10-30 when the feed name has no saved position and continuing from the saved position after that. Winner names stay off, the default.
{"stateKey": "store-test","noticeTypes": ["competition"],"buyerCountries": ["DEU", "FRA"],"cpvCodes": ["72"],"dateFrom": "2026-10-30","maxResults": 10}
Example output (one item of a private run with the input above, includeWinnerNames false):
{"publication_number": "752720-2026","notice_version": 1,"notice_type": "cn-standard","form_type": "competition","publication_date": "2026-10-30","title": "Deutschland – Softwareprogrammierung und -beratung – Spezifisches IT-Projektmanagement für das Informationstechnikzentrum Bund - Los 1","title_lang": "deu","original_language": ["DEU"],"buyer_name": "Bundesrepublik Deutschland, vertreten durch das Bundesministerium des Innern, vertreten durch das Beschaffungsamt des BMI","buyer_country": "DEU","buyer_city": "Bonn","cpv_codes": ["72200000","72224000"],"contract_nature": ["services"],"procedure_type": "open","procedure_identifier": "402e620f-78f3-4fdd-bd3f-3ecb2839cd78","place_of_performance": ["DEU"],"deadline_tender": ["2026-12-03+01:00"],"estimated_value": [],"currency": [],"framework_agreement": ["fa-wo-rc"],"lot_ids": ["LOT-0000"],"change_of": null,"modifies": [],"result_value": null,"result_currency": null,"winner_country": [],"winner_size": [],"winner_decision_date": [],"notice_url": "https://ted.europa.eu/en/notice/752720-2026/html","xml_url": "https://ted.europa.eu/en/notice/752720-2026/xml","first_seen_at": "2026-11-01T03:07:07.283Z","source_attribution": "Source: © European Union, TED (Tenders Electronic Daily), https://ted.europa.eu. Reused under Commission Decision 2011/833/EU (https://eur-lex.europa.eu/eli/dec/2011/833/oj/eng). Modified by Ample Labs: fields selected and normalized.","redelivered": false}
Field names and meanings are in section 3.
5. Pricing
Customers pay for scheduling, normalization and delivery, not for the data, which is free from TED.
Pay per event: $0.01 per run start (one start event up to 1 GB of memory), $0.003 per notice delivered, $0.005 per Extra publication day (a non-empty publication day beyond the first), and $0.001 per Page scanned (a result page that contains at least one notice).
Filtered and excluded notices are not charged. A crash replay is not charged again. The status row is free.
Removal requests
Takedown requests about winner names go to support@haveample.com and are handled by excluding the publication number. Maintainers edit exclusions.json and ship a new build. See EXCLUSIONS.md. A removed notice is not pushed and is not charged. Rows already in a customer's dataset stay in that customer's account.
6. Known limits
- The scroll is a point in time. A notice published after the first page of a day waits for a later run only if that day was not saved. Today is not saved when it returns no notices.
- Whether a whole day's notices appear at once was not measured.
- Short CPV codes are prefixes:
72is sent asclassification-cpv = 72*.IN (72)is rejected by TED. See docs/api-checks.md. - Sampled publication numbers were unique in the index. That is not a proof for every notice.
- Some notices list more than one official language. The title is the first of those values that has a notice-title entry. If none has one, title is null and original_language stays the official-language list. No other language is used.
modification-previous-notice-identifieris accepted by the API and has not been seen with a value.- Compute time and data transfer on Apify were not measured.
- If TED returns HTTP 202, or HTML 403, or a second 403, the run stops. There is no proxy and no IP rotation.
- Field names can change without an API version bump. A 400 on the query fails the run and keeps the saved day.
7. FAQ
Is this an official TED or EU service? No. It is an independent Ample Labs Actor. See the first paragraph of this page.
Do I need a TED account or API key? No. The Actor uses the anonymous TED Search API.
Does it return contact details? No. Emails, phone numbers, street addresses and contact persons are never requested or written. Only the buyer's name, city and country are included.
Are winner names included? Only when you set includeWinnerNames to true. It is false by default.
Are titles translated? No. title is the notice-title entry in the notice's original language, as TED published it.
How do I ask for a notice to be removed? Email support@haveample.com. See Removal requests.
Re-check triggers
Re-check this Actor before publishing a change when any of these happen:
- The TED legal notice changes.
- The API docs change on anonymous access, a published rate limit, or API terms.
- TED requires a key.
- Apify IPs see a WAF challenge (HTTP 202) or repeated HTTP 403.
- Winner names would be turned on by default.
- EU customer counts change the CMP-011 personal-data view. Add TED snapshots to the weekly terms scan.
The HTTP log and HTTP_STATUS_SUMMARY are the throttle record for private runs. Private test runs before publishing included the Console prefill (2026-10-30, CPV 72, DEU and FRA, 10 notices), one unfiltered weekday (2026-10-30, all notice types), a repeat of that feed, which read only the empty Saturday that followed, and two 300-second timeout checks.