Licitații SICAP prin API: căutare automată după CPV și județ
Licitații SICAP prin API: cum caută un agent AI anunțuri după cod CPV, cuvânt cheie, județ și dată, ce înseamnă starea procedurii și ce lipsește.
O firmă care vinde către statul român urmărește zilnic anunțurile de participare din SICAP, pe e-licitatie.ro. Munca e repetitivă: aceleași coduri CPV, aceleași județe, aceleași cuvinte în titlu, verificate în fiecare dimineață. E exact genul de sarcină pe care o poate face un agent AI, cu condiția să aibă o interfață stabilă, cu parametri clari și un răspuns structurat. Articolul descrie cum caută unealta ro_tenders de la 402check în SICAP, cum se folosesc codurile CPV și filtrul de județ, cum se citește starea unei proceduri și ce nu returnează v1.
Ce interoghează unealta
Site-ul public e-licitatie.ro își încarcă lista de anunțuri de participare dintr-un endpoint JSON intern. Nu are documentație publică: am citit formatul cererii din codul frontend-ului site-ului și l-am verificat cu cereri reale pe 27 octombrie 2026. ro_tenders trimite aceeași cerere pe care o trimite pagina de listă a site-ului și transformă răspunsul într-un format stabil.
Asta are o consecință pe care un agent trebuie s-o știe: endpoint-ul se poate schimba fără anunț. Când se schimbă sau cade, unealta răspunde 502 upstream_error, iar apelul nu se taxează. Validăm cu Zod atât parametrii primiți, cât și forma răspunsului de la SICAP, deci o schimbare de format devine o eroare clară, nu date greșite.
Parametrii
O căutare are nevoie de cel puțin unul dintre q și cpv. Restul sunt opționali:
q: un cuvânt sau o expresie din titlul contractului, între 2 și 200 de caractere.cpv: un cod CPV de 8 cifre, fără cifra de control.county: județul locului de executare, de exempluCluj.fromșito: intervalul datei de publicare,YYYY-MM-DD, ambele capete incluse;fromnu poate fi dupăto.limit: câte anunțuri să întoarcă, între 1 și 50, implicit 20.
Rezultatele vin în ordinea în care le întoarce SICAP, cele mai noi primele. Parametrii ajung în corpul cererii exact ca filtrele din pagina site-ului:
src/tools/tenders.tsfunction buildListBody(query: TenderQuery, county: County | null): string {
return JSON.stringify({
sysNoticeTypeIds: [],
sortProperties: [],
pageIndex: 0,
pageSize: query.limit,
contractName: query.q,
cPVText: query.cpv,
nutsCodeIds: county ? [county.id] : undefined,
startPublicationDate: query.from,
endPublicationDate: query.to,
});
}
Codurile CPV
CPV (Common Procurement Vocabulary) e nomenclatorul comun al achizițiilor publice din UE. Potrivit paginii CPV de pe TED, vocabularul a fost adoptat prin Regulamentul (CE) nr. 213/2008 și are o structură de arbore cu coduri de până la nouă cifre: primele două cifre identifică diviziunea, primele trei grupa, primele patru clasa, primele cinci categoria, iar fiecare dintre ultimele trei cifre adaugă precizie. A noua cifră, cea de după cratimă, servește la verificarea celorlalte.
Unealta primește codul de 8 cifre și întoarce codul complet, cu cifra de control, așa cum apare în anunț. Două exemple reale din fixture-ul nostru de test:
30213100-6: Computere portabile31400000-0: Acumulatori, pile galvanice si baterii primare
Folosește coduri complete, de 8 cifre, cum apar în anunțuri. Nu am verificat dacă un cod de nivel superior (o diviziune sau o grupă) întoarce și anunțurile din subcoduri; comportamentul SICAP nu e documentat, așa că nu ne bazăm pe el.
Pentru un agent, CPV-ul e filtrul cel mai precis. Un cuvânt cheie depinde de cum și-a formulat autoritatea titlul: „laptop”, „laptopuri”, „calculatoare portabile”. Codul CPV e același indiferent de formulare. În practică, combinația utilă e un CPV plus, la nevoie, un cuvânt cheie care restrânge rezultatele.
Filtrul de județ
Lista de anunțuri din SICAP nu conține locația, dar căutarea se poate filtra după locul de executare. SICAP folosește coduri NUTS, iar județele sunt intrările de forma RO urmat de trei cifre. Unealta descarcă lista NUTS a SICAP, o păstrează în cache 24 de ore și caută județul după nume, fără diacritice și fără să țină cont de majuscule: bucuresti, București și Bucureşti duc la aceeași intrare.
Un județ necunoscut, de exemplu o greșeală de scriere, primește 400 invalid_query cu detaliul unknown county, înainte de orice căutare de anunțuri, și nu se taxează. Câmpul county din răspuns e județul după care ai filtrat; fără filtru e null, pentru că SICAP nu trimite locația în listă.
Ce primește agentul
Fiecare anunț are aceleași câmpuri:
id: numărul anunțului, de exempluCN1097513title: titlul contractuluiauthority: autoritatea contractantă, fără codul fiscal din fața numeluicpv: codul CPV complet, cu cifra de controlcounty: județul filtrat saunullvalueRon: valoarea estimată în lei, saunullcând lipsește din anunțpublishedșideadline: data publicării și termenul de depunere a ofertelorstatus: starea proceduriiurl: pagina publică a anunțului pe e-licitatie.ro
Starea procedurii
SICAP are propriile stări de procedură: în desfășurare, anulată, suspendată, atribuită. Unealta le reduce la patru valori, cu o regulă în plus pentru termen:
src/tools/tenders.tsfunction mapStatus(notice: Notice, deadline: string | null, now: number): Tender["status"] {
const state = notice.sysProcedureState?.id;
if (state === PROCEDURE_STATE.awarded) return "awarded";
if (state === PROCEDURE_STATE.cancelled) return "cancelled";
const deadlineOpen = deadline === null || Date.parse(deadline) > now;
return state === PROCEDURE_STATE.inProgress && deadlineOpen ? "open" : "unknown";
}
open înseamnă că procedura e în desfășurare și termenul de depunere nu a trecut. O procedură în desfășurare cu termenul expirat devine unknown: oferta nu se mai poate depune, iar rezultatul nu e încă cunoscut. O procedură suspendată devine tot unknown: oferta nu se poate depune acum. Un agent care caută oportunități ar trebui să filtreze pe status: "open"; restul sunt context.
Exemple de căutări
Laptopuri cu loc de executare în Cluj, după cod CPV:
cpv=30213100&county=Cluj
Monitorizare zilnică pe un cuvânt cheie, doar anunțurile publicate într-o anumită zi:
q=drumuri&from=2026-10-26&to=2026-10-26&limit=50
Cuvânt cheie plus CPV, pentru a restrânge o categorie largă:
q=acumulatori&cpv=31400000
Un agent care rulează zilnic aceeași căutare cu from și to egale cu ziua precedentă primește doar anunțurile noi, dacă sunt cel mult 50 pe zi (limita unui apel), fără să țină el evidența celor văzute.
Ce nu face v1
- Nu returnează anunțuri de atribuire, câștigători sau valori de contract. Vezi doar starea procedurii (
awarded), nu cine a câștigat. - Caută doar anunțuri de participare din lista SICAP, nu documentația de atribuire.
- Cel mult 50 de anunțuri per apel.
- Endpoint-ul nedocumentat se poate schimba; atunci răspunsul e
502 upstream_error, netaxat.
Încearcă
O căutare costă $0.02 per apel reușit. Primele 10 apeluri pe zi pentru fiecare adresă IP sunt gratuite, fără cheie și fără cont:
curl "https://402check.com/v1/ro/tenders?cpv=30213100&county=Cluj&limit=5"
curl "https://402check.com/v1/ro/tenders?q=drumuri&from=2026-10-26&to=2026-10-26"
Parametrii generați din schema Zod, un formular care rulează căutarea din browser și apelul MCP echivalent sunt pe pagina de documentație ro_tenders.