# Greek Public Tenders Monitor & Alerts (`jimkarageo/greek-tenders-monitor`) Actor

Get alerted when new Greek public tenders, contracts or awards match your criteria. Watches Diavgeia and KIMDIS, reports only what is new since the last run, and can email you.

- **URL**: https://apify.com/jimkarageo/greek-tenders-monitor.md
- **Developed by:** [Dimitris Karageorgis](https://apify.com/jimkarageo) (community)
- **Stats:** 2 total users, 1 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.00 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Greek Public Tenders Monitor & Alerts

Get told when a new Greek public tender, contract or award matches your criteria. Watches **both** official registries — **ΚΗΜΔΗΣ** (public procurement) and **Διαύγεια** (government transparency) — reports only what is new since the last run, and can email you.

Point an Apify Schedule at it and it becomes a standing alert.

***

### What makes it a monitor, not a search

Scheduling a search would email you the same records every day. This Actor remembers what it has already reported, in storage that survives between runs, so each run returns **only genuinely new records**.

- Nothing new → nothing reported, no email, and you are charged only the run fee.
- A record is never reported twice, even though each run deliberately searches an overlapping window.
- Several independent alerts can run from one account: give each a different **Alert name** and each keeps its own memory.

The overlapping window matters. Greek public bodies publish with a delay — a contract signed on the 1st may reach the registry on the 20th — so each run looks back further than the gap between runs. Deduplication is what makes that safe.

***

### Setting up a daily alert

1. Run the Actor once with your criteria and check the results. This first run reports everything in the window and establishes the baseline.
2. Save it as a Task.
3. Add a Schedule to that Task — daily is the usual choice.
4. Keep `alertName` unchanged. Changing it starts a new, empty memory and you will be re-notified about old records.

Fill in `emailTo` and new findings arrive by email. Leave it empty and they arrive in the dataset, where Apify's own integrations (webhook, Slack, Make, Zapier) can pick them up.

Set **Test mode** (`mockEmail`) to build the email and log it without sending, so you can try an alert safely.

***

### Input

| Field | Type | Description |
|---|---|---|
| `alertName` | string | Names this alert and keeps its memory separate. **Keep it stable.** |
| `sources` | array | `kimdis`, `diavgeia`, or both. Default: both. |
| `keywords` | array | Words to match in the title or subject. |
| `organization` | string | Watch one public body: name, id, or VAT number. Both registries share the same ids, so one name covers both. |
| `contractorVat` | string | Watch what one company wins. **ΚΗΜΔΗΣ only.** |
| `cpvCodes` | array | Watch one procurement category. **ΚΗΜΔΗΣ only.** |
| `minAmount` | integer | Ignore anything smaller. |
| `lookbackDays` | integer | How far back each run searches. Default `7`. |
| `emailTo` | string | Where to send findings. Comma-separate several. |
| `mockEmail` | boolean | Build the email but do not send it. |
| `kimdisRecordTypes` | array | Default: contracts and tender notices. |
| `diavgeiaDecisionTypes` | array | Default: awards, tender notices and contract awards. |
| `maxResults` | integer | Safety cap per run. Default `200`. |

#### Example: watch your sector

Everything over €50,000 mentioning IT supplies, anywhere in Greek government:

```json
{
  "alertName": "IT contracts over 50k",
  "sources": ["kimdis", "diavgeia"],
  "keywords": ["προμήθεια υπολογιστών", "λογισμικού"],
  "minAmount": 50000,
  "lookbackDays": 7,
  "emailTo": "me@example.com"
}
```

#### Example: watch a competitor

Every contract one company wins:

```json
{
  "alertName": "Competitor watch",
  "sources": ["kimdis"],
  "contractorVat": "800606208",
  "kimdisRecordTypes": ["contracts", "auctions"],
  "lookbackDays": 14,
  "emailTo": "me@example.com"
}
```

***

### Output

One dataset item per **new** record:

```json
{
  "id": "kimdis:contracts:26SYMV019898583",
  "source": "kimdis",
  "recordType": "Σύμβαση",
  "title": "ΣΥΜΦΩΝΗΤΙΚΟ ΥΠΗΡΕΣΙΑΣ ΠΡΟΣΒΑΣΗΣ ΣΤΗΝ ΤΡΑΠΕΖΑ ΝΟΜΙΚΩΝ ΠΛΗΡΟΦΟΡΙΩΝ",
  "date": "2026-10-01",
  "organizationName": "ΔΗΜΟΣ ΑΘΗΝΑΙΩΝ",
  "amount": 6825.0,
  "contractorName": "NETCOMPANY SA ΕΛΛΗΝΙΚΟ ΥΠΟΚΑΤΑΣΤΗΜΑ",
  "contractorVat": "099360290",
  "url": "https://cerpp.eprocurement.gov.gr/khmdhs-opendata/contract/attachment/26SYMV019898583",
  "firstSeenAt": "2026-10-03T21:37:30+00:00",
  "details": { "…": "the full source record, nothing dropped" }
}
```

`details` carries every field the source published, so the common shape above never costs you information.

***

### Things to know

**The first run is noisy by design.** With no memory yet, it reports everything in the look-back window. That is the baseline; run it once manually before scheduling.

**Keep `lookbackDays` longer than your schedule gap.** Daily schedule → 7 days is a safe default. Publication delays are real and a window that is too tight silently misses records. Overlap costs nothing because duplicates are filtered.

**Some filters are ΚΗΜΔΗΣ-only.** The Διαύγεια API cannot filter by contractor VAT or CPV code. When you set those, the run log says plainly that they apply to ΚΗΜΔΗΣ results only.

**Διαύγεια matches exact word forms.** There is no stemming: `υπολογιστη` finds nothing while `υπολογιστών` finds results. Use the form that appears in Greek documents, and list more than one.

**Dates mean different things per source.** ΚΗΜΔΗΣ filters on the day an act reached the registry; Διαύγεια on the decision's issue date.

***

### Related Actors

- [Greek Public Contracts & Tenders Search (KIMDIS)](https://apify.com/jimkarageo/greek-public-contracts-kimdis) — one-off procurement search.
- [Greek Public Contractor Profile](https://apify.com/jimkarageo/greek-contractor-profile) — when an alert names a company you do not know, profile its whole record with the Greek state from its VAT number.
- [Greek Government Decisions Search (Diavgeia)](https://apify.com/jimkarageo/greek-diavgeia-search) — one-off search across all government decisions.

***

### Limitations & disclaimer

- Data comes from the official ΚΗΜΔΗΣ and Διαύγεια OpenData APIs **as published**. Public bodies upload their own acts, so completeness and accuracy are theirs. **No guarantee of completeness is given or implied**, and an alert is not a substitute for checking the registries.
- ΚΗΜΔΗΣ refreshes once a day, so same-day acts may not appear yet.
- If the alert's stored memory is lost or the alert is renamed, the next run re-reports recent records rather than failing.
- This tool watches **contracts and public bodies**, not individuals. Contractor records are companies and their VAT numbers; some sole traders appear as named persons because Greek law requires publication. Handle any personal data in results in line with the GDPR.
- ΚΗΜΔΗΣ data is licensed CC BY 4.0 by the Greek Ministry of Digital Governance. Not affiliated with or endorsed by the Ministry.

***

***

## Ελληνικά

### Τι κάνει

Σε ειδοποιεί όταν βγαίνει **νέα** δημόσια σύμβαση, προκήρυξη ή ανάθεση που ταιριάζει στα κριτήριά σου. Παρακολουθεί **και τα δύο** επίσημα μητρώα — ΚΗΜΔΗΣ και Διαύγεια — και στέλνει μόνο ό,τι είναι καινούργιο από την προηγούμενη φορά. Με Apify Schedule γίνεται μόνιμη ειδοποίηση.

### Γιατί δεν είναι απλή αναζήτηση

Μια προγραμματισμένη αναζήτηση θα σου έστελνε τα ίδια αποτελέσματα κάθε μέρα. Αυτό το εργαλείο **θυμάται τι σου έχει ήδη στείλει**, σε μνήμη που επιβιώνει μεταξύ εκτελέσεων.

- Δεν βγήκε τίποτα νέο → δεν στέλνεται τίποτα και χρεώνεσαι μόνο το τέλος εκτέλεσης.
- Καμία εγγραφή δεν στέλνεται δύο φορές.
- Πολλές ανεξάρτητες ειδοποιήσεις: διαφορετικό **Όνομα ειδοποίησης** = ξεχωριστή μνήμη.

Η επικάλυψη του παραθύρου είναι σκόπιμη: οι φορείς αναρτούν με καθυστέρηση, οπότε κάθε εκτέλεση κοιτάζει πιο πίσω από το διάστημα μεταξύ εκτελέσεων. Η αφαίρεση διπλών είναι αυτό που το κάνει ασφαλές.

### Πώς στήνεται

1. Τρέξ' το μία φορά με τα κριτήριά σου — η πρώτη εκτέλεση φέρνει τα πάντα του παραθύρου και ορίζει τη βάση.
2. Αποθήκευσέ το ως Task.
3. Βάλε Schedule στο Task (συνήθως ημερήσιο).
4. **Μην αλλάξεις το `alertName`** — αλλιώς ξεκινά νέα, άδεια μνήμη και θα ξαναπάρεις παλιές εγγραφές.

### Προσοχή

- **Η πρώτη εκτέλεση είναι θορυβώδης**, εκ σχεδιασμού.
- **Κράτα το `lookbackDays` μεγαλύτερο από το διάστημα του schedule.** Ημερήσιο → 7 ημέρες.
- **Το ΑΦΜ αναδόχου και τα CPV δουλεύουν μόνο στο ΚΗΜΔΗΣ** — το API της Διαύγειας δεν τα υποστηρίζει. Το log το λέει καθαρά.
- **Η Διαύγεια θέλει ακριβή μορφή λέξης**: το `υπολογιστη` δεν φέρνει τίποτα, το `υπολογιστών` φέρνει.

### Νομικά

Τα δεδομένα προέρχονται από τα επίσημα API και παρέχονται **όπως έχουν αναρτηθεί** — **χωρίς εγγύηση πληρότητας**. Η ειδοποίηση δεν υποκαθιστά τον έλεγχο των μητρώων. Δεν συνδέεται με το Υπουργείο Ψηφιακής Διακυβέρνησης.

***

**Keywords:** Greece, Greek public procurement, tender alerts, contract alerts, ΚΗΜΔΗΣ, Διαύγεια, monitoring, notifications, δημόσιοι διαγωνισμοί, ειδοποιήσεις, προκηρύξεις, παρακολούθηση, scheduled, webhook, email alerts, competitor monitoring, MCP

# Actor input Schema

## `alertName` (type: `string`):

Names this alert and keeps its memory separate from your other alerts. Keep it the same between runs, or the alert forgets what it already reported. Use a different name to run a second, independent alert. | Ονομάζει την ειδοποίηση και κρατά τη μνήμη της ξεχωριστή. Κράτα το ίδιο μεταξύ εκτελέσεων, αλλιώς ξεχνά τι έχει ήδη στείλει.

## `sources` (type: `array`):

Which registries to watch. | Ποια μητρώα να παρακολουθεί.

## `keywords` (type: `array`):

Words to match in the title or subject. Each entry is searched separately. IMPORTANT for Διαύγεια: it matches the exact word form with no stemming, so use the form that appears in Greek documents. | Λέξεις για αναζήτηση. ΠΡΟΣΟΧΗ στη Διαύγεια: ταιριάζει ακριβώς τη μορφή της λέξης, χωρίς λημματοποίηση.

## `organization` (type: `string`):

Watch one public body only: its name, id, or 9-digit VAT number. Both registries use the same identifiers, so one name covers both. Leave empty to watch all of Greek government. | Παρακολούθηση ενός φορέα: όνομα, κωδικός ή ΑΦΜ. Κενό = όλο το δημόσιο.

## `contractorVat` (type: `string`):

Watch what one company wins. ΚΗΜΔΗΣ only — the Διαύγεια API cannot filter by contractor VAT. | Παρακολούθηση μιας εταιρείας. Μόνο ΚΗΜΔΗΣ.

## `cpvCodes` (type: `array`):

Watch one procurement category, e.g. 30200000-1. ΚΗΜΔΗΣ only. | Παρακολούθηση κατηγορίας. Μόνο ΚΗΜΔΗΣ.

## `minAmount` (type: `integer`):

Ignore anything smaller. For Διαύγεια, records with no amount in their metadata are skipped when this is set. | Αγνοεί μικρότερα ποσά.

## `lookbackDays` (type: `integer`):

How far back each run searches. Keep it comfortably longer than the gap between runs, because public bodies publish with a delay — 7 days for a daily schedule is a safe default. Records already reported are never repeated. | Πόσο πίσω ψάχνει κάθε εκτέλεση. Κράτα το άνετα μεγαλύτερο από το διάστημα μεταξύ εκτελέσεων.

## `emailTo` (type: `string`):

Email address to notify when new records are found. Comma-separate several. Leave empty to get results in the dataset only. Quiet runs send nothing. | Διεύθυνση email για ειδοποίηση. Κενό = μόνο στο dataset.

## `mockEmail` (type: `boolean`):

Build the email and log it without sending, so you can test the alert safely. | Φτιάχνει το email χωρίς να το στείλει, για ασφαλή δοκιμή.

## `kimdisRecordTypes` (type: `array`):

Which ΚΗΜΔΗΣ acts to watch. Default: contracts and tender notices. | Ποιες πράξεις ΚΗΜΔΗΣ. Προεπιλογή: συμβάσεις και προκηρύξεις.

## `diavgeiaDecisionTypes` (type: `array`):

Which Διαύγεια decisions to watch. Default: awards, tender notices and contract awards. | Ποιες πράξεις Διαύγειας. Προεπιλογή: αναθέσεις, διακηρύξεις, κατακυρώσεις.

## `maxResults` (type: `integer`):

Safety cap so one very broad alert cannot report thousands at once. | Όριο ασφαλείας ανά εκτέλεση.

## Actor input object example

```json
{
  "alertName": "Greek tenders alert",
  "sources": [
    "kimdis",
    "diavgeia"
  ],
  "keywords": [
    "προμήθεια"
  ],
  "organization": "Δήμος Αθηναίων",
  "lookbackDays": 7,
  "mockEmail": false,
  "kimdisRecordTypes": [
    "contracts",
    "notices"
  ],
  "diavgeiaDecisionTypes": [
    "awards",
    "tenders",
    "contract_awards"
  ],
  "maxResults": 200
}
```

# Actor output Schema

## `newRecords` (type: `string`):

The new matching records found by this run, as JSON items in the default dataset. Empty when nothing new appeared.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "alertName": "Greek tenders alert",
    "sources": [
        "kimdis",
        "diavgeia"
    ],
    "keywords": [
        "προμήθεια"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("jimkarageo/greek-tenders-monitor").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "alertName": "Greek tenders alert",
    "sources": [
        "kimdis",
        "diavgeia",
    ],
    "keywords": ["προμήθεια"],
}

# Run the Actor and wait for it to finish
run = client.actor("jimkarageo/greek-tenders-monitor").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "alertName": "Greek tenders alert",
  "sources": [
    "kimdis",
    "diavgeia"
  ],
  "keywords": [
    "προμήθεια"
  ]
}' |
apify call jimkarageo/greek-tenders-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,jimkarageo/greek-tenders-monitor"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/WbJjhq560QMb9b9oG/builds/en8yfYkbDP1cGB23W/openapi.json
