oneapi
Sign in
Business v1 / Achiziții publice

Tenders by subject (semantic)

You describe in free text what is being bought (e.g. „cleaning services") and get back the contracts in the CPV code that matches by MEANING. Under the hood: the text is matched semantically to a CPV code (see /cpv/potriveste), then the contracts with that code are listed. The response shows the detected CPV plus the alternatives. Optional filters: ?an=, ?autoritate_cui=, ?castigator_cui=, ?val_min=, ?val_max=. Paginated.

GET
https://oneapi.ro/api/business/v1/achizitii/dupa-obiect

Query parameters

NameTypeDescriptionAccepted values
anoptional integer | null Optional filter on the contract year. e.g. 2024
autoritate_cuioptional integer | null The contracting authority VAT number, as a filter on top of the semantic match. 1
castigator_cuioptional integer | null The winner VAT number, as a filter on top of the semantic match. 1
textoptional string | null A description of the contract subject (required). E.g. "cleaning services". e.g. servicii de curateniee.g. reparatii drumurie.g. servicii medicale
tipoptional string | null Procedure type: contracte, directe or notificari. contractedirectenotificari
val_maxoptional number | null Maximum contract value, in RON (valoare_ron). 0
val_minoptional number | null Minimum contract value, in RON (valoare_ron). 0

How it behaves

  • Not every contract has a declared value. Measured on 4 October 2026, across all 17.39 million rows: it is missing on 10.8% of contracts (312,587 rows), and almost never on direct awards (47 out of 13.68 million) or notices (52 out of 811,033). Any total is therefore the total of the rows that DO carry a figure, not of the whole set — for tip=contracte, of nine tenths of them. Contract counts cover all rows. The val_min/val_max filters work on the RON value, so they exclude rows without one.
  • Describe the subject of the contract in free text (e.g. "cleaning services") and get the contracts under the CPV matched by meaning, not by words. It composes semantic text→CPV matching (see /cpv/potriveste) with listing contracts under that code.
  • The response states the detected CPV explicitly (with its score) and the alternatives. Filters can be added: ?an=, ?autoritate_cui=, ?castigator_cui=, ?tip=, ?val_min=, ?val_max=. ?text= is required.
  • Filtering uses the highest-scoring CPV. For fine control, use /cpv/potriveste and then /achizitii/cauta?cpv=.
  • Each contract appears once: older publications of a contract SEAP republished and the contract value repeated on other lots are not listed (/achizitii/{id} opens them). valoare.ron is the declared value; valoare.atribuita_ron, this winner's share, is the one used in sums.
  • Sums count each contract once, with each winner's share. SEAP republishes the award notice on every update (1.19 M contract rows are republications), repeats the contract value on every lot (0.52 M) and puts the value of the WHOLE framework agreement on every winner (228,000 rows). Read raw, the 2021–2026 contracts added up to 7,059 billion lei and Farmexim to 248 billion; corrected, 1,212 billion and 14.6. Impossible values (a 125.9-billion air-traffic simulator, 1.59 billion of dairy at a child-protection directorate) are left out of sums.

What it is for

  • Finding contracts for a kind of purchase described in words.
  • Market analysis on a procurement category.
  • Monitoring a field of public contracts.

Response structure

FieldTypeDescription
data[].id integer The contract identifier. Open it with /achizitii/{id}, which carries the full SEAP notice (notice number, award criterion, EU funding).
data[].an integer | null The reference year.
data[].data_contract string | null The contract date.
data[].autoritate.nume string | null The name of the contracting authority.
data[].autoritate.cui integer | null The tax ID of the contracting authority.
data[].castigator.nume string | null The name of the winning company.
data[].castigator.cui integer | null The winner's tax ID. ⚠️ SEAP puts foreign identifiers in this same field: of 179,814 distinct identifiers, 8,656 (4.8%) are not valid Romanian tax IDs — see cui_romanesc.
data[].obiect string | null The contract subject, as published.
data[].cpv string | null The CPV code of the subject.
data[].cpv_denumire string | null The official name of the CPV code, from the nomenclature. It is the fallback description when the authority wrote nothing useful in obiect — 4,582 direct purchases have the word "directa" there. null for the 11 codes (out of 8,628) missing from the CPV 2008 nomenclature.
data[].valoare.ron number | null The contract value, in RON.
data[].valoare.eur number | null The contract value, in euro.
data[].valoare.moneda_originala string | null The currency the contract was published in.
data[].valoare.atribuita_ron number | null What falls to this winner: the declared value divided by the winners of the same framework agreement; null if the declared value is impossible. All sums use it.
data[].valoare.castigatori integer How many winners share the same contract (framework agreement); usually 1.
data[].valoare.suspecta boolean true if the declared value is impossible (over 10 times the procedure estimate, or thousands of times the authority's usual contracts); still shown, but left out of sums.
data[].tip string | null The type.
data[].procedura string | null The award procedure type.
meta.paginare.pagina integer Pagina curentă.
meta.paginare.per_pagina integer Rezultate pe pagină.
meta.paginare.total integer Total rezultate.
meta.paginare.pagini integer Număr de pagini.
data[].castigator.cui_romanesc boolean true if the value validates as a Romanian tax ID, check digit included. false only means it is NOT one — usually a foreign identifier (1,257 are longer than 10 digits) or a code with a wrong check digit (7,392). We do not claim to know whose it is. Worth reading before calling /firme/{cui}: with false, the company will not be found there.

Response examples

GEThttps://oneapi.ro/api/business/v1/achizitii/dupa-obiect?text=servicii+de+curatenie&per_pagina=3
{
    "data": [
        {
            "id": 57979911,
            "an": 2026,
            "data_contract": "2026-03-31",
            "autoritate": {
                "nume": "LICEUL TEORETIC GH.SINCAI",
                "cui": 4736434
            },
            "castigator": {
                "nume": "TRANSILVANIA CLEANING SOLUTIONS S.R.L.",
                "cui": 48188732,
                "cui_romanesc": true
            },
            "obiect": "Servicii de curatenie perioada 01.01.2026-31.03.2026",
            "cpv": "90910000-9",
            "cpv_denumire": "Servicii de curăţenie",
            "valoare": {
                "ron": 112352.52,
                "eur": null,
                "moneda_originala": null,
                "atribuita_ron": 112352.52,
                "castigatori": 1,
                "suspecta": false
            },
            "tip": "notificari",
            "procedura": "Servicii"
        }
    ],
    "meta": {
        "obiect": {
            "text": "servicii de curatenie",
            "cpv": {
                "cod": "90910000-9",
                "denumire": "Servicii de curăţenie",
                "scor": 0.8729719519615173
            },
            "alternative": [
                {
                    "cod": "90911100-7",
                    "denumire": "Servicii de curăţare a locuinţelor",
                    "scor": 0.7943454025490706
                }
            ]
        },
        "paginare": {
            "pagina": 1,
            "per_pagina": 3,
            "total": 16962,
            "pagini": 5654
        }
    }
}

Error codes

CodeSlugWhen it occurs
401neautentificatToken missing, invalid, expired or revoked.
403feature_indisponibilThe current plan does not include the feature the route depends on.
422validareThe text parameter is missing.
429cota_depasitaThe plan's monthly quota has been exceeded (see Retry-After).
503mentenantaThe CPV semantic index is not built, or the embeddings service is temporarily unavailable.

All errors share the same shape. eroare.cod is stable and is the value you should branch on in code — not the text in mesaj, which may change.

{
    "eroare": {
        "cod": "validare",
        "mesaj": "The text parameter is missing.",
        "detalii": {
            "an": [
                "The value sent does not satisfy the parameter rule."
            ]
        }
    }
}