Public procurement monitoring: the notice matters more than the AI
How Tendris does public procurement monitoring for Lithuania: reading CVP IS notice PDFs, merging TED duplicates, scoring matches and analysing tender files with AI.
AFKzona Group · 7 min read
The short answer
- Tendris reads every national tender's CPV code from its notice PDF, so a company filtering by sector code is matched on the buyer's own classification.
- Matching is a deterministic score with stored reasons and a pass mark of 25; a database constraint allows one match, and so one alert, per company per tender.
- The AI quotes the document for every risk it names and marks missing information as not enough data instead of guessing, and every tender links straight to its official notice in CVP IS or TED.
The search listing Tendris reads from Lithuania's procurement portal gives no CPV code, the number most suppliers filter tenders by. That code sits inside a PDF notice attached to each tender, one download per tender, in Lithuanian.
Tendris is our tender monitoring product. It covers CVP IS, the national system where every procurement has run since 1 December 2024, and TED, the EU's journal for larger contracts, and it alerts teams by Telegram or email.
Tendris runs on 51 pages, 122 API routes and 61 database tables. This piece follows a tender through it, from the portal listing to the alert.
Tendris reads the CPV code from every notice PDF
The CPV code decides who hears about a tender. Most suppliers filter by it, and on the Lithuanian portal it sits inside the notice PDF. A monitoring tool that reads the listing alone has no code to match on, and a team relying on it sees a quiet week in its sector while tenders are being published.
Tendris gates on the CPV code: if a company's profile lists CPV codes, a tender is scored on code overlap first, whatever its title says. So Tendris downloads and reads the notice PDF of every national tender before it scores anything. Alert quality is decided by the PDF reader long before any model is involved.
Duplication is the other trap: tenders above EU thresholds appear on both CVP IS and TED, and a tool that reads both naively sends every large tender twice.
Most of the work is turning files into fields
Most of the work in Tendris is ingestion: pulling each tender from two sources, reading its notice PDF and merging duplicates into one record. After that a tender is scored against each company's profile, and the language model reads its documents for the bid pipeline.
Every two hours Tendris walks the CVP IS listing, 100 tenders a page, and stops at the first page that adds nothing new. For each tender it downloads the notice PDF, extracts the text and finds fields by their Lithuanian labels: Pasiūlymų priėmimo terminas for the deadline, Sutarties objektas for works, services or supplies. In parallel it asks the TED API for notices from Lithuanian buyers over the last 30 days.
Duplicates are handled by identity rather than by comparing titles. Each tender's ID carries its source, and each run reads TED before CVP IS. When a national tender's page links to a TED notice, Tendris merges the national record into that TED record, keeping the local links to submission and documents, so the tender lives as one record.
Tender documents are harder than notices. CVP IS offers each tender's files as one ZIP, and the procurement documents often sit inside a nested 7z archive. Tendris opens both and reads every PDF in the bundle and every PDF, DOCX, XLSX and legacy DOC file inside the 7z.
Tendris takes the CPV code from the tender's own notice, so a sector filter works on the buyer's classification, not on a guess from the title.
Every match carries its reasons, and none can repeat
Matching in Tendris is arithmetic, not a model's opinion, so every match can explain itself. Each tender gets a score from CPV overlap, contract type, value range, keywords and buyer type. A match needs 25 points. Up to five reasons are stored with the match and printed in the real-time alert.
A CPV overlap is the heaviest single signal, worth 30 points. A tender more than five times a company's maximum value loses 20. A database rule allows one match row per company per tender, so a re-read tender cannot alert the same team twice. Teams that choose real-time alerts get a Telegram message; teams on a daily setting get one digest at 9:00 Vilnius time with their five highest-scoring new matches and a link to the rest.
The AI analysis runs from the bid pipeline, using GPT-4o-mini at temperature 0.1 against a strict schema of 16 required fields. These include mandatory requirements, qualification criteria, weighted evaluation criteria and a timeline. The prompt forbids invented facts, demands a quoted source for every risk and opportunity, and writes "Nepakanka duomenų" (not enough data), with a lower confidence figure, wherever the documents are silent. Each analysis is stored with its model, token count and the number of document words it read.
Every tender links to its official notice
Tendris finds tenders and tells a team what to read first. Every tender links straight to its official notice and files in CVP IS or TED, so the buyer's own wording is one click away.
Each part of the record comes from the reader suited to it. The fields that decide whether a supplier can bid, meaning the CPV code, the value and the deadline, come from the notice by fixed rules. The model reads the prose around them: requirements, criteria and risks, and every risk and opportunity it names is tied to a quote from the document.
Once a team decides to bid, the next document is the technical proposal, which we cover in how to write an IT tender's technical proposal.
Evaluating a tender monitoring tool: five questions to ask
| Question | What good looks like |
|---|---|
| Where does each field come from? | CPV code, value and deadline are traced to the notice, not guessed from the title |
| Does it read the tender documents, or only the notice? | It opens ZIP and 7z bundles and reads PDF, DOCX and XLSX files |
| How are CVP IS and TED duplicates handled? | Merged by TED notice number into one record, so one alert |
| Why did this tender alert me? | Stored, readable reasons for every match |
| Does the AI show its working? | Quotes, a word count read, and "not enough data" when true |
What generalises
Monitoring is an ingestion problem that looks like a search problem. Wherever the field you filter on lives inside an attachment, whether permits, grants or court notices, the parser decides your recall, so the attachment itself is the thing to read.
Keep the gates deterministic and explainable, give each record and each alert a stable identity, and let the model read prose rather than decide eligibility.
If you want to see how Tendris reads a tender in your sector, it is on our work page, our public sector work covers the rest, and you can book a call.
Common questions
How do I find Lithuanian public tenders for my company?
All Lithuanian procurements have run in the new CVP IS at viesiejipirkimai.lt since 1 December 2024, and larger ones are also published on the EU's TED. You can search both by hand, filtering on CPV codes for your sector. A monitoring tool such as Tendris reads both sources every two hours and alerts you when a new tender matches your profile.
What is a CPV code and why does it matter for tender alerts?
A CPV code is the EU's common procurement vocabulary number that classifies what a tender buys, for example construction works or IT services. Most tender alerts match on it. Tendris reads the code from each tender's notice PDF and scores a CPV overlap as its heaviest signal, worth 30 points, so a company's sector codes decide which tenders reach it.
How does AI read public tender documents?
First the files have to become text. Tendris downloads the tender's document bundle from CVP IS, opens the ZIP and any 7z archive nested in it, and extracts text from every PDF in the bundle and from the PDF, DOCX, XLSX and older DOC files inside the 7z. A language model then returns a fixed structure: requirements, qualification and evaluation criteria, timeline, risks with a quoted source, and a confidence figure.
How often should I check for new public tenders?
New Lithuanian tenders appear in CVP IS throughout the working day, and a tender found late leaves less time to prepare a bid, so check at least daily. Tendris reads CVP IS and TED every two hours, sends real-time matches by Telegram straight away and sends a daily digest at 9:00 Vilnius time with the five highest-scoring new matches.
How do tender monitoring tools avoid duplicate alerts?
They need a stable identity for each tender and each alert. Tendris gives every tender an ID based on its source and reads TED before CVP IS on each run, so a national record that links to a TED notice merges into that TED record by notice number. Matches are stored under a database rule of one row per company per tender, so each company gets one alert per tender.