# Romanian Public Procurement (SEAP/SICAP) (`apnoda/seap-sicap-tenders`) Actor

Romanian public tenders from e-licitatie.ro (SEAP/SICAP): sub-threshold achiziții directe (not in EU TED) and above-threshold licitații publice. PII-stripped per GDPR, enriched with Romanian sector taxonomy, winner intelligence joined on awarded records. MCP-native, pay-per-record, no subscription.

- **URL**: https://apify.com/apnoda/seap-sicap-tenders.md
- **Developed by:** [Apnoda](https://apify.com/apnoda) (community)
- **Categories:** Developer tools, MCP servers, AI
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $60.00 / 1,000 tender emitted (primary)s

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## Achiziții Publice România (SEAP/SICAP)

🇷🇴 [Română](#română) · 🇬🇧 [English](#english)

---

### Română

**Licitații și achiziții publice din România, livrate ca date structurate pentru agenți AI și dezvoltatori.** Date live + arhivă istorică, achiziții directe + licitații publice, cu informații despre câștigători. Compatibil MCP, plată pe rezultat, fără abonament.

> 🤖 **Pregătit pentru plăți agentice:** x402 (automat pentru orice Actor cu preț pay-per-event).

#### Ce face acest Actor

Extrage anunțuri de achiziții publice din România de pe [e-licitatie.ro](https://e-licitatie.ro) (SEAP/SICAP) și le livrează ca înregistrări JSON normalizate, cu PII eliminat, îmbogățite cu taxonomie sectorială românească, CUI-uri autorități contractante parsate și date despre ofertanții câștigători atașate pentru procedurile atribuite.

Acoperă ambele tipuri:

- **Achiziții directe sub-prag**: achiziții de valoare mică (sub ~€140k servicii / €5.5M lucrări) publicate exclusiv pe SEAP. Acesta este segmentul IMM din România și **nu apare în TED UE**. Aproximativ 10 000 de anunțuri pe săptămână.
- **Licitații publice peste prag**: achiziții de valoare mare, publicate și în TED UE. Aproximativ 1 500 de anunțuri pe săptămână, cu date despre câștigători atașate după atribuire.

Volum total: ~11 500 de anunțuri de achiziții publice din România pe săptămână. Plătești doar pentru înregistrările care corespund filtrelor tale.

#### De ce să folosești acest Actor

Trei profiluri de cumpărător:

**Pentru dezvoltatori de agenți AI:** Compatibil MCP din prima zi. Te conectezi via `mcp.apify.com?tools=apnoda/seap-sicap-tenders` și agentul tău are **14 unelte**: rezolvare nume-la-CUI, căutare, detaliu, profiluri furnizori/autorități, benchmarking de preț, flag-uri de neregularitate, acorduri-cadru, comparație de furnizori, căutare semantică, clasamente și o verificare gratuită a acoperirii (lista completă mai jos). Fără abonamente, fără chei API, fără infrastructură.

**Pentru dezvoltatori care construiesc instrumente de achiziții:** API-ul JSON nedocumentat al SEAP are multe capcane: limitele `searchTooLong`, dispatch-ul `showOngoingDa`, semantica stărilor, filtre absente pe server. Acest Actor le abstractizează. Output-ul este stabil și tipat.

**Pentru analiști și jurnaliști:** Interogări punctuale după CUI, cod CPV, cuvânt cheie, interval de date, valoare. Export în CSV. Plătești cenți pe interogare. Fără cont la un SaaS românesc.

#### Încearcă acum

1. **Click "Try for free"**, rulează cu input-urile implicite (CPV 45, construcții, ultimele 7 zile), până la 50 de înregistrări.
2. **Exportă ca CSV** și deschide în Excel / Google Sheets.
3. **SAU** conectează via MCP și întreabă Claude în limbaj natural (vezi secțiunea următoare).

Primul rulaj este limitat implicit la 50 de înregistrări, deci costă sub $5, acoperit integral de creditul Apify de $5 la înscriere. Mărește "Maximum results" pentru acoperire completă.

#### Comparație rapidă

| Capabilitate | Acest Actor | sicap.ai (Free) | sicap.pro | DataDriven.ro | Actori Apify TED |
|---|---|---|---|---|---|
| Achiziții directe (sub-prag) | ✅ | ✅ | ✅ | ✅ | ❌ TED le omite |
| Date despre câștigători | ✅ în output | ✅ în UI | ✅ în UI | ✅ în UI | parțial |
| API public pentru dezvoltatori | ✅ | ❌ | ❌ | ❌ | ✅ |
| Acces MCP / agenți AI | ✅ | ❌ | ❌ | ❌ | unii |
| Filtre programatice | ✅ | ❌ | ❌ | ❌ | ✅ |
| Alerte email | ✅ via Apify Schedules + Gmail | ❌ | ✅ | ✅ | ❌ |
| Export CSV/JSON brut | ✅ | ❌ | limitat | limitat | ✅ |
| Urmărire acorduri-cadru (acord-cadru) | ✅ | ❌ | ❌ | ❌ | ❌ |
| Flag-uri de neregularitate | ✅ | ❌ | ❌ | ❌ | ❌ |
| Căutare semantică (embeddings) | ✅ | ❌ | ❌ | ❌ | ❌ |
| Plăți agentice (x402) | ✅ | ❌ | ❌ | ❌ | ❌ |
| Model de preț | pay-per-record | gratuit | abonament anual | abonament lunar/utilizator | variabil |

Nișa acestui Actor: **acces programatic la datele SEAP, via MCP, API sau CSV, fără abonament și fără cont.** Datele sunt aceleași disponibile pe alte platforme românești de monitorizare licitații (UI web, alerte email, abonamente lunare/anuale). Diferența: livrăm raw, prin API sau MCP, plătit doar la utilizare. Pentru integrare în propriul cod, agenți AI, sau analize one-shot, acest Actor.

⚠️ **Acest Actor NU oferă direct:**
- Detectare automată "doar licitații noi" (Pattern 2 din secțiunea Programare automată acoperă ~80% din cazuri; pentru diff strict, vezi Pattern 3)
- Interfață vizuală pentru echipă (datele se accesează via API, MCP, sau dataset Apify)
- OCR pentru documente PDF atașate (doar metadatele licitațiilor)

#### Utilizare MCP

Conectează Claude Desktop (sau orice client MCP) adăugând următoarele în configurație:

```json
{
  "mcpServers": {
    "achizitii-romania": {
      "url": "https://mcp.apify.com?tools=apnoda/seap-sicap-tenders"
    }
  }
}
````

Apoi întreabă Claude lucruri precum:

- *"Ce licitații de construcții au fost publicate în România săptămâna trecută peste 500 000 RON?"* (`search_romanian_tenders`)
- *"Obține detaliile complete și câștigătorul pentru licitația SCNA1128899."* (`get_tender_detail`)
- *"Listează contractele semnate de Ministerul Sănătății în 2025 cu principalii furnizori."* (`list_authority_contracts`)
- *"Ce a câștigat Alliance Healthcare în achizițiile publice din România?"* (`get_winner_profile`)
- *"Cât de concentrată e baza de furnizori a Primăriei Cluj-Napoca?"* (`analyze_authority_spending`)
- *"Este 2 milioane RON un preț normal pentru lucrări CPV 4533?"* (`benchmark_cpv_pricing`)
- *"Există semnale de alarmă pentru cumpărătorul cu CUI 4266456?"* (`detect_irregularities`)
- *"Ce acorduri-cadru pentru CPV 33 sunt cele mai consumate?"* (`framework_agreement_lookup`)
- *"Furnizorii 8955860 și 12345678 concurează pentru aceiași cumpărători?"* (`compare_winners`)
- *"Găsește licitații similare cu SCNA1128899."* (`find_similar_tenders`)
- *"Găsește licitații despre asfaltarea drumurilor județene."* (`search_by_natural_description`)
- *"Top 3 câștigători în Cluj în 2024."* (`rank_entities`)
- *"Care este CUI-ul Primăriei Cluj-Napoca?"* (`resolve_entity`)
- *"Câte licitații live sunt în set și cât de proaspăt este?"* (`get_seap_coverage`, gratuit)

Claude alege unealta potrivită, o apelează și răspunde. Plătești per înregistrare returnată, nu per interogare.

##### Unelte MCP disponibile (14)

Toate cele 14 unelte sunt expuse via MCP. Apelurile se taxează $0.05 per apel reușit (`mcp_tool_request`), cu excepția `get_seap_coverage`, care este gratuit (nu declanșează niciun eveniment); `detect_irregularities` taxează suplimentar $0.10 per flag returnat.

| Unealtă | Ce face |
|---|---|
| **`search_romanian_tenders`** | Filtrare după CPV, cuvânt cheie, interval de date, tip, valoare, CUI autoritate, județ, acord-cadru, ofertant unic și CUI câștigător (urmărirea concurenților: doar licitațiile câștigate de furnizorii listați). Achizițiile directe au CUI-ul câștigătorului atașat; licitațiile atribuite sunt marcate `winner_lookup_required: true` pentru înlănțuire cu unealta de detaliu. |
| **`get_tender_detail`** | O singură licitație după `sicap_id`, cu toate contractele și câștigătorii. Acceptă toate prefixele (DA, CAN, CN, SCN, SCNA). |
| **`list_authority_contracts`** | Contractele atribuite de un CUI într-un an + agregate precalculate (cheltuieli totale, furnizori unici, top 5 după valoare). |
| **`get_winner_profile`** | Profilul de achiziții al unui furnizor după CUI: istoric câștiguri, valori totale, licitații recente. |
| **`analyze_authority_spending`** | Cheltuielile unei autorități publice: total, concentrare (HHI), top furnizori, narațiune în limba română. |
| **`benchmark_cpv_pricing`** | Repere de preț pentru o categorie CPV: mediană, IQR, P5/P95, defalcare pe județ. |
| **`detect_irregularities`** | Flag-uri de neregularitate bazate pe reguli: ofertant unic, preț anormal, sole-source repetat, umflarea valorii prin amendamente. |
| **`framework_agreement_lookup`** | Acorduri-cadru (acord-cadru) cu consum + rollup pe contractele subsecvente. |
| **`compare_winners`** | Comparație head-to-head între doi furnizori români. |
| **`find_similar_tenders`** | Licitații similare semantic cu o licitație sursă (embedding e5-small). |
| **`search_by_natural_description`** | Căutare semantică în text liber peste licitații (română sau engleză). |
| **`rank_entities`** | Top-N după furnizori, cumpărători, coduri CPV sau județe, după o metrică aleasă. |
| **`resolve_entity`** | Găsește CUI-ul unei firme sau autorități după nume (cumpărători + furnizori). Pornește de aici când ai un nume, nu un CUI, apoi transmiți rezultatul către uneltele indexate după CUI. |
| **`get_seap_coverage`** (gratuit) | Dimensiunea corpusului (număr de licitații live pe paliere, profiluri furnizori/autorități, acorduri-cadru) plus data prospețimii pe cele două substraturi. Fără argumente, fără cost. Verifică acoperirea și actualitatea înainte de a apela o unealtă cu plată. |

**Câteva detalii importante** (prezente și în răspunsul fiecărei unelte, deci un agent le primește și la momentul apelului):

- `framework_agreement_lookup`: `consumed_pct` poate depăși 100. Acordurile-cadru din România își supra-consumă frecvent plafonul anunțat, iar acest supra-consum este semnalul, deci nu este niciodată limitat la 100.
- `benchmark_cpv_pricing`: percentilele (P5/P25/mediană/P75/P95) și stddev apar doar pentru un rând cu sursă unică (un CPV de 4/6/8 cifre cu un an specific); un prefix de 2 cifre sau un roll-up pe mai mulți ani le întoarce ca null. `min`, `max` și media ponderată rămân populate.
- `detect_irregularities`: fiecare flag returnat este taxat individual, deci o verificare cu multe flag-uri pentru un cumpărător sau furnizor costă proporțional mai mult; un rezultat curat (`flags: []`) nu taxează niciun flag.

##### Prompturi MCP (fluxuri ghidate)

Trei fluxuri de analiză gata făcute sunt expuse ca prompturi MCP (fiecare cu un nume în română și un alias în engleză, șase nume înregistrate în total). Clientul tău MCP le listează ca slash-command-uri sau șabloane; completezi argumentele și promptul se extinde într-o rutină în mai mulți pași care apelează uneltele de mai sus în ordine.

| Prompt (RO / alias EN) | Argumente | Ce face |
|---|---|---|
| `due-diligence-autoritate-contractanta` / `due-diligence-buyer` | `authority_cui`, `year` | Rutină de due-diligence pentru cumpărător: profil de cheltuieli, concentrarea furnizorilor, o verificare de nereguli și top contracte pentru o autoritate. |
| `analiza-oportunitate-licitatie` / `tender-opportunity-analysis` | `tender_id`, `my_supplier_cui` (opțional) | Evaluează o licitație ca oportunitate: detaliu complet, reper de preț pe categorie, licitații similare și (când dai un CUI de furnizor) o citire a potrivirii. |
| `profil-ofertant-castigator` / `supplier-winner-profile` | `supplier_cui`, `lookback_years` (opțional, implicit 3) | Profilul istoricului de câștiguri al unui furnizor: totaluri, amploare cumpărători/CPV, atribuiri recente și o comparație cu furnizori similari. |

##### Resurse MCP (date de referință)

Patru seturi de date de referință, doar-citire, sunt expuse ca resurse MCP; un agent le poate citi pentru a rezolva coduri și vocabular fără a consuma un apel de unealtă.

| URI resursă | Ce este |
|---|---|
| `cpv://tree` | Ierarhia CPV 2008: 9.454 de coduri (45 de diviziuni rădăcină) cu etichete RO+EN și rollup-ul pe 9 sectoare românești. |
| `nuts://ro` | Cele 41 de județe plus București, cu coduri NUTS3 și rollup-ul NUTS2. |
| `glossary://ro-procurement` | Un glosar bilingv (RO/EN) de ~130 de termeni din vocabularul achizițiilor publice, raportat la Legea 98/2016 și Legea 99/2016. |
| `thresholds://ro-2026` | Praguri de achiziții din Legea 98/2016 + 99/2016 în EUR și RON, cu date de intrare în vigoare. |

#### Utilizare Apify (non-MCP)

Rulare standard de Actor. Configurezi input-ul, pornești, colectezi rezultatele din dataset.

```json
{
  "mode": "live",
  "tiers": ["sub_threshold", "above_threshold"],
  "publicationDateStart": "2026-04-17",
  "publicationDateEnd": "2026-04-24",
  "cpvCodes": ["45"],
  "minValueRon": 100000,
  "acquisitionStatus": "ongoing",
  "maxResults": 1000
}
```

Output-ul ajunge într-un dataset Apify standard. Export ca JSON, CSV sau XLSX.

Mod istoric (arhiva 2007–2018 via `istoric.e-licitatie.ro`) disponibil setând `mode: "backfill"`. **Doar licitațiile peste-prag.** Arhiva sub-prag este goală pe `istoric.e-licitatie.ro` pentru că Legea 98/2016 a formalizat achizițiile directe după fereastra acoperită de arhivă. Preț per înregistrare mai mic reflectă valoarea comercială mai redusă a datelor istorice.

#### Sarcini pre-configurate (Task templates)

Cinci configurații gata de utilizat care acoperă scenariile cele mai frecvente. **Copiază JSON-ul de input** într-o Sarcină nouă în Apify Console (Actor → tab `Saved tasks` → `Create new task` → lipește în câmpul `Input`), apoi adaugă un Schedule cu cadența recomandată. Toate folosesc modul `alert_check` (cu excepția #5), deci dedupă structural între execuții, primești doar înregistrările NOI sau MODIFICATE de la ultima rulare.

**1. Construcții în județul Cluj, zilnic 7:00 EET**

Cumpărători locali de construcții (drumuri, clădiri, reabilitări) cu reședința în județul Cluj. Cadență recomandată: zilnic 07:00 EET.

```json
{
  "mode": "alert_check",
  "tiers": ["sub_threshold", "above_threshold"],
  "cpvCodes": ["45"],
  "judet": ["Cluj"],
  "alertTypes": []
}
```

**2. IT & servicii software în București, bi-zilnic**

Achiziții IT (consultanță, dezvoltare software, integrare) la nivelul Capitalei. Cadență recomandată: 06:00 și 14:00 EET.

```json
{
  "mode": "alert_check",
  "tiers": ["sub_threshold", "above_threshold"],
  "cpvCodes": ["72"],
  "judet": ["Bucuresti"],
  "alertTypes": []
}
```

**3. Acord-cadru active, medicale, săptămânal**

Acorduri-cadru active (CPV 33, echipament medical, medicamente, dispozitive), exclude direct-acquisitions, care nu sunt acord-cadru. Cadență recomandată: luni 08:00 EET.

```json
{
  "mode": "alert_check",
  "tiers": ["above_threshold"],
  "cpvCodes": ["33"],
  "frameworkOnly": true,
  "alertTypes": []
}
```

**4. Doar amendamente, zilnic**

Notifică doar când o licitație existentă este AMENDED (erată sau versionare incrementată). Util pentru monitorizarea modificărilor pe licitații pe care le urmărești deja. Cadență recomandată: zilnic 09:00 EET.

```json
{
  "mode": "alert_check",
  "tiers": ["above_threshold"],
  "alertTypes": ["AMENDED"]
}
```

**5. Audit single-bidder pentru o autoritate, la cerere**

Rulează la cerere când vrei să vezi toate licitațiile finalizate cu un singur ofertant pentru o autoritate-țintă (ex: o primărie cu rată ridicată de single-bidder). Înlocuiește `4266456` cu CUI-ul autorității. Heuristică: `highestOfferValue === lowestOfferValue` cu ambele non-null și non-zero.

```json
{
  "mode": "live",
  "tiers": ["above_threshold"],
  "acquisitionStatus": "with_winners",
  "authorityCui": ["4266456"],
  "singleBidder": true
}
```

**Note operaționale:**

- `judet` rezolvă numele de județ insensibil la majuscule și diacritice; `Cluj` / `CLUJ` / `cluj` și `București` / `Bucuresti` se potrivesc identic.
- `frameworkOnly` exclude `sub_threshold` automat (achizițiile directe sunt bilaterale prin construcție, niciodată acord-cadru).
- `alertTypes` filtrează ce livrăm în dataset; alert\_state se actualizează pentru toate înregistrările matched, deci modificarea filtrului mai târziu NU va re-trimite înregistrările istorice ca NEW.
- **Modificarea `judet` / `frameworkOnly` / `singleBidder` mintă o porțiune nouă de alert\_state**, deci următoarea execuție va re-trimite TOATE înregistrările potrivite ca NEW. Asta e prin design, seturi diferite de județe / acord-cadru / single-bidder = căutări salvate diferite. Dacă vrei dedup între aceste filtre, creează Sarcini separate.
- Pentru Sarcina #5, rezultatul nu dedupă între execuții (e mod `live`); rulează la cerere când ai nevoie de un instantaneu.

#### Programare automată + livrare email

Pentru a primi automate licitațiile noi pe email, fără cod sau servicii terțe:

**Pattern 1, Snapshot zilnic (recomandat pentru majoritate)**

1. Configurează un **Apify Schedule** care rulează acest Actor zilnic la 09:00 (Europe/Bucharest, DST-aware).
2. Activează **Gmail integration** pe tab-ul Integrations al Actor-ului. OAuth direct la Google, dataset-ul se atașează automat ca CSV/JSON.
3. În fiecare dimineață, primești un email cu toate licitațiile care corespund filtrelor tale (CPV, autoritate, etc.).

Cost lunar: o rulare zilnică pe CPV 45 = ~$2.70/lună. Fără infrastructură de menținut.

**Pattern 2, Doar licitații publicate ieri**

Aceeași configurație ca Pattern 1, dar setezi `publicationDateStart: yesterday` + `publicationDateEnd: yesterday` în input-ul programat. Astfel primești doar ce s-a publicat în ultimele 24 de ore, efectul "alertă pentru lucruri noi" fără cod adițional.

**Pattern 3, Detectare schimbări (avansat)**

Pentru "trimite email DOAR când apare ceva nou față de rularea anterioară", configurează un al doilea Actor downstream care face diff împotriva dataset-ului precedent. Posibil dar necesită cod custom.

**Pattern 4, Mod `alert_check` (înlocuire abonament)**

Setează `mode: "alert_check"` în input + filtrele tale obișnuite (CPV, autoritate, cuvinte cheie, interval valoric). Actor-ul face diff împotriva stării tale anterioare de alertă (per `(user_id, task_id, filtre)`) și scrie un singur record per delta în dataset-ul rulării `alerts-<run_id>`. Tipuri detectate: `NEW`, `MODIFIED`, `AWARDED`, `AMENDED`, `EXTENDED`, `CANCELLED`. Plată: un singur event `tender_alert_digest` ($0.49 plat, identic pe toate planurile) per rulare care produce ≥1 delta, **event-ul digest nu este niciodată taxat pe rulări cu zero deltas** (garanția "fără digest gol"). Event-ul `actor_start` ($0.01) se aplică pe fiecare rulare, ca pe orice mod. Rezultatul net: o programare zilnică pe un filtru stabil costă tipic ~$0.01 baseline pe zilele fără schimbări + $0.49 doar în zilele cu deltas, vs ~$0.06 × numărul total de înregistrări la fiecare rulare în Pattern 2.

Documentație Apify: [Schedules](https://docs.apify.com/platform/schedules), [Webhooks](https://docs.apify.com/platform/integrations/webhooks), [Gmail integration](https://docs.apify.com/platform/integrations/gmail).

#### Rețete de integrare fără cod

Trimite licitațiile direct în uneltele pe care echipa ta le folosește deja, fără cod. Apify este declanșatorul și sursa de date; o platformă fără cod (Make, Zapier sau n8n) citește dataset-ul rulării finalizate și distribuie fiecare rând către Google Sheets, Slack, email sau oriunde altundeva.

Fiecare rețetă are aceiași trei pași:

1. **Declanșează la rularea finalizată.** Zapier: "Finished Task Run". Make: "Watch Task Runs". n8n: evenimentul "Task Run Finished" al nodului Apify.
2. **Ia rândurile.** Pasul de preluare a rândurilor: pe Make și n8n se numește "Get Dataset Items", pe Zapier "Fetch dataset items" (o căutare). Ce dataset citești depinde de mod (vezi mai jos).
3. **Trimite fiecare rând** către destinație: Google Sheets "Create Spreadsheet Row", Slack "Send a message" etc.

**Ce dataset citești.** O rulare `live` (sau `backfill`) scrie licitațiile care se potrivesc în **dataset-ul implicit** al rulării, al cărui `defaultDatasetId` se află în payload-ul declanșatorului, deci pasul 2 îl folosește direct. O rulare `alert_check` este diferită: scrie delta-urile de schimbare într-un **dataset denumit**, iar `defaultDatasetId` din payload arată către dataset-ul implicit (gol), nu către delta-uri. Referă dataset-ul denumit după nume: **`<your-apify-username>~alerts-<RUN_ID>`** (numele tău de utilizator Apify, apoi ID-ul rulării din payload; dataset-ul este creat sub contul tău când rulează Task-ul). Un simplu `alerts-<RUN_ID>` este interpretat ca ID de dataset, nu este unul, și nu întoarce nimic, deci prefixul `username~` este obligatoriu. Odată ce referința se rezolvă, acel dataset denumit există la fiecare rulare și este pur și simplu gol în zilele fără schimbări, deci rețeta nu face nimic în zilele liniștite, fără să dea eroare. Într-o delta `alert_check` fiecare licitație se află sub un obiect `current` (mapează `current.title_ro`, `current.primary_winner_name` și așa mai departe), alături de un `alert_type` la nivelul de sus.

**Rețeta 1: licitații noi într-un Google Sheet, deduplicate.** Un rând per licitație cu adevărat nouă, fără repetări, folosind `alert_check` astfel încât o fereastră de date suprapusă să nu scrie de două ori.

Input pentru Task salvat:

```json
{
  "mode": "alert_check",
  "tiers": ["sub_threshold", "above_threshold"],
  "cpvCodes": ["45"],
  "alertTypes": ["NEW"]
}
```

Conectare: declanșator "Finished Task Run", apoi pasul de preluare (pasul 2) citind `<your-apify-username>~alerts-<RUN_ID>`, apoi Google Sheets "Create Spreadsheet Row" mapând `current.title_ro`, `current.authority_name`, `current.value_ron`, `current.cpv_code`, `current.url`. Programează Task-ul zilnic; fiecare licitație nouă de construcții ajunge ca un rând în Sheet, o singură dată.

**Rețeta 2: licitații atribuite în Slack.** Postează în `#tenders` doar când o licitație urmărită este efectiv atribuită (câștigătorul trece de la gol la setat), fără repetări.

Input pentru Task salvat:

```json
{
  "mode": "alert_check",
  "tiers": ["above_threshold"],
  "cpvCodes": ["45"],
  "alertTypes": ["AWARDED"]
}
```

Conectare: declanșator "Finished Task Run", apoi pasul de preluare (pasul 2) citind `<your-apify-username>~alerts-<RUN_ID>`, apoi Slack "Send a message" per element, ex. *"Atribuit: {{current.title\_ro}} către {{current.primary\_winner\_name}} pentru {{current.contract\_value\_ron}} RON. {{current.url}}"*. AWARDED se declanșează doar pe licitațiile publice (peste-prag), o singură dată per atribuire.

**Cost.** Ambele rețete rulează în `alert_check`, deci urmează economia modului `alert_check` descrisă mai sus: `actor_start` ($0.01) se aplică pe fiecare rulare, iar o zi cu schimbări adaugă un singur `tender_alert_digest` ($0.49) peste, deci o zi liniștită costă ~$0.01 și o zi cu schimbări ~$0.50, indiferent de câte rânduri se potrivesc. Pe un filtru aglomerat este mult mai ieftin decât emiterea per înregistrare în mod live.

**Fără o platformă fără cod.** Pentru un snapshot one-shot într-un sheet, rulează în mod `live` și înlănțuie [actorul Google Sheets Import & Export](https://apify.com/lukaskrivka/google-sheets) pe un [webhook](https://docs.apify.com/platform/integrations/webhooks) de rulare-finalizată, transmițând ID-ul dataset-ului implicit al rulării finalizate. Livrarea nativă [Google Drive](https://docs.apify.com/platform/integrations/drive) (dataset-ul pus într-un folder Drive ca fișier) nu are nevoie de nicio unealtă terță.

Ghiduri de integrare: [Zapier](https://docs.apify.com/platform/integrations/zapier), [Make](https://docs.apify.com/platform/integrations/make), [n8n](https://docs.apify.com/platform/integrations/n8n).

#### Ce primești

Fiecare înregistrare conține:

```json
{
  "sicap_id": "SCNA1128899",
  "tier": "above_threshold",
  "cpv_code": "45331100-7",
  "cpv_label_ro": "Lucrări de instalare de echipamente de încălzire centrală",
  "sector_ro": "construcții",
  "authority_cui": "2351555",
  "authority_name": "Regia Autonomă Administrația Patrimoniului Protocolului de Stat",
  "authority_judet": "Bucuresti",
  "title_ro": "Lucrări de înlocuire a unui cazan de pardoseală...",
  "value_ron": 255012.86,
  "contract_value_ron": 260000,
  "publication_date": "2026-04-17T10:15:34+03:00",
  "finalization_date": "2026-04-24T11:20:00+03:00",
  "state": "Atribuita",
  "primary_winner_cui": "RO34649836",
  "primary_winner_name": "DAV CLIMA SYSTEM",
  "winners": [{"cui": "RO34649836", "name": "DAV CLIMA SYSTEM"}],
  "winner_cuis_joined": "RO34649836",
  "url": "https://e-licitatie.ro/pub/..."
}
```

Datele despre câștigători sunt prezente pe achizițiile directe din starea 2 în sus (furnizorii sunt pre-desemnați pentru achiziții directe) și pe licitațiile publice post-atribuire (prin join cu tabelul de contracte).

#### Calculator de costuri

**Prețuri:**

- Pornire Actor: $0.01
- Per licitație emisă (mod live): **$0.06**
- Per licitație din arhivă (mod backfill): $0.008
- Digest de alerte (mod `alert_check`): $0.49 plat per rulare cu ≥1 deltă (rulările cu zero deltas nu se taxează)
- Apel MCP tool (orice tool): $0.05 plat per apel finalizat cu succes (erorile de validare / erorile structurate de instrument / excepțiile neașteptate ale handler-ului nu se taxează)
- Flag de neregularitate (`detect_irregularities`): $0.10 per flag returnat (apelurile fără flag-uri nu se taxează)

> **Notă**, cele trei evenimente noi (`tender_alert_digest`, `mcp_tool_request`, `irregularity_flag`) trec prin coada lunară de revizuire a modificărilor de preț ale Apify. Până la aprobare, încercările de taxare sunt înregistrate dar nu produc o factură efectivă (SDK-ul Apify loghează `Ignored attempt to charge for an event`). Prețurile listate aici reprezintă rata finală post-aprobare.

Costurile de platformă/compute sunt absorbite în prețul pe eveniment, nu există taxe ascunse.

**Exemple reale:**

| Caz de utilizare | Interogare | Înregistrări/săptămână | Cost săptămânal |
|---|---|---|---|
| Monitorizare licitații construcții România (CPV 45) | cpv\_codes: `["45"]`, interval 7 zile | ~320 | **~$19** |
| Monitorizare achiziții medicale + IT (CPV 33 + 72) | cpv\_codes: `["33", "72"]`, doar peste-prag | ~400 | **~$24** |
| Urmărire licitații ale unui minister anume | authority\_cui: `"4266456"` | ~7 | **~$0.50** |
| Monitorizare 3 categorii CPV + 2 autorități | cpv\_codes + authority\_cui | ~800 | **~$48** |
| Analiză anuală a cheltuielilor unei autorități | list\_authority\_contracts(CUI, an) | ~35 contracte | **~$2** |

Filtrele CPV mai înguste + filtrele pe autoritate dau cel mai bun raport cost/semnal. Pentru acoperire largă, rulează mai multe interogări filtrate și unește rezultatele, SEAP limitează fiecare răspuns la 2 000 / 3 000 înregistrări per interogare (vezi limitări).

**Latență:** O căutare filtrată pe CPV pentru 7 zile se termină în 13–15 secunde. O interogare `list_authority_contracts` pentru o autoritate medie (≤50 contracte) se termină sub 10 secunde. Join-urile cu datele de câștigător adaugă ~100ms per contract.

#### Exemplu real: cheltuielile Ministerului Sănătății în 2025

Output real al `list_authority_contracts({authority_cui: "4266456", year: 2025})`:

```
Valoare atribuită totală:  115 932 117 RON pe 35 de contracte
Furnizori unici:           29
Contract mediu:            3,3M RON

Top 5 furnizori (66% din cheltuielile totale):
  1. Shimadzu Handelsgesellschaft mbH (ATU 18379608)    27,2M RON, 2 contracte
  2. BIOMEDICA MEDIZINPRODUKTE ROMANIA (RO 31101676)    15,6M RON, 4 contracte
  3. ANALYTIK-JENA-ROMANIA S.R.L. (RO 11795620)         14,5M RON, 1 contract
  4. CANBERRA PACKARD (RO 7012045)                      11,0M RON, 1 contract
  5. MECRO SYSTEM S.R.L. (RO 431712)                     8,0M RON, 1 contract
```

Cost total al acestei analize: **~$2.10**. Timp de răspuns: ~5 secunde.

Acesta este genul de interogare pe care jurnaliștii, ONG-urile anti-corupție și echipele de inteligență concurențială o rulează zilnic. Date deschise făcute utilizabile.

#### Limitări cunoscute

Să fim oneşti din start:

- **Datele despre câștigători pentru achiziții directe sunt în înregistrarea principală** (furnizorii sunt pre-desemnați), dar **achizițiile directe nu au înregistrări de contract separate**: valoarea de pe rândul licitației ESTE valoarea finală atribuită. Pentru metadate structurate despre contracte (număr contract, dată), acestea există doar pentru licitațiile peste-prag.

- **SEAP limitează răspunsurile la 2 000 achiziții directe / 3 000 licitații publice per interogare.** Interogările foarte largi (fără CPV, fără autoritate, interval mare) ating această limită. Îngustează cu CPV, cuvânt cheie sau autoritate, sau împarte în intervale mai mici.

- **Intervalul optim de date este 3–14 zile.** SEAP setează un flag `searchTooLong` la interogări largi; Actor-ul procesează corect răspunsul dar rezultatele pot fi trunchiate la limita serverului. Folosește intervale mai înguste pentru acoperire completă.

- **Unele contracte istorice (2022 și mai vechi) returnează `null` la `contract_value_ron`.** Acest lucru reflectă datele SEAP, nu o problemă de parsare. Contractele moderne (2024+) sunt populate în >99% din cazuri.

- **Mod backfill acoperă doar licitațiile peste-prag (2007–2018).** Arhiva `istoric.e-licitatie.ro` nu conține achiziții directe: acestea au fost formalizate prin Legea 98/2016 și nu au fost populate retroactiv. Înregistrările peste-prag din arhivă au date despre câștigători (CUI + denumire + valoare contractată), dar dataset-ul este static, util pentru analiză istorică, nu pentru monitorizare concurențială activă.

- **CUI-ul autorității trebuie să fie un CUI de autoritate contractantă înregistrată în SEAP**, nu orice cod fiscal românesc. Unealta `list_authority_contracts` returnează `CA_NOT_FOUND` pentru CUI-uri neînregistrate.

#### Sursa datelor și aspecte legale

Datele provin de pe portalul oficial de achiziții publice [e-licitatie.ro](https://e-licitatie.ro) sub **Licența pentru Guvernare Deschisă v1.0**, stabilită prin Legea 98/2016 (Codul achizițiilor publice din România). Datele sunt publice prin lege; acest Actor le împachetează pentru consum mașinal.

Uneltele analitice MCP (informații despre câștigători, praguri de preț CPV, praguri pe autoritate, detecția neregularităților) folosesc și corpusul de date deschise [data.gov.ro](https://data.gov.ro). Resursele-sursă sunt publicate fie sub Creative Commons Attribution 4.0 (CC BY 4.0), fie sub UK Open Government Licence v3.0 (OGL v3.0, compatibilă CC-BY-4.0); analizele derivate sunt redistribuite uniform sub [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/).

**Procesare GDPR:**

- Numele, emailurile și telefoanele persoanelor responsabile de achiziții sunt eliminate din output.
- CUI-urile și numele autorităților contractante și ale furnizorilor sunt informații publice din registru și sunt păstrate. De regulă sunt persoane juridice; dacă un furnizor este înregistrat ca PFA / întreprindere individuală (ÎI) / familială (IF), denumirea sa este numele unei persoane fizice, păstrată ca dată din registru public.
- Nu sunt reținute date cu caracter personal în key-value stores Apify dincolo de durata unei singure rulări.

#### Confidențialitate & date personale

apnoda-daas este operator de date; Apify, Cloudflare și Hetzner sunt împuterniciți (art. 28 RGPD). Controalele de confidențialitate sunt arhitecturale, nu improvizate per sursă:

- **Eliminarea PII** se face la momentul preluării, înainte de stocare: CNP-ul, datele de contact și adresa de domiciliu sunt eliminate. Output-ul conține de regulă date de persoane juridice (CUI + denumire); excepție fac furnizorii înregistrați ca PFA / ÎI / IF, a căror denumire este numele unei persoane fizice, păstrat ca informație din registru public. Vezi secțiunea GDPR de mai sus.
- **Evaluare de impact (DPIA)** depusă pentru infrastructura SEAP.
- **Registru de prelucrări (ROPA)** menținut conform art. 30.
- **Retenție documentată:** arhiva R2 SEAP 7 ani (Legea 98/2016); cache-ul operațional Postgres maximum 100 de zile.
- **Cereri ale persoanelor vizate (DSR):** scrie la `privacy@apnoda.com`: răspuns în 30 de zile (art. 12 alin. (3) RGPD).
- **Notă de informare publică:** [apnoda.com/privacy](https://apnoda.com/privacy).

#### Fiabilitate

- **Backup Postgres** la fiecare 6 ore, cu retenție de 7 zile în Cloudflare R2 (criptat AES-256).
- **Exercițiu de recuperare în caz de dezastru (DR drill)** bilunar; ultimul reușit 2026-05-17, următorul programat 2026-07-17.
- Infrastructura (orchestrator + Postgres + R2) este permanentă, nu „șterge-și-reconstruiește".

#### Transparență privind utilizarea platformei

Calea MCP rulează în mod standby pe Apify.

- **Memorie standby:** 1024 MB (RSS de vârf măsurat ~96 MB, marjă confortabilă).
- **Profil de latență (warm), p50 / p95** (măsurat 2026-06-24 împotriva URL-ului standby de producție, N=30 per categorie):
  - citiri din cache (majoritatea uneltelor): 761 / 830 ms
  - căutare semantică: 694 / 810 ms
  - `rank_entities` (analitică): 925 / 984 ms
  - cold-spawn (primul apel după inactivitate prelungită): ~8900 ms (provizionare container Apify + pornire Node; afectează doar primul apel)
- **Calcul de platformă:** absorbit în prețul pe eveniment, fără taxe ascunse. Facturarea standby este bazată pe timp: containerul rămâne activ ~5 minute între apeluri (coada de inactivitate), deci costul dominant este timpul de standby în timp real, nu apelul activ de sub o secundă.

> Cifrele de mai sus au fost măsurate pe 2026-06-24 rulând benchmark-ul din `docs/latency-benchmark-2026-05-28.md` împotriva URL-ului standby de producție.

#### Suport

- **Probleme sau întrebări:** folosește formularul de contact Apify de pe pagina acestui Actor, sau raportează probleme via sistemul de issue-uri al platformei Apify.
- **Alți Actori:** explorează [profilul apnoda](https://apify.com/apnoda) pentru instrumente de date birocratice și de reglementare din România/CEE.

#### Întrebări frecvente

**Î: Datele sunt în timp real?**
R: Reflectă starea SEAP la momentul rulării. Actualizările apar predominant între 08:00 și 18:00, ora României.

**Î: Pot folosi datele într-un produs comercial pe care îl vând?**
R: Da, sub OGL v1.0, datele sunt publice prin lege. Nu poți revinde datele brute ca un competitor al API-ului SEAP.

**Î: Cât de des este actualizat Actor-ul?**
R: Menținut activ. Corecții de erori și adaptări la schimbările API SEAP în maxim 72 de ore pentru utilizatorii activi. Cereri de funcționalități noi via formularul de contact Apify.

**Î: Care e diferența dintre datele „cache" și „live"?**
R: Uneltele MCP analitice citesc dintr-un strat Postgres în cache (fereastra recentă de ≤90 de zile este colectată la aproximativ 30 de minute; arhiva istorică de peste 90 de zile se reconstruiește săptămânal). Fiecare răspuns poartă metadate de prospețime (`freshness_tier`, `lag_minutes`, `is_stale`, `data_max_scraped_at`), deci agentul tău știe cât de proaspete sunt datele și ce strat le-a servit. Rularea de tip dataset cu `mode: "live"` interoghează SEAP direct, în timp real.

**Î: Cum îmi controlez cheltuielile?**
R: Plată pe rezultat, plătești per înregistrare emisă sau per apel MCP reușit, fără abonament. Setează limite de cheltuieli per rulare și lunare în Apify Console. Filtrele înguste (CPV, autoritate) și modul `alert_check` (un singur `tender_alert_digest` pe zilele cu schimbări) țin costul mic.

**Î: Ce se întâmplă dacă SEAP își schimbă formatul de date?**
R: Un „shape sentinel" validează forma înregistrărilor din amonte la fiecare câteva ore; abaterile (drift) sunt detectate și remediate în maxim 72 de ore pentru utilizatorii activi, înainte să corupă output-ul.

*Versiunea 2.0 · Actualizat mai 2026*

***

### English

**Romanian government tenders as structured data for AI agents and developers.** Live + historical, sub-threshold + above-threshold, with winner intelligence joined. MCP-native, pay-per-record, no subscription.

> 🤖 **Agentic-payments ready:** x402 (automatic for any pay-per-event Actor).

#### What this Actor does

Fetches Romanian public procurement notices from [e-licitatie.ro](https://e-licitatie.ro) (SEAP/SICAP) and returns them as normalized, PII-stripped JSON records, enriched with Romanian sector taxonomy, CUI-parsed contracting authorities, and joined winner data on awarded notices.

Covers two tender tiers:

- **Sub-threshold direct acquisitions** (*achiziții directe*): small-scale purchases (under ~€140k services / €5.5M works) published only on SEAP. This is the Romanian SMB sweet spot and **is not in EU TED**. Roughly 10 000 notices per week.
- **Above-threshold public tenders** (*licitații publice*): larger procurements, also published to EU TED. Roughly 1 500 notices per week with winner intelligence joined post-award.

Total addressable firehose: ~11 500 Romanian public procurement notices per week. You pay only for records matching your filters.

#### Why use this Actor

Three buyer profiles:

**For AI-agent developers:** MCP-native from day one. Connect via `mcp.apify.com?tools=apnoda/seap-sicap-tenders` and your agent has **14 tools**: name-to-CUI resolution, search, detail, supplier/authority profiles, price benchmarking, irregularity flags, framework agreements, supplier comparison, semantic search, rankings, and a free coverage check (full list below). No subscriptions, no API keys, no infrastructure.

**For developers building procurement tools:** SEAP's undocumented JSON API is painful to work with directly: quirks around `searchTooLong` caps, `showOngoingDa` dispatch, state-machine semantics, missing server-side filters. This Actor abstracts them. Output is stable and typed.

**For analysts and journalists:** One-shot queries by CUI, CPV, keyword, date range, value. Export to CSV. Pay cents per query. No account with a Romanian SaaS required.

#### Try it now

1. **Click "Try for free"**, runs with the default inputs (CPV 45, construction, last 7 days), up to 50 records.
2. **Export as CSV** and open in Excel / Google Sheets.
3. **OR** connect via MCP and ask Claude in natural language (see next section).

The default caps the first run at 50 records, so it costs under $5, fully covered by Apify's $5 signup credit. Raise "Maximum results" for full coverage.

#### Quick comparison

| Capability | This Actor | sicap.ai (Free) | sicap.pro | DataDriven.ro | TED Apify Actors |
|---|---|---|---|---|---|
| Sub-threshold direct acquisitions | ✅ | ✅ | ✅ | ✅ | ❌ TED omits them |
| Winner intelligence | ✅ in output | ✅ in UI | ✅ in UI | ✅ in UI | partial |
| Public developer API | ✅ | ❌ | ❌ | ❌ | ✅ |
| MCP / AI-agent access | ✅ | ❌ | ❌ | ❌ | some |
| Programmatic filters | ✅ | ❌ | ❌ | ❌ | ✅ |
| Email alerts | ✅ via Apify Schedules + Gmail | ❌ | ✅ | ✅ | ❌ |
| Raw CSV/JSON export | ✅ | ❌ | limited | limited | ✅ |
| Framework-agreement tracking (acord-cadru) | ✅ | ❌ | ❌ | ❌ | ❌ |
| Irregularity flags | ✅ | ❌ | ❌ | ❌ | ❌ |
| Semantic search (embeddings) | ✅ | ❌ | ❌ | ❌ | ❌ |
| Agentic payments (x402) | ✅ | ❌ | ❌ | ❌ | ❌ |
| Pricing model | pay-per-record | free | annual subscription | monthly subscription/user | varies |

This Actor's niche: **programmatic access to SEAP data, via MCP, API, or CSV, with no subscription and no account.** The same data is available on other Romanian tender-monitoring platforms (web UI, email alerts, monthly/annual subscriptions). The difference: we deliver raw, via API or MCP, pay-per-use only. For integration into your own code, AI agents, or one-shot analyses, this Actor.

⚠️ **This Actor does NOT provide directly:**

- Automatic "new tenders only" detection (Pattern 2 in the Scheduling section covers ~80% of cases; for strict diff, see Pattern 3)
- Visual team UI (data is accessed via API, MCP, or Apify dataset)
- OCR for attached PDF documents (tender metadata only)

#### MCP-first usage

Connect Claude Desktop (or any MCP client) by adding this to your config:

```json
{
  "mcpServers": {
    "romanian-tenders": {
      "url": "https://mcp.apify.com?tools=apnoda/seap-sicap-tenders"
    }
  }
}
```

Now ask Claude things like:

- *"What construction tenders were published in Romania last week above 500,000 RON?"* (`search_romanian_tenders`)
- *"Get the full detail and winner for tender SCNA1128899."* (`get_tender_detail`)
- *"List the contracts Ministerul Sănătății signed in 2025 with their top suppliers."* (`list_authority_contracts`)
- *"What has Alliance Healthcare won in Romanian public procurement?"* (`get_winner_profile`)
- *"How concentrated is Primăria Cluj-Napoca's supplier base?"* (`analyze_authority_spending`)
- *"Is 2 million RON a normal price for CPV 4533 works?"* (`benchmark_cpv_pricing`)
- *"Any red flags for buyer CUI 4266456?"* (`detect_irregularities`)
- *"Which framework agreements for CPV 33 are the most consumed?"* (`framework_agreement_lookup`)
- *"Are suppliers 8955860 and 12345678 competing for the same buyers?"* (`compare_winners`)
- *"Find tenders similar to SCNA1128899."* (`find_similar_tenders`)
- *"Find tenders about asphalting county roads."* (`search_by_natural_description`)
- *"Top 3 winners in Cluj in 2024."* (`rank_entities`)
- *"What's the CUI for Primăria Cluj-Napoca?"* (`resolve_entity`)
- *"How many live tenders are in the dataset, and how fresh is it?"* (`get_seap_coverage`, free)

Claude picks the right tool, calls it, and answers. You pay per record returned, not per query.

##### Available MCP tools (14)

All 14 tools are exposed over MCP. Calls are billed $0.05 per successful call (`mcp_tool_request`), except `get_seap_coverage`, which is free (fires no event); `detect_irregularities` additionally bills $0.10 per flag returned.

| Tool | What it does |
|---|---|
| **`search_romanian_tenders`** | Filter by CPV code, keyword, date range, tier, value range, authority CUI, county (județ), framework-only, single-bidder, winner CUI (competitor tracking: only tenders won by the listed suppliers). Sub-threshold rows carry winner CUI inline; above-threshold awarded rows are marked `winner_lookup_required: true` for chaining into the detail tool. |
| **`get_tender_detail`** | One tender by `sicap_id` with all contracts and winner intelligence joined. Handles all notice-code prefixes (DA, CAN, CN, SCN, SCNA). |
| **`list_authority_contracts`** | Awarded contracts for a CUI in a given year + pre-computed aggregates (total spend, unique suppliers, top 5 by value). |
| **`get_winner_profile`** | A supplier's procurement profile by CUI: win history, total values, recent tenders. |
| **`analyze_authority_spending`** | A public authority's spending: total, concentration (HHI), top suppliers, Romanian-language narrative. |
| **`benchmark_cpv_pricing`** | Price benchmarks for a CPV category: median, IQR, P5/P95, breakdown by județ. |
| **`detect_irregularities`** | Rule-based irregularity flags: single bidder, abnormal price, repeated sole-source, modification value bloat. |
| **`framework_agreement_lookup`** | SEAP framework agreements (acord-cadru) with consumption + child-contract rollups. |
| **`compare_winners`** | Head-to-head analysis between two Romanian suppliers. |
| **`find_similar_tenders`** | Tenders semantically similar to a source tender (e5-small embedding). |
| **`search_by_natural_description`** | Free-text semantic search over tenders (Romanian or English). |
| **`rank_entities`** | Top-N across winners, buyers, CPV codes, or județe by a chosen metric. |
| **`resolve_entity`** | Look up a company or authority CUI by name (buyers + suppliers). Start here when you have a name, not a CUI, then feed the result into the CUI-keyed tools. |
| **`get_seap_coverage`** (free) | Corpus size (live tender counts by tier, supplier/authority profiles, framework agreements) plus a freshness watermark for both substrates. No arguments, no charge. Check coverage and currency before calling a paid tool. |

**A few load-bearing details** (also carried in each tool's response, so an agent gets them at call time too):

- `framework_agreement_lookup`: `consumed_pct` can exceed 100. Romanian frameworks routinely over-consume their announced ceiling, and that over-consumption is the signal, so it is never clamped to 100.
- `benchmark_cpv_pricing`: percentiles (P5/P25/median/P75/P95) and stddev populate only for a single-source row (a 4/6/8-digit CPV with a specific year); a 2-digit prefix or a multi-year roll-up returns them as null. `min`, `max`, and the weighted `mean` stay populated.
- `detect_irregularities`: each surfaced flag is metered individually, so a maximally-flagged buyer or supplier sweep costs proportionally more; a clean result (`flags: []`) meters no per-flag charge.

##### MCP prompts (guided workflows)

Three ready-made analysis workflows are exposed as MCP prompts (each with a Romanian name and an English alias, six registered names in total). Your MCP client lists them as slash-commands or templates; you fill the arguments and the prompt expands into a multi-step routine that calls the tools above in order.

| Prompt (RO / EN alias) | Arguments | What it does |
|---|---|---|
| `due-diligence-autoritate-contractanta` / `due-diligence-buyer` | `authority_cui`, `year` | Buyer due-diligence routine: spend profile, supplier concentration, an irregularity sweep, and top contracts for one authority. |
| `analiza-oportunitate-licitatie` / `tender-opportunity-analysis` | `tender_id`, `my_supplier_cui` (optional) | Sizes one tender as an opportunity: full detail, category price benchmark, similar tenders, and (when a supplier CUI is given) a fit read. |
| `profil-ofertant-castigator` / `supplier-winner-profile` | `supplier_cui`, `lookback_years` (optional, default 3) | Supplier win-history profile: totals, buyer/CPV breadth, recent awards, and a head-to-head against comparable suppliers. |

##### MCP resources (reference data)

Four read-only reference datasets are exposed as MCP resources; an agent can read them to resolve codes and vocabulary without spending a tool call.

| Resource URI | What it is |
|---|---|
| `cpv://tree` | CPV 2008 hierarchy: 9,454 codes (45 root divisions) with RO+EN labels and the 9-sector Romanian rollup. |
| `nuts://ro` | The 41 Romanian județe plus Bucharest, with NUTS3 codes and the NUTS2 rollup. |
| `glossary://ro-procurement` | A ~130-term bilingual (RO/EN) glossary of Romanian public-procurement vocabulary, referenced to Law 98/2016 and Law 99/2016. |
| `thresholds://ro-2026` | Law 98/2016 + 99/2016 procurement thresholds in EUR and RON, with effective dates. |

#### Apify usage (non-MCP)

Standard Actor run. Configure inputs, start, collect dataset results.

```json
{
  "mode": "live",
  "tiers": ["sub_threshold", "above_threshold"],
  "publicationDateStart": "2026-04-17",
  "publicationDateEnd": "2026-04-24",
  "cpvCodes": ["45"],
  "minValueRon": 100000,
  "acquisitionStatus": "ongoing",
  "maxResults": 1000
}
```

Output lands in a standard Apify dataset. Export as JSON, CSV, or XLSX.

Historical mode (2007–2018 archive via `istoric.e-licitatie.ro`) available by setting `mode: "backfill"`. **Above-threshold only.** The sub-threshold archive is empty on `istoric.e-licitatie.ro` because Law 98/2016 formalized achiziții directe after the archive window. Lower per-record price reflects lower commercial value of historical data.

#### Pre-built Task templates

Five ready-to-use configurations covering the most common scenarios. **Copy the input JSON** into a new Task in Apify Console (Actor → `Saved tasks` tab → `Create new task` → paste into the `Input` field), then attach a Schedule with the recommended cadence. All but #5 use `alert_check` mode, which structurally dedupes across runs, you only get NEW or MODIFIED records since the last run.

**1. Construction in Cluj county, daily 7:00 EET**

Local construction buyers (roads, buildings, refurbishment) headquartered in Cluj county. Recommended cadence: daily 07:00 EET.

```json
{
  "mode": "alert_check",
  "tiers": ["sub_threshold", "above_threshold"],
  "cpvCodes": ["45"],
  "judet": ["Cluj"],
  "alertTypes": []
}
```

**2. IT & software services in Bucharest, twice daily**

IT procurement (consulting, software development, integration) at the capital-city level. Recommended cadence: 06:00 and 14:00 EET.

```json
{
  "mode": "alert_check",
  "tiers": ["sub_threshold", "above_threshold"],
  "cpvCodes": ["72"],
  "judet": ["Bucuresti"],
  "alertTypes": []
}
```

**3. Active medical framework agreements, weekly**

Active framework agreements (CPV 33, medical equipment, drugs, devices). Excludes direct acquisitions, which are never framework agreements by construction. Recommended cadence: Monday 08:00 EET.

```json
{
  "mode": "alert_check",
  "tiers": ["above_threshold"],
  "cpvCodes": ["33"],
  "frameworkOnly": true,
  "alertTypes": []
}
```

**4. Amendments only, daily**

Notifies only when an existing tender is AMENDED (errata or version-counter incremented). Useful for monitoring changes on tenders you're already tracking. Recommended cadence: daily 09:00 EET.

```json
{
  "mode": "alert_check",
  "tiers": ["above_threshold"],
  "alertTypes": ["AMENDED"]
}
```

**5. Single-bidder audit for one authority, on demand**

Run on demand when you want to see every awarded tender that had exactly one bidder for a target authority (e.g. a city hall with an unusually high single-bidder rate). Replace `4266456` with the authority's CUI. Heuristic: `highestOfferValue === lowestOfferValue` with both non-null and non-zero.

```json
{
  "mode": "live",
  "tiers": ["above_threshold"],
  "acquisitionStatus": "with_winners",
  "authorityCui": ["4266456"],
  "singleBidder": true
}
```

**Operational notes:**

- `judet` resolves county names case- and diacritic-insensitively; `Cluj` / `CLUJ` / `cluj` and `București` / `Bucuresti` all match identically.
- `frameworkOnly` excludes `sub_threshold` automatically (direct acquisitions are bilateral by construction, never framework agreements).
- `alertTypes` filters what we emit to the dataset; alert\_state is updated for every matched record, so widening the filter later does NOT replay historical records as NEW.
- **Changing `judet` / `frameworkOnly` / `singleBidder` mints a fresh alert\_state slice**, so the next run will re-fire EVERY matched record as NEW. This is by design, different judet / framework / single-bidder sets are different saved searches. If you want dedup across these filter variants, create separate Tasks.
- Task #5 does not dedupe across runs (it's `live` mode); run on demand when you need a snapshot.

#### Scheduled runs with email delivery

To receive new tenders by email automatically, with no code or third-party services:

**Pattern 1, Daily snapshot (recommended for most users)**

1. Configure an **Apify Schedule** that runs this Actor daily at 09:00 (Europe/Bucharest, DST-aware).
2. Enable the **Gmail integration** on the Actor's Integrations tab. Direct OAuth to Google; the dataset attaches automatically as CSV/JSON.
3. Each morning, you receive an email with all tenders matching your filters (CPV, authority, etc.).

Monthly cost: one daily run on CPV 45 = ~$2.70/month. No infrastructure to maintain.

**Pattern 2, Yesterday's tenders only**

Same configuration as Pattern 1, but set `publicationDateStart: yesterday` + `publicationDateEnd: yesterday` in the scheduled input. You'll only receive what was published in the last 24 hours, the "alert for new things" effect with no additional code.

**Pattern 3, Change detection (advanced)**

For "email me ONLY when something new appeared compared to the previous run," configure a second downstream Actor that diffs against the previous dataset. Possible but requires custom code.

**Pattern 4, `alert_check` mode (subscription replacement)**

Set `mode: "alert_check"` in input alongside your usual filters (CPV, authority, keywords, value range). The Actor diffs against your per-customer alert state (per `(user_id, task_id, filter)`) and writes one record per delta to the run's `alerts-<run_id>` named dataset. Detected types: `NEW`, `MODIFIED`, `AWARDED`, `AMENDED`, `EXTENDED`, `CANCELLED`. Billing: a single `tender_alert_digest` event ($0.49 flat across all plans) per run that produced ≥1 delta, **the digest event is never charged on zero-delta runs** (the "no empty digest" guarantee). The `actor_start` event ($0.01) applies to every run regardless of mode. Net result: a daily schedule on a stable filter typically costs ~$0.01 baseline on no-change days plus $0.49 only on delta days, vs ~$0.06 × total-records-in-window per Pattern 2 run.

Apify documentation: [Schedules](https://docs.apify.com/platform/schedules), [Webhooks](https://docs.apify.com/platform/integrations/webhooks), [Gmail integration](https://docs.apify.com/platform/integrations/gmail).

#### No-code integration recipes

Push tenders into the tools your team already uses, with no code. Apify is the trigger and the data source; a no-code platform (Make, Zapier, or n8n) reads the finished run's dataset and fans each row out to Google Sheets, Slack, email, or anywhere else.

Every recipe is the same three steps:

1. **Trigger on the finished run.** Zapier: "Finished Task Run". Make: "Watch Task Runs". n8n: the Apify node's "Task Run Finished" event.
2. **Get the rows.** The dataset-items step: Make and n8n call it "Get Dataset Items", Zapier calls it "Fetch dataset items" (a Search). Which dataset you read depends on the mode (see below).
3. **Send each row** to the destination: Google Sheets "Create Spreadsheet Row", Slack "Send a message", etc.

**Which dataset to read.** A `live` (or `backfill`) run writes matching tenders to the run's **default dataset**, whose `defaultDatasetId` is in the trigger payload, so you point step 2 straight at it. An `alert_check` run is different: it writes the change deltas to a **named dataset**, while the payload's `defaultDatasetId` points at the (empty) default dataset, not the deltas. Reference the named dataset by name: **`<your-apify-username>~alerts-<RUN_ID>`** (your Apify username, then the run ID from the payload; the dataset is created under your account when the Task runs). A bare `alerts-<RUN_ID>` is read as a dataset ID, is not one, and returns nothing, so the `username~` prefix is required. Once the reference resolves, that named dataset exists on every run and is simply empty on no-change days, so the recipe does nothing on quiet days rather than erroring. In an `alert_check` delta each tender sits under a `current` object (map `current.title_ro`, `current.primary_winner_name`, and so on), alongside a top-level `alert_type`.

**Recipe 1: new tenders to a Google Sheet, deduped.** One row per genuinely new tender, no repeats, using `alert_check` so an overlapping date window never double-writes.

Saved-Task input:

```json
{
  "mode": "alert_check",
  "tiers": ["sub_threshold", "above_threshold"],
  "cpvCodes": ["45"],
  "alertTypes": ["NEW"]
}
```

Wiring: "Finished Task Run" trigger, then the dataset-items step (step 2) reading `<your-apify-username>~alerts-<RUN_ID>`, then Google Sheets "Create Spreadsheet Row" mapping `current.title_ro`, `current.authority_name`, `current.value_ron`, `current.cpv_code`, `current.url`. Schedule the Task daily; each new construction tender lands as one Sheet row, once.

**Recipe 2: awarded tenders to Slack.** Post to `#tenders` only when a tracked tender is actually awarded (its winner transitions from empty to set), with no repeats.

Saved-Task input:

```json
{
  "mode": "alert_check",
  "tiers": ["above_threshold"],
  "cpvCodes": ["45"],
  "alertTypes": ["AWARDED"]
}
```

Wiring: "Finished Task Run" trigger, then the dataset-items step (step 2) reading `<your-apify-username>~alerts-<RUN_ID>`, then Slack "Send a message" per item, e.g. *"Awarded: {{current.title\_ro}} to {{current.primary\_winner\_name}} for {{current.contract\_value\_ron}} RON. {{current.url}}"*. AWARDED fires on above-threshold records only, once per award.

**Cost.** Both recipes run in `alert_check`, so they follow the `alert_check` economics described above: `actor_start` ($0.01) fires on every run, and a change day adds a single `tender_alert_digest` ($0.49) on top, so a quiet day is ~$0.01 and a change day ~$0.50, independent of how many rows match. On a busy filter that is much cheaper than per-record live emits.

**Without a no-code platform.** For a one-shot snapshot to a sheet, run `live` mode and chain the [Google Sheets Import & Export actor](https://apify.com/lukaskrivka/google-sheets) on a run-finished [webhook](https://docs.apify.com/platform/integrations/webhooks), passing the finished run's default dataset ID. Native [Google Drive delivery](https://docs.apify.com/platform/integrations/drive) (the dataset dropped into a Drive folder as a file) needs no third-party tool at all.

Integration guides: [Zapier](https://docs.apify.com/platform/integrations/zapier), [Make](https://docs.apify.com/platform/integrations/make), [n8n](https://docs.apify.com/platform/integrations/n8n).

#### What you get

Every record includes:

```json
{
  "sicap_id": "SCNA1128899",
  "tier": "above_threshold",
  "cpv_code": "45331100-7",
  "cpv_label_ro": "Lucrări de instalare de echipamente de încălzire centrală",
  "sector_ro": "construcții",
  "authority_cui": "2351555",
  "authority_name": "Regia Autonomă Administrația Patrimoniului Protocolului de Stat",
  "authority_judet": "Bucuresti",
  "title_ro": "Lucrări de înlocuire a unui cazan de pardoseală...",
  "value_ron": 255012.86,
  "contract_value_ron": 260000,
  "publication_date": "2026-04-17T10:15:34+03:00",
  "finalization_date": "2026-04-24T11:20:00+03:00",
  "state": "Atribuita",
  "primary_winner_cui": "RO34649836",
  "primary_winner_name": "DAV CLIMA SYSTEM",
  "winners": [{"cui": "RO34649836", "name": "DAV CLIMA SYSTEM"}],
  "winner_cuis_joined": "RO34649836",
  "url": "https://e-licitatie.ro/pub/..."
}
```

Winner intelligence is present on sub-threshold records from state 2 onward (suppliers are pre-designated for achiziții directe) and on above-threshold records post-award (contract join).

#### Cost calculator

**Pricing:**

- Actor start: $0.01
- Per emitted tender (live mode): **$0.06**
- Per backfill tender (historical archive): $0.008
- Alert digest (`alert_check` mode): $0.49 flat per run with ≥1 delta (zero-delta runs are never charged)
- MCP tool call (any tool): $0.05 flat per successful call (validation errors / structured tool errors / unhandled handler exceptions are not charged)
- Irregularity flag (`detect_irregularities`): $0.10 per Flag returned (calls returning zero flags are not charged)

> **Note**, the three newer events (`tender_alert_digest`, `mcp_tool_request`, `irregularity_flag`) go through Apify's monthly pricing-change review queue. Until approved, charge attempts are recorded but no invoice item is produced (the Apify SDK logs `Ignored attempt to charge for an event`). The prices listed here are the post-approval final rates.

Platform/compute costs are absorbed in the event price, you see no hidden charges.

**Real-world examples:**

| Use case | Query | Records/week | Weekly cost |
|---|---|---|---|
| Monitor all Romanian construction tenders (CPV 45) | cpv\_codes: `["45"]`, 7-day window | ~320 | **~$19** |
| Medical + IT procurement monitoring (CPV 33 + 72) | cpv\_codes: `["33", "72"]`, above-threshold only | ~400 | **~$24** |
| Track all tenders by a specific ministry | authority\_cui: `"4266456"` | ~7 | **~$0.50** |
| Monitor 3 CPV categories + 2 authorities | cpv\_codes + authority\_cui filters | ~800 | **~$48** |
| One-shot annual authority spend analysis | list\_authority\_contracts(CUI, year) | ~35 contracts | **~$2** |

Narrower CPV filters + authority filters give the best cost/signal ratio. For broad coverage, run multiple filtered queries and union the results, SEAP caps each response at 2 000 / 3 000 records per query (see limitations).

**Latency:** A 7-day CPV-filtered search returns in 13–15 seconds. A `list_authority_contracts` query for a mid-size authority (≤50 contracts) completes in under 10 seconds. Winner intelligence joins add roughly 100ms per contract fetched.

#### Real example: Ministerul Sănătății 2025 spend

Actual output of `list_authority_contracts({authority_cui: "4266456", year: 2025})`:

```
Total awarded:        115 932 117 RON across 35 contracts
Unique suppliers:     29
Average contract:     3.3M RON

Top 5 suppliers (66% of total spend):
  1. Shimadzu Handelsgesellschaft mbH (ATU 18379608)     27.2M RON, 2 contracts
  2. BIOMEDICA MEDIZINPRODUKTE ROMANIA (RO 31101676)     15.6M RON, 4 contracts
  3. ANALYTIK-JENA-ROMANIA S.R.L. (RO 11795620)          14.5M RON, 1 contract
  4. CANBERRA PACKARD (RO 7012045)                       11.0M RON, 1 contract
  5. MECRO SYSTEM S.R.L. (RO 431712)                      8.0M RON, 1 contract
```

Cost of this entire analysis: **~$2.10**. Time to return: ~5 seconds.

This is the kind of query that journalists, anti-corruption NGOs, and competitive-intelligence teams run daily. Open data made useful.

#### Known limitations

Being honest up front:

- **Sub-threshold winner data is inline on every record** (suppliers are pre-designated in achiziții directe), but **sub-threshold contracts have no separate "contract" record**: the value on the tender row IS the final awarded value. If you want structured contract metadata (contract number, date), that only exists for above-threshold tenders.

- **SEAP caps responses at 2 000 sub-threshold / 3 000 above-threshold per query.** Very broad queries (no CPV, no authority, long date window) hit this cap. Narrow by CPV, keyword, or authority, or split into smaller time windows.

- **Optimal date window is 3–14 days.** SEAP sets a `searchTooLong` flag on broad queries; the Actor still processes them correctly but results may be truncated at the server cap. Use narrower windows for complete coverage.

- **Some historical contracts (2022 and earlier) return `null` on `contract_value_ron`.** This reflects SEAP's own data, not a parsing issue. Modern contracts (2024+) are populated >99% of the time.

- **Backfill mode covers above-threshold only (2007–2018).** The `istoric.e-licitatie.ro` archive contains no sub-threshold records: achiziții directe were formalized by Law 98/2016 and never backfilled into the historic service. Historical above-threshold records do carry winner intelligence (CUI + name + contract value), but the dataset is static, useful for historical analysis, not for competitive monitoring.

- **Authority CUI must be a SEAP-registered contracting authority**, not an arbitrary Romanian tax code. The `list_authority_contracts` tool returns `CA_NOT_FOUND` for unregistered CUIs.

#### Data source and legal

Data is sourced from the official Romanian public procurement portal [e-licitatie.ro](https://e-licitatie.ro) under **Licența pentru Guvernare Deschisă v1.0** (Open Government License), established under Law 98/2016 (the Romanian public procurement code). The data is public by statute; this Actor packages it for machine consumption.

The analytical MCP tools (winner intelligence, CPV price baselines, authority baselines, irregularity detection) also draw on the [data.gov.ro](https://data.gov.ro) open-data corpus. Those source resources ship under either Creative Commons Attribution 4.0 (CC BY 4.0) or the UK Open Government Licence v3.0 (OGL v3.0, which is CC-BY-4.0-compatible); the derived analytics are redistributed uniformly under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/).

**GDPR handling:**

- Procurement officer personal names, emails, and phone numbers are stripped from output.
- Contracting authority and supplier CUIs + names are public record and retained. They are usually legal entities; if a supplier is registered as a sole trader (PFA / ÎI / IF), its registered name is a natural person's name, retained as public-register data.
- No PII is retained in Apify key-value stores beyond a single run's lifetime.

#### Privacy & personal data

apnoda-daas is the data controller; Apify, Cloudflare, and Hetzner are Article 28 processors. The privacy controls are architectural, not per-source improvisation:

- **PII stripping** happens at scrape time, before storage: CNP, contact details, and home address are removed. Output is usually legal-entity data (CUI + name); the exception is suppliers registered as sole traders (PFA / ÎI / IF), whose registered name is a natural person's name, retained as public-register data. See the GDPR section above.
- **Data Protection Impact Assessment (DPIA)** on file for the SEAP infrastructure.
- **Records of Processing Activities (ROPA)** maintained under Art. 30.
- **Documented retention:** SEAP R2 archive 7 years (Law 98/2016); operational Postgres cache at most 100 days.
- **Data Subject Requests (DSR):** write to `privacy@apnoda.com`: answered within 30 days (Art. 12(3) GDPR).
- **Public privacy notice:** [apnoda.com/privacy](https://apnoda.com/privacy).

#### Reliability

- **Postgres backup** every 6 hours, with 7-day retention in Cloudflare R2 (AES-256 encrypted).
- **Disaster-recovery (DR) drill** bi-monthly; last successful 2026-05-17, next scheduled 2026-07-17.
- The infrastructure (orchestrator + Postgres + R2) is permanent, never "delete-and-rebuild".

#### Platform-usage transparency

The MCP path runs in Apify standby mode.

- **Standby memory:** 1024 MB (measured peak RSS ~96 MB, comfortable headroom).
- **Warm latency profile, p50 / p95** (measured 2026-06-24 against the production standby URL, N=30 per category):
  - cached reads (most tools): 761 / 830 ms
  - semantic search: 694 / 810 ms
  - `rank_entities` (analytics): 925 / 984 ms
  - cold-spawn (first call after extended idle): ~8900 ms (Apify container provisioning + Node start; affects only the first call)
- **Platform compute:** absorbed in the per-event price, no hidden charges. Standby billing is time-based: the container stays warm for a ~5 minute idle-tail between calls, so the dominant cost is wall-clock standby time, not the sub-second active call.

> The figures above were measured on 2026-06-24 by running the benchmark in `docs/latency-benchmark-2026-05-28.md` against the production standby URL.

#### Support

- **Issues or questions:** use the Apify Store contact form on this Actor's page, or report issues via the Apify platform's built-in issue reporting.
- **Other Actors:** browse the [apnoda profile](https://apify.com/apnoda) for Romanian/CEE bureaucratic data tools.

#### FAQ

**Q: Is the data real-time?**
A: Reflects SEAP's state at the moment of the run. Updates are primarily between 08:00 and 18:00 Romania time.

**Q: Can I use the data in a commercial product I sell?**
A: Yes, under OGL v1.0, the data is public by law. You can't resell raw data as a competing SEAP API.

**Q: How often is the Actor updated?**
A: Actively maintained. Bug fixes and adaptations to SEAP API changes within 72 hours for active users. Feature requests via the Apify contact form.

**Q: What's the difference between "cached" and "live" data?**
A: The analytical MCP tools read from a cached Postgres layer (the recent ≤90-day window is scraped roughly every 30 minutes; the >90-day historical archive rebuilds weekly). Every response carries freshness metadata (`freshness_tier`, `lag_minutes`, `is_stale`, `data_max_scraped_at`) so your agent knows how fresh the data is and which tier served it. A dataset run with `mode: "live"` queries SEAP directly, in real time.

**Q: How do I control spend?**
A: Pay-per-result, you pay per emitted record or per successful MCP call, no subscription. Set per-run and monthly spend limits in Apify Console. Narrow filters (CPV, authority) and `alert_check` mode (a single `tender_alert_digest` on change days only) keep costs low.

**Q: What happens if SEAP changes its data format?**
A: A shape sentinel validates the upstream record shape every few hours; drift is caught and fixed within 72 hours for active users, before it can corrupt output.

*Version 2.0 · Updated May 2026*

***

*Part of the apnoda CEE public-data API portfolio. Romanian public procurement is Actor #1 in a 12-Actor roadmap covering company registries, court records, insolvency gazettes, land registry, and cross-border due diligence across Romania, Hungary, Bulgaria, and Moldova.*

# Actor input Schema

## `mode` (type: `string`):

'live' pulls current data from e-licitatie.ro (maxResults capped at 1 000). 'backfill' pulls the 2007–2018 historical archive from istoric.e-licitatie.ro (maxResults capped at 100 000, priced per backfill\_tender event). Backfill covers the above-threshold tier only, sub-threshold (achiziții directe) was formalized by Romania's Law 98/2016 and was never populated in the historical archive; sub\_threshold passes return zero records under backfill. 'alert\_check' (XP-01) queries the cached seap\_tenders\_hot MV (no live SEAP, no proxy cost) and diffs filter-matched records against the customer's prior alert\_state slice, emitting one delta record per change annotated with alert\_type ∈ {NEW, MODIFIED, AWARDED, AMENDED, EXTENDED, CANCELLED}. Within-Task dedup is structural via the 4-part PK (user\_id, task\_id, filter\_fingerprint, sicap\_id); date window is excluded from the filter\_fingerprint so daily Tasks dedupe across observation windows.

## `tiers` (type: `array`):

Which tender types to include. Sub-threshold = achiziții directe (Romanian SMB sweet spot, not in EU TED). Above-threshold = licitații publice (also mirrored in EU TED). Defaults to sub-threshold only in live and backfill; in alert\_check, omitting this defaults to BOTH tiers so the AWARDED, AMENDED, and EXTENDED alert types (which only fire on above-threshold records) are enabled.

## `acquisitionStatus` (type: `string`):

Which sub-threshold workflow slice to return. 'ongoing' (default) returns every current-era achiziție directă on the live index, sub-threshold buyers pre-designate the supplier, so winner CUI/name/closing-value are populated even on in-flight records. 'with\_winners' narrows to state 7 'Oferta acceptata' (the most-terminal SEAP state observed in 2026) for users who only want offer-accepted records. 'all' is equivalent to 'ongoing' on this endpoint and is kept for forward compatibility. The legacy 'finalized' value is auto-mapped to 'with\_winners' for backwards compatibility.

## `publicationDateStart` (type: `string`):

ISO date (YYYY-MM-DD). Returns tenders published on or after this date. Defaults to 7 days ago. SEAP rejects queries wider than ~90 days with `searchTooLong:true`; use backfill mode for archival pulls.

## `publicationDateEnd` (type: `string`):

ISO date (YYYY-MM-DD). Returns tenders published on or before this date. Defaults to today.

## `finalizationDateStart` (type: `string`):

ISO date (YYYY-MM-DD). Accepted and range-validated for forward compatibility, but NOT currently applied as a filter: the live sub-threshold index does not populate finalization dates (0% populated on the showOngoingDa path), so a finalization-date filter would match nothing. Filter by publication date instead.

## `finalizationDateEnd` (type: `string`):

ISO date (YYYY-MM-DD). Accepted and range-validated for forward compatibility, but NOT currently applied as a filter (see finalizationDateStart). Filter by publication date instead.

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

Common Procurement Vocabulary codes. E.g. 45000000 (construction works), 72000000 (IT services), 33100000 (medical equipment). Prefix matching supported, '451' matches every 451xxxxx code. Empty = all CPVs. Max 50 codes per run; for broader coverage, run multiple filtered queries and union the results.

## `keywordsRo` (type: `array`):

Case-insensitive substring match in the tender title (Romanian); there is no description field to match against. OR between keywords. Max 20 keywords, each up to 100 characters; narrow further by combining with CPV or authority filters. Note: the MCP search tools match keywords with Romanian full-text stemming, this dataset-run filter is plain substring only.

## `authorityCui` (type: `array`):

Romanian tax codes (CUI) of contracting authorities to filter to. Numeric only, do not include the 'RO' VAT prefix. OR between values. Useful for monitoring a specific ministry, city hall, hospital, or state company. Max 100 CUIs per run.

## `minValueRon` (type: `integer`):

Minimum estimated tender value in Romanian Lei.

## `maxValueRon` (type: `integer`):

Maximum estimated tender value in Romanian Lei.

## `includeWinners` (type: `boolean`):

For finalized above-threshold tenders, fetch winner company CUI, name, and awarded value (adds one API call per finalized tender). Sub-threshold winner data is always populated when present (no extra call, F-15a). Strongly recommended for competitor monitoring use cases.

## `enrichWithSector` (type: `boolean`):

Add Romanian sector label (construcții / IT\&C / medical / agricultură / transporturi / consultanță / mobilier / servicii profesionale / utilități) derived from CPV. More useful than raw CPV for filtering.

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

Hard cap on total records returned across all tiers. Prevents runaway costs. Enforced per mode: 1 000 in live, 100 000 in backfill. Requests above the mode cap are clamped at runtime.

## `concurrency` (type: `integer`):

Parallel contract-detail fetches for above-threshold finalized notices. Higher = faster, more load on SEAP. Backfill runs should typically use a lower value to avoid rate-limiting on the historic service.

## `judet` (type: `array`):

Filter to tenders whose contracting authority is registered in one of the listed Romanian counties (județe). Matched case- and diacritic-insensitively, so 'Cluj', 'CLUJ', 'cluj' all resolve identically; 'București' / 'Bucuresti' both match the capital. Coverage is ~98% of CUIs (per IN-06-F-XX-judet Spike 5c), records whose authority CUI is missing from the bundled snapshot are dropped by this filter. Empty = no judet filter. Max 42 entries. NOTE for alert\_check Tasks: changing this filter (e.g. adding a new county) mints a fresh alert\_state slice, so the next run will re-fire every matched record as NEW. This is by design, different judet sets are different saved searches. The alertTypes filter, by contrast, does NOT replay history when changed (it's emit-side only).

## `frameworkOnly` (type: `boolean`):

Limit results to framework agreements (acord-cadru). When true, sub-threshold direct acquisitions are excluded entirely (they are bilateral by construction and never framework). For above-threshold, derived from SEAP's hasSubsequentContracts boolean on the list response, no extra detail fetch. For alert\_check Tasks: toggling this filter mints a fresh alert\_state slice (same fingerprint-replay caveat as judet).

## `singleBidder` (type: `boolean`):

Limit results to tenders received with exactly one bid. Sub-threshold direct acquisitions are inherently single-bidder (the supplier is pre-designated). For above-threshold, applied as a heuristic, true when the SEAP list response reports highestOfferValue === lowestOfferValue with both non-null and non-zero. Records where the bid range is missing or zero (typically newly published or non-awarded) are dropped by this filter when set. For alert\_check Tasks: toggling this filter mints a fresh alert\_state slice (same fingerprint-replay caveat as judet).

## `winnerCui` (type: `array`):

Romanian tax codes (CUI) of WINNING suppliers to filter to. Keeps only tenders whose primary awarded winner is one of these CUIs. Numeric only, do not include the 'RO' VAT prefix. OR between values. The competitor-alert use case: an alert\_check Task with a competitor watch-list here fans out a delta every time that competitor wins a new tender (pair with acquisitionStatus=with\_winners so only awarded rows count). Matches the primary awarded winner, same as the get\_winner\_profile MCP tool. For alert\_check Tasks: changing this list mints a fresh alert\_state slice (same fingerprint-replay caveat as judet). Max 100 CUIs.

## `alertTypes` (type: `array`):

alert\_check mode only. Restricts emitted delta records to the listed alert\_type values. Alert state is still upserted for filtered records (so subsequent runs do not replay them); only the per-run dataset emit is filtered. Empty = all types emitted. Ignored in live and backfill modes.

## Actor input object example

```json
{
  "mode": "live",
  "tiers": [
    "sub_threshold"
  ],
  "acquisitionStatus": "ongoing",
  "cpvCodes": [
    "45000000"
  ],
  "keywordsRo": [],
  "authorityCui": [],
  "includeWinners": true,
  "enrichWithSector": true,
  "maxResults": 50,
  "concurrency": 10,
  "judet": [],
  "frameworkOnly": false,
  "singleBidder": false,
  "winnerCui": [],
  "alertTypes": []
}
```

# Actor output Schema

## `tenders` (type: `string`):

All normalized tenders emitted by this run. JSON / CSV / XLSX export is available from the Apify dataset API at the URL below.

# 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 = {
    "tiers": [
        "sub_threshold"
    ],
    "cpvCodes": [
        "45000000"
    ],
    "maxResults": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("apnoda/seap-sicap-tenders").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 = {
    "tiers": ["sub_threshold"],
    "cpvCodes": ["45000000"],
    "maxResults": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("apnoda/seap-sicap-tenders").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "tiers": [
    "sub_threshold"
  ],
  "cpvCodes": [
    "45000000"
  ],
  "maxResults": 50
}' |
apify call apnoda/seap-sicap-tenders --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=apnoda/seap-sicap-tenders",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Romanian Public Procurement (SEAP/SICAP)",
        "description": "Romanian public tenders from e-licitatie.ro (SEAP/SICAP): sub-threshold achiziții directe (not in EU TED) and above-threshold licitații publice. PII-stripped per GDPR, enriched with Romanian sector taxonomy, winner intelligence joined on awarded records. MCP-native, pay-per-record, no subscription.",
        "version": "0.1",
        "x-build-id": "StttRCNconBNvQ6B0"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/apnoda~seap-sicap-tenders/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-apnoda-seap-sicap-tenders",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/apnoda~seap-sicap-tenders/runs": {
            "post": {
                "operationId": "runs-sync-apnoda-seap-sicap-tenders",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/apnoda~seap-sicap-tenders/run-sync": {
            "post": {
                "operationId": "run-sync-apnoda-seap-sicap-tenders",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "mode"
                ],
                "properties": {
                    "mode": {
                        "title": "Mode",
                        "enum": [
                            "live",
                            "backfill",
                            "alert_check"
                        ],
                        "type": "string",
                        "description": "'live' pulls current data from e-licitatie.ro (maxResults capped at 1 000). 'backfill' pulls the 2007–2018 historical archive from istoric.e-licitatie.ro (maxResults capped at 100 000, priced per backfill_tender event). Backfill covers the above-threshold tier only, sub-threshold (achiziții directe) was formalized by Romania's Law 98/2016 and was never populated in the historical archive; sub_threshold passes return zero records under backfill. 'alert_check' (XP-01) queries the cached seap_tenders_hot MV (no live SEAP, no proxy cost) and diffs filter-matched records against the customer's prior alert_state slice, emitting one delta record per change annotated with alert_type ∈ {NEW, MODIFIED, AWARDED, AMENDED, EXTENDED, CANCELLED}. Within-Task dedup is structural via the 4-part PK (user_id, task_id, filter_fingerprint, sicap_id); date window is excluded from the filter_fingerprint so daily Tasks dedupe across observation windows.",
                        "default": "live"
                    },
                    "tiers": {
                        "title": "Tender tiers",
                        "minItems": 1,
                        "uniqueItems": true,
                        "type": "array",
                        "description": "Which tender types to include. Sub-threshold = achiziții directe (Romanian SMB sweet spot, not in EU TED). Above-threshold = licitații publice (also mirrored in EU TED). Defaults to sub-threshold only in live and backfill; in alert_check, omitting this defaults to BOTH tiers so the AWARDED, AMENDED, and EXTENDED alert types (which only fire on above-threshold records) are enabled.",
                        "items": {
                            "type": "string",
                            "enum": [
                                "sub_threshold",
                                "above_threshold"
                            ],
                            "enumTitles": [
                                "Sub-threshold (achiziții directe)",
                                "Above-threshold (licitații publice)"
                            ]
                        }
                    },
                    "acquisitionStatus": {
                        "title": "Acquisition status",
                        "enum": [
                            "ongoing",
                            "with_winners",
                            "all"
                        ],
                        "type": "string",
                        "description": "Which sub-threshold workflow slice to return. 'ongoing' (default) returns every current-era achiziție directă on the live index, sub-threshold buyers pre-designate the supplier, so winner CUI/name/closing-value are populated even on in-flight records. 'with_winners' narrows to state 7 'Oferta acceptata' (the most-terminal SEAP state observed in 2026) for users who only want offer-accepted records. 'all' is equivalent to 'ongoing' on this endpoint and is kept for forward compatibility. The legacy 'finalized' value is auto-mapped to 'with_winners' for backwards compatibility.",
                        "default": "ongoing"
                    },
                    "publicationDateStart": {
                        "title": "Publication date, from",
                        "type": "string",
                        "description": "ISO date (YYYY-MM-DD). Returns tenders published on or after this date. Defaults to 7 days ago. SEAP rejects queries wider than ~90 days with `searchTooLong:true`; use backfill mode for archival pulls."
                    },
                    "publicationDateEnd": {
                        "title": "Publication date, to",
                        "type": "string",
                        "description": "ISO date (YYYY-MM-DD). Returns tenders published on or before this date. Defaults to today."
                    },
                    "finalizationDateStart": {
                        "title": "Finalization date, from",
                        "type": "string",
                        "description": "ISO date (YYYY-MM-DD). Accepted and range-validated for forward compatibility, but NOT currently applied as a filter: the live sub-threshold index does not populate finalization dates (0% populated on the showOngoingDa path), so a finalization-date filter would match nothing. Filter by publication date instead."
                    },
                    "finalizationDateEnd": {
                        "title": "Finalization date, to",
                        "type": "string",
                        "description": "ISO date (YYYY-MM-DD). Accepted and range-validated for forward compatibility, but NOT currently applied as a filter (see finalizationDateStart). Filter by publication date instead."
                    },
                    "cpvCodes": {
                        "title": "CPV codes",
                        "maxItems": 50,
                        "uniqueItems": true,
                        "type": "array",
                        "description": "Common Procurement Vocabulary codes. E.g. 45000000 (construction works), 72000000 (IT services), 33100000 (medical equipment). Prefix matching supported, '451' matches every 451xxxxx code. Empty = all CPVs. Max 50 codes per run; for broader coverage, run multiple filtered queries and union the results.",
                        "items": {
                            "type": "string",
                            "pattern": "^[0-9]{1,8}$"
                        },
                        "default": []
                    },
                    "keywordsRo": {
                        "title": "Romanian keywords",
                        "maxItems": 20,
                        "type": "array",
                        "description": "Case-insensitive substring match in the tender title (Romanian); there is no description field to match against. OR between keywords. Max 20 keywords, each up to 100 characters; narrow further by combining with CPV or authority filters. Note: the MCP search tools match keywords with Romanian full-text stemming, this dataset-run filter is plain substring only.",
                        "items": {
                            "type": "string",
                            "maxLength": 100
                        },
                        "default": []
                    },
                    "authorityCui": {
                        "title": "Contracting authority CUI",
                        "maxItems": 100,
                        "type": "array",
                        "description": "Romanian tax codes (CUI) of contracting authorities to filter to. Numeric only, do not include the 'RO' VAT prefix. OR between values. Useful for monitoring a specific ministry, city hall, hospital, or state company. Max 100 CUIs per run.",
                        "items": {
                            "type": "string",
                            "pattern": "^[0-9]{2,10}$"
                        },
                        "default": []
                    },
                    "minValueRon": {
                        "title": "Minimum value (RON)",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Minimum estimated tender value in Romanian Lei."
                    },
                    "maxValueRon": {
                        "title": "Maximum value (RON)",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Maximum estimated tender value in Romanian Lei."
                    },
                    "includeWinners": {
                        "title": "Include winner intelligence",
                        "type": "boolean",
                        "description": "For finalized above-threshold tenders, fetch winner company CUI, name, and awarded value (adds one API call per finalized tender). Sub-threshold winner data is always populated when present (no extra call, F-15a). Strongly recommended for competitor monitoring use cases.",
                        "default": true
                    },
                    "enrichWithSector": {
                        "title": "Enrich with Romanian sector taxonomy",
                        "type": "boolean",
                        "description": "Add Romanian sector label (construcții / IT&C / medical / agricultură / transporturi / consultanță / mobilier / servicii profesionale / utilități) derived from CPV. More useful than raw CPV for filtering.",
                        "default": true
                    },
                    "maxResults": {
                        "title": "Maximum results",
                        "minimum": 1,
                        "maximum": 100000,
                        "type": "integer",
                        "description": "Hard cap on total records returned across all tiers. Prevents runaway costs. Enforced per mode: 1 000 in live, 100 000 in backfill. Requests above the mode cap are clamped at runtime.",
                        "default": 1000
                    },
                    "concurrency": {
                        "title": "Concurrent contract fetches",
                        "minimum": 1,
                        "maximum": 25,
                        "type": "integer",
                        "description": "Parallel contract-detail fetches for above-threshold finalized notices. Higher = faster, more load on SEAP. Backfill runs should typically use a lower value to avoid rate-limiting on the historic service.",
                        "default": 10
                    },
                    "judet": {
                        "title": "Județ (Romanian county)",
                        "maxItems": 42,
                        "uniqueItems": true,
                        "type": "array",
                        "description": "Filter to tenders whose contracting authority is registered in one of the listed Romanian counties (județe). Matched case- and diacritic-insensitively, so 'Cluj', 'CLUJ', 'cluj' all resolve identically; 'București' / 'Bucuresti' both match the capital. Coverage is ~98% of CUIs (per IN-06-F-XX-judet Spike 5c), records whose authority CUI is missing from the bundled snapshot are dropped by this filter. Empty = no judet filter. Max 42 entries. NOTE for alert_check Tasks: changing this filter (e.g. adding a new county) mints a fresh alert_state slice, so the next run will re-fire every matched record as NEW. This is by design, different judet sets are different saved searches. The alertTypes filter, by contrast, does NOT replay history when changed (it's emit-side only).",
                        "items": {
                            "type": "string",
                            "maxLength": 50
                        },
                        "default": []
                    },
                    "frameworkOnly": {
                        "title": "Framework agreements only (acord-cadru)",
                        "type": "boolean",
                        "description": "Limit results to framework agreements (acord-cadru). When true, sub-threshold direct acquisitions are excluded entirely (they are bilateral by construction and never framework). For above-threshold, derived from SEAP's hasSubsequentContracts boolean on the list response, no extra detail fetch. For alert_check Tasks: toggling this filter mints a fresh alert_state slice (same fingerprint-replay caveat as judet).",
                        "default": false
                    },
                    "singleBidder": {
                        "title": "Single-bidder only",
                        "type": "boolean",
                        "description": "Limit results to tenders received with exactly one bid. Sub-threshold direct acquisitions are inherently single-bidder (the supplier is pre-designated). For above-threshold, applied as a heuristic, true when the SEAP list response reports highestOfferValue === lowestOfferValue with both non-null and non-zero. Records where the bid range is missing or zero (typically newly published or non-awarded) are dropped by this filter when set. For alert_check Tasks: toggling this filter mints a fresh alert_state slice (same fingerprint-replay caveat as judet).",
                        "default": false
                    },
                    "winnerCui": {
                        "title": "Winner CUI (competitor tracking)",
                        "maxItems": 100,
                        "uniqueItems": true,
                        "type": "array",
                        "description": "Romanian tax codes (CUI) of WINNING suppliers to filter to. Keeps only tenders whose primary awarded winner is one of these CUIs. Numeric only, do not include the 'RO' VAT prefix. OR between values. The competitor-alert use case: an alert_check Task with a competitor watch-list here fans out a delta every time that competitor wins a new tender (pair with acquisitionStatus=with_winners so only awarded rows count). Matches the primary awarded winner, same as the get_winner_profile MCP tool. For alert_check Tasks: changing this list mints a fresh alert_state slice (same fingerprint-replay caveat as judet). Max 100 CUIs.",
                        "items": {
                            "type": "string",
                            "pattern": "^[0-9]{2,10}$"
                        },
                        "default": []
                    },
                    "alertTypes": {
                        "title": "Alert types to emit (alert_check only)",
                        "uniqueItems": true,
                        "type": "array",
                        "description": "alert_check mode only. Restricts emitted delta records to the listed alert_type values. Alert state is still upserted for filtered records (so subsequent runs do not replay them); only the per-run dataset emit is filtered. Empty = all types emitted. Ignored in live and backfill modes.",
                        "items": {
                            "type": "string",
                            "enum": [
                                "NEW",
                                "MODIFIED",
                                "CANCELLED",
                                "AWARDED",
                                "AMENDED",
                                "EXTENDED"
                            ],
                            "enumTitles": [
                                "NEW (first observation of a record)",
                                "MODIFIED (content_hash changed, fallback gate)",
                                "CANCELLED (stubbed; currently classifies as MODIFIED, XP-01-followup-1)",
                                "AWARDED (primary_winner_cui transitioned null → non-null)",
                                "AMENDED (errata_no or version_no incremented)",
                                "EXTENDED (tender_deadline_date changed)"
                            ]
                        },
                        "default": []
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
