French Company Finder - Sirene Financials
French company lead lists from Sirene screened by net result and revenue, with net margin, size, matching establishment and optional directors.
datagrit › Public procurement › TED Contract Expiry Radar - Recompete Leads
Public procurementFind EU public contracts approaching expiry from TED award notices: incumbent, buyer, value, end date and renewal options.
TED Contract Expiry Radar turns contract award notices from the official EU tender portal TED into a list of public contracts that are about to end across Europe. For every lot it returns the incumbent supplier, the buying authority and its country, the award value, the contract end date, the days left, contract length, renewal options and CPV codes. You choose the expiry window, for example the next 12 months, and optionally filter by keyword, buyer country, CPV code, supplier name and minimum value. Export the result as JSON, CSV or Excel, call it through the Apify API, or plug it into n8n, Make and AI agents through MCP.
72 for IT services, 90 for waste and cleaning, 45 for construction), incumbent names and a minimum value.Results are read in monthly expiry slices, so with a maximum results limit you get the soonest-expiring contracts first.
Most award notices state how long the contract runs but not the exact end date. When Estimate missing end dates is on, the Actor computes the end date from the start date, or from the contract conclusion date, plus the published duration. The field endDateSource tells you where every date comes from: stated means the buyer published it, start+duration and award+duration mean it was calculated. Turn the option off to keep only stated end dates. Estimated dates ignore extensions and early termination, so treat them as a strong lead rather than a legal fact.
Why it matters: many award notices publish how long a contract runs but not the date it ends. The Actor computes that date from the lot start date or the contract conclusion date plus the duration, and marks every row with endDateSource. In two complete live runs on 30 September 2026, contracts ending within the next month gave 7,053 lots with a stated end date and 9,052 more with a computed one (16,105 rows), and contracts ending in two to three months gave 7,465 stated and 12,064 computed (19,529 rows). See the FAQ for what is not covered.
Each record is one awarded lot. It includes the TED notice number and link, notice and contract titles, buyer name, country and city, incumbent supplier with country, size class and registry identifier, all winners of the notice when they cannot be matched to a single lot, award value and currency, award, publication and contract start dates, contract end date with its source, days and months to expiry, contract length, renewal options and terms, framework agreement flag and type, main and additional CPV codes, contract nature and the number of lots in the notice.
The Actor reads only information that the European Union publishes openly through the TED search API. It does not log in or bypass any access control. The data covers organisations and public contracts. You are responsible for using it in line with applicable law, including data protection rules. This description is not legal advice.
Every result is one flat record, so it drops straight into a spreadsheet, a database or a CRM.
| Field | Type | Description | Example |
|---|---|---|---|
query | string | The keyword from your input found in this lot (lot title, lot description, contract title or notice title); null only when you gave no keywords. | software |
id | string | Stable identifier: TED notice number plus the lot. One award notice can hold several lots, each returned as its own row. Empty only on the single status row emitted when nothing matched. | 406127-2023/LOT-0001 |
noticeNumber | string | Publication number of the contract award notice on TED. | 406127-2023 |
lotId | string | Lot identifier inside the notice. | LOT-0001 |
title | string | Title of the award notice as published on TED. | Estonia – Software package and information systems – Public transport ticketing |
contractTitle | string | Title of the contract given by the buyer, when it differs from the notice title. Filled only when the notice has one contract title; empty when several contracts have different titles. | Ticketing system maintenance |
lotTitle | string | Title of this lot in the language of the notice. Matched to the lot by its identifier; empty when TED does not list one title per lot. | Los 2 Dienstleistung |
lotDescription | string | Description of this lot in the language of the notice, cut to 1000 characters. Matched to the lot by its identifier; empty when TED does not list one description per lot. | Support services for the licence administration. |
sourceUrl | string | Link to the award notice on TED. | https://ted.europa.eu/en/notice/-/detail/406127-2023 |
buyerName | string | Contracting authority that awarded the contract, i.e. who will buy again. | Tallinna Transpordiamet |
buyerCountry | string | Three-letter ISO country code of the buyer. | EST |
buyerCity | string | City of the buyer. | Tallinn |
incumbentName | string | Supplier that won this lot. Null when the notice does not allow a safe match of winner to lot; see allIncumbents. | AS Connecto Eesti |
incumbentCountry | string | Three-letter ISO country code of the incumbent supplier. | EST |
incumbentSize | string | Company size class of the incumbent as declared in the notice (micro, small, medium, large). | sme |
incumbentId | string | Company registration identifier of the incumbent as published in the notice. | 10201316 |
allIncumbents | string | Names of all winning suppliers in the notice, separated by semicolons. Filled when winners cannot be matched to a single lot. | CIR FOOD S.C.; VIVENDA SPA |
awardValue | number | Awarded value of the lot in the currency given in the currency field. | 500000 |
currency | string | Currency code of awardValue. | EUR |
awardDate | string | Date the contract was concluded (YYYY-MM-DD). Filled only when the notice has one contract or all its contracts were concluded the same day; TED does not say which contract belongs to which lot, so otherwise empty. | 2023-10-16 |
publishedAt | string | Date the award notice was published (YYYY-MM-DD). | 2023-11-13 |
contractStart | string | Contract start date when stated in the notice (YYYY-MM-DD). | 2023-09-06 |
contractEnd | string | Contract end date (YYYY-MM-DD), stated by the buyer or computed; see endDateSource. | 2026-09-05 |
endDateSource | string | How contractEnd was obtained: stated (published by the buyer), start+duration or award+duration (estimated from the published duration). | start+duration |
daysToExpiry | integer | Days from the run date to contractEnd. | 158 |
monthsToExpiry | number | Months from the run date to contractEnd, one decimal. | 5.2 |
contractLengthMonths | number | Published contract duration in months. | 36 |
renewalOptionsMax | integer | Maximum number of renewals the buyer reserved, when stated. | 1 |
renewalTerms | string | Description of the renewal option, cut at 400 characters. | The contract may be extended once for up to 12 months. |
frameworkAgreement | boolean | True when the lot is a framework agreement rather than a stand-alone contract. | false |
frameworkType | string | Framework agreement type as published, for example with or without reopening of competition. | fa-w-rc |
cpvCode | string | Main CPV code of the lot (from TED main-classification-lot); the first code of the notice when TED gives no lot code. | 72000000 |
cpvScope | string | lot when cpvCode is the lot's own code, notice when it falls back to the notice-level classification. | lot |
cpvCodes | string | All CPV codes of the notice, separated by commas. | 72000000, 48000000 |
contractNature | string | Supplies, services or works. | services |
lotCount | integer | Number of lots in the award notice (TED lot list, identifier-lot); when TED gives no lot list, the number of awarded results. | 3 |
found | boolean | False only for the single status row emitted when a run has no results. | true |
scrapedAt | string | ISO 8601 timestamp of extraction. | 2026-09-30T08:00:00.000Z |
{
"query": "software",
"id": "406127-2023/LOT-0001",
"noticeNumber": "406127-2023",
"lotId": "LOT-0001",
"title": "Estonia – Software package and information systems – Public transport ticketing software",
"contractTitle": "Ticketing system maintenance",
"lotTitle": "Los 2 Dienstleistung",
"lotDescription": "Support services for the licence administration.",
"sourceUrl": "https://ted.europa.eu/en/notice/-/detail/406127-2023",
"buyerName": "Tallinna Transpordiamet",
"buyerCountry": "EST",
"buyerCity": "Tallinn",
"incumbentName": "AS Connecto Eesti",
"incumbentCountry": "EST",
"incumbentSize": "sme",
"incumbentId": "10201316",
"allIncumbents": "CIR FOOD S.C.; VIVENDA SPA",
"awardValue": 500000,
"currency": "EUR",
"awardDate": "2023-10-16",
"publishedAt": "2023-11-13",
"contractStart": "2023-09-06",
"contractEnd": "2026-09-05",
"endDateSource": "start+duration",
"daysToExpiry": 158,
"monthsToExpiry": 5.2,
"contractLengthMonths": 36,
"renewalOptionsMax": 1,
"renewalTerms": "The contract may be extended once for up to 12 months.",
"frameworkAgreement": false,
"frameworkType": "fa-w-rc",
"cpvCode": "72000000",
"cpvScope": "lot",
"cpvCodes": "72000000, 48000000",
"contractNature": "services",
"lotCount": 3,
"found": true,
"scrapedAt": "2026-09-30T08:00:00.000Z"
}
| Field | Name | Type | What it does |
|---|---|---|---|
queries | Keywords | array | Optional keywords. TED full-text search finds candidate notices, and a lot is returned only when a keyword appears in its own title or description, or in the contract or notice title (case-insensitive, in the language of the notice). Leave empty to list all expiring contracts. |
countries | Buyer countries | array | Optional. Two-letter country codes of the contracting authority, for example DE, FR, PL, NL, ES, IT. Leave empty for all countries covered by TED. |
cpvPrefixes | CPV code prefixes | array | Optional. Keep only contracts whose CPV classification starts with one of these digits, for example 72 (IT services), 90 (waste and cleaning) or 45 (construction). |
incumbents | Incumbent supplier names | array | Optional. Keep only contracts won by suppliers whose name contains one of these words, for example to see when a competitor's contracts end. |
expiresAfterMonths | Expires no earlier than (months from today) | integer | Start of the expiry window. 0 means contracts ending today or later. |
expiresBeforeMonths | Expires no later than (months from today) | integer | End of the expiry window. 12 returns contracts ending within the next twelve months. Results are read in monthly slices, soonest expiry first. |
minValue | Minimum contract value | number | Optional. Minimum awarded value in the contract's own currency (mostly EUR). Contracts without a published value are excluded when this is above 0. |
includeFrameworkAgreements | Include framework agreements | boolean | Turn off to drop framework agreements and keep only stand-alone contracts. |
estimateMissingEndDates | Estimate missing end dates | boolean | Most notices state a contract duration but no end date. When on, the end date is computed from start date (or award date) plus duration and marked in endDateSource. Turn off to return only end dates stated by the buyer. |
maxItems | Maximum results | integer | Stop after this many contracts. |
proxyConfiguration | Proxy configuration | object | Optional proxy. The TED API is public and needs no proxy; leave disabled. |
Run the Actor and get the results in one request. Replace YOUR_APIFY_TOKEN with the token from your Apify account settings.
curl -X POST "https://api.apify.com/v2/acts/datagrit~ted-contract-expiry-radar/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"queries":["software"],"expiresAfterMonths":0,"expiresBeforeMonths":12,"maxItems":20}'import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('datagrit/ted-contract-expiry-radar').call({
"queries": [
"software"
],
"expiresAfterMonths": 0,
"expiresBeforeMonths": 12,
"maxItems": 20
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.length, items[0]);Install with npm i apify-client.
from apify_client import ApifyClient
import os
client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("datagrit/ted-contract-expiry-radar").call(run_input={
"queries": [
"software"
],
"expiresAfterMonths": 0,
"expiresBeforeMonths": 12,
"maxItems": 20
})
items = client.dataset(run["defaultDatasetId"]).list_items().items
print(len(items), items[0] if items else None)Install with pip install apify-client.
No. It covers awarded contracts and shows when each one ends. Use the expiry window to find recompete opportunities early.
Four reasons. First, a notice with neither an end date nor a duration cannot be placed in an expiry window, and lots without a selected winner are skipped. Second, contracts with a stated end date are always found, but for estimated end dates the Actor asks TED only about common durations: 3, 6, 9, 12, 15, 18, 24, 30, 36, 42, 48, 60, 72, 84, 96 and 120 months, and 1 to 8 and 10 years. Contracts published with another length (for example 4, 11 or 20 months) or with a duration in days or weeks are found only when they also state an end date. In a sample of 2023 notices this leaves out roughly 7 percent of those that publish a duration. Third, TED lists conclusion dates per signed contract, not per lot, and does not say which contract belongs to which lot. When a notice has several contracts with different conclusion dates, the Actor does not guess: awardDate and contractTitle stay empty, and the end date is computed only from the lot's own start date. This is the most common reason a notice found by the duration search gives no row; the run status says how many of those notices produced one. Fourth, TED publishes the per-lot fields (end dates, durations, titles, CPV codes, renewal terms) as lists that follow the notice's lot list, and it sometimes leaves entries out: one notice with 46 lots had 45 end dates. The Actor matches each awarded lot to its entry by the lot identifier and uses a list only when it has exactly one entry per lot; otherwise those fields stay empty and a lot that cannot be placed in the window is not returned, because guessing would attach another lot's date. TED lets a single query read at most 15,000 notices, and 11 of the 24 queries of the default 12-month window match more. The Actor splits such a query into shorter date windows on its own, so nothing is dropped. Only a single day with more than 15,000 notices would be cut, and then the run status says INCOMPLETE and names the day.
TED rate-limits its public search API, so the Actor sends about one request per second. Results are read in monthly expiry slices, two queries per month (stated dates, then estimated ones). A window of 12 months means up to 24 queries. Each query can span many pages of 100 notices, one request per page. In a measurement on 30 September 2026 the default 12-month window without filters matched about 251,000 notices (64,000 for stated dates, 187,000 for estimated ones), which is roughly 2,600 requests and about 45 minutes; a window of two to three months took about 8 minutes. Narrow the window, add a country or CPV prefix, or set a maximum number of results to finish faster. Most runs finish much sooner, because the Actor stops as soon as it reaches your maximum results on the first pages. TED matches notices, not single lots: a notice is returned when any of its lots fits the window, and the Actor then keeps only the lots that really fit, so many lots read are discarded. The run status reports how many lots had a stated, estimated or missing end date. The Actor stops as soon as it reaches your maximum results, and a run that is migrated to another server continues without charging twice for the results it already returned.
TED returned awarded lots but none of them carried an end date or duration, which points to a change in the source data rather than to an empty search. The run fails on purpose so that you are not told there are no expiring contracts. Try again later or open an issue.
All buyers that publish award notices on TED, that is the EU member states and several other European countries.
When a notice has several lots and the winners cannot be matched to lots reliably, the Actor leaves the incumbent empty and lists all winners in `allIncumbents` instead of guessing.
Every run reads the live TED API. Notices appear on TED shortly after publication.
Yes, use Apify schedules or call the Actor from your own workflow.
Open an issue with the input you used; layout or API changes at the source are fixed quickly.
French company lead lists from Sirene screened by net result and revenue, with net margin, size, matching establishment and optional directors.
Ashby job postings with normalized annual salary ranges, equity flags and new-since-last-run detection.
Open jobs from Greenhouse, Lever, Ashby, Workday, Workable, SmartRecruiters, Recruitee and Personio in one schema with normalized salaries.
Greenhouse job postings with published pay ranges by zone, annualised pay, filters and new-since-last-run detection.