German and EU public tenders in one deduplicated list: public procurement notices for Germany from oeffentlichevergabe.de (öffentliche Ausschreibungen, Vergabe) and TED, other EU countries via TED. Tenders scored to your CPV codes, keywords and regions, with deadlines. Daily tender alerts.
README: cross-links and examples, no code or price change (2026-10-08, build 0.1.8)
Product name in the README now matches the Store title ("German & EU Tenders: Public Procurement Monitor").
New Examples section linking the published example task "IT security tenders in Germany - last 7 days".
"Other Lindenwerk Data Actors" lists all six sibling Actors by their current Store titles and Store URLs.
No change to code, input schema, pricing, events, defaults or output.
Data-quality update: awardedValue fix and deadline-window filter (2026-10-07)
Fixed: awardedValue / awardedCurrency were filled on open tenders. TED's search API puts the estimated value in
total-value on competition notices, and that showed up as an "awarded" value. Both fields are now null on every
notice that is not an award (result) or contract-modification notice; estimatedValue is unchanged.
New optional inputs minDaysUntilDeadline and maxDaysUntilDeadline (days from the run date to the deadline in
daysUntilDeadline), e.g. "maxDaysUntilDeadline": 21 for tenders due within three weeks. Not set = no filter, so
existing inputs behave exactly as before. When either is set, notices without a published deadline are excluded.
The filter runs before scoring and before anything is pushed, so filtered notices are never charged. Counts appear in
RUN_SUMMARY.excludedByFilter (deadlineTooSoon, deadlineTooFar, noDeadline) and RUN_SUMMARY.deadlineFilter.
Input help: CPV examples 4873 / 72212730 for security software, 7971 marked as guarding services (not IT);
keywords / minScore explain that keywords raise the score, so a high minScore with few keywords can return nothing.
README: warning that an API or AI-agent call without mode runs monitor mode (only new notices since the last run),
with a one-off backfill example; the two new filters are documented.
No change to pricing, events, defaults or output columns.
Reliability update: long backfills keep both sources (2026-10-06, before the first public release)
Fixed: on Apify at 512 MB a 30-day backfill could drop the whole German source. Parsing the German eForms export
is CPU-bound, 512 MB runs get 1/8 of a CPU core, and the source had a fixed 210 s budget; when it ran out, every
finished day was thrown away and the run returned TED-only rows while still showing Succeeded.
A source that runs out of time or breaks now keeps what it delivered (finished export days, TED pages fetched so
far). The run says so: status message starting with PARTIAL DATA, a PARTIAL SOURCE log line with the missing
days, and new RUN_SUMMARY fields sourceStatus, partialSources, missingDays, sourceTimeBudgetSeconds.
Only delivered rows are charged.
Time budget per source: 210 s for short monitor windows (unchanged), 60 s + 25 s per day for backfills (31 days:
835 s), always leaving at least 300 s before the run timeout for dedup, scoring and pushing.
About 3.6x less CPU for the same output (30-day window locally: 46.8 s -> 12.9 s): compiled XPath look-ups, notice
types that were not requested are skipped before the XML is parsed, one parse thread instead of three competing for
the GIL, faster accent folding and a cheap upper-bound check before fuzzy title matching. Output of a 30-day test
window is identical row for row. Dedup normalises each title once and reuses one matcher per TED notice (same
rows and scores). On Apify (512 MB) the 30-day IT backfill now takes ~2.5 min with both sources complete (German
source 30/30 days fetched and parsed in ~108 s of an 810 s budget; was: German source dropped after 210 s).
No change to prices, events, input fields, defaults or output fields.
Listing quality update (2026-10-06, before the first public release)
README: starts with an H2 "What is ...?" (Apify Store shows the Actor name as the page H1), new step-by-step
"How to ..." section (first run, own profile, schedule, integrations, API) and a list of the other Lindenwerk Data Actors.
Input form: readable titles for the "Sort by" options, a "Quickest try" hint in the form description and a short description for the Advanced section.
No change to the code, prices, events, output fields or defaults.
0.1 (2026-10-04, updated 2026-10-05 before the first publication)
The input form prefill is now a stateless 7-day backfill with maxResults 25 (IT profile unchanged). Apify's daily
Store test runs the prefill, so it gets rows on any day. A monitor-mode prefill could return 0 rows on a quiet day,
and 3 failed days in a row mark an Actor "under maintenance". API, task and schedule defaults are unchanged
(monitor, lookbackDays 1, maxResults 500).
New firstRunBackfillDays (default 7, 0 = off): a monitor run with no saved state whose window is empty looks back
7 days once.
More robust against outages: an unexpected error or a hang (210 s budget) in one source no longer crashes the run.
The other source's results are delivered and a warning goes into the status message and RUN_SUMMARY.warnings. If
every source is unreachable, the run fails cleanly with no charge and no state change. Empty runs end with a clear
status message. RUN_SUMMARY gains firstRun, firstRunFallbackUsed, failedSources and warnings.
sources: ["oeffentlichevergabe"] without DE in countries is now rejected as an invalid input instead of running
with no source.
Initial release (2026-10-04):
First public release.
Sources: oeffentlichevergabe.de open-data eForms export (CC0) and TED search API v3.
Cross-source deduplication (eForms notice id, TED reference, fuzzy fallback), plus collapse of identical
re-publications under a new notice id (older ids in relatedNoticeIds).
Rule-based profile scoring (CPV prefixes, DE/EN keywords with IDF, regions, contract types, value range,
exclusions, open-only) with relevanceScore and matchReasons.
Modes: monitor (only new notices, persistent state), backfill (up to 31 days), awards (competitor tracking).
Pay-per-event events notice and scored-match; respects the run's maximum total charge.
GDPR: personal contact names, personal e-mails and phone numbers are never output, including inside titles and
descriptions (replaced with placeholders).
Truncated CPV codes from some publishers are padded to 8 digits.