Data model
The fields of a record with their type, what missing and estimated values look like and which key identifies a tender permanently.
You receive this service through an individual quote.
One record per tender is the goal, not a guarantee. If a notice appears on several portals, procuris merges it into one record. If procuris detects a duplicate only later, it archives the newer record with archiveReason set to merged and gives in mergedInto the id of the record that remains.
Corrections change the existing record instead of creating a new one. Corrections and change notices keep the id and get a new lastModified. procuris does not delete records, it archives them. Expired, cancelled, awarded or merged tenders get the status archived.
The list, the single request and webhooks deliver the same complete records. The keys are written in camelCase (each word after the first starts with a capital letter, for example lastModified).
Complete example
The example shows the sample record used throughout these docs, as of 1 October 2026. The contracting authority published the notice on 17 September without a contract value. Until 22 September the record therefore held an estimate. On 22 September the contracting authority stated the contract value of 351,000 euros, and on 24 September it moved the submission deadline.
{
"id": "e9da30eb-50e6-47f1-887f-434016267b2f",
"status": "open",
"archiveReason": null,
"mergedInto": null,
"title": "Nordhausen - Sanierung Rolandbrunnen, Erneuerung Brunnentechnik",
"description": "Erneuerung der Brunnentechnik des Rolandbrunnens in Nordhausen. Los 1 umfasst Pumpen und Steuerung, Los 2 die Beckenabdichtung.",
"tenderNumber": "33/61/2026",
"url": "https://www.procuris.eu/notices/nordhausen-sanierung-rolandbrunnen-erneuerung-brunnentechnik-e9da30eb",
"publicationDate": "2026-09-17T13:32:56.000Z",
"submissionDate": "2026-10-14T08:00:00.000Z",
"participationDeadline": null,
"lastModified": "2026-09-24T09:10:00.000Z",
"checkedAt": "2026-10-01T06:00:00.000Z",
"contractAmount": {
"value": 351000,
"currency": "EUR",
"estimated": false
},
"procedureType": "open",
"contractNature": "works",
"legislation": null,
"organizations": [
{
"id": "7c2a9e41-3d8b-4f6a-b1e2-5a0c9d4e8f17",
"name": "Stadtverwaltung Nordhausen - Vergabestelle",
"role": "contractingParty",
"contactName": "Vergabestelle",
"email": "vergabe@example.org",
"phone": "+49 3631 000000",
"address": {
"street": "Musterstraße 1",
"postalCode": "99734",
"city": "Nordhausen",
"countryCode": "DE"
}
}
],
"cpvClassifications": [
{
"cpvCode": "45000000",
"title": "Bauarbeiten"
},
{
"cpvCode": "71000000",
"title": "Architektur & Ingenieurwesen"
}
],
"regionCodes": ["DEG"],
"realizedLocation": "Nordhausen",
"lots": [
{
"lotNumber": "1",
"title": "Pumpen und Steuerung",
"description": "Lieferung und Einbau der Umwälzpumpen und der Brunnensteuerung.",
"contractAmount": {
"value": 212000,
"currency": "EUR",
"estimated": true
},
"submissionDate": null,
"cpvClassifications": [
{
"cpvCode": "45232150",
"title": "Arbeiten an Wasserleitungen"
}
]
},
{
"lotNumber": "2",
"title": "Beckenabdichtung",
"description": null,
"contractAmount": null,
"submissionDate": null,
"cpvClassifications": []
}
],
"sources": [
{
"name": "TED",
"url": "https://ted.europa.eu/de/notice/-/detail/000000-2026",
"publishedAt": "2026-09-17T13:32:56.000Z"
}
]
}Title, tender number, dates and CPV codes come from a real notice. Contact, lots, region and source were added for illustration. The contact details are placeholders.
Basic rules
- Missing values appear as
null, not as a missing key. "ornull" in the tables means: the key is in the record, without a value. For details from the notice, the contracting authority has usually not published the value. ForarchiveReason,mergedInto,contractAmountand the fields of the lots, the table says whatnullmeans there. An empty list[]means the same for lists. - Timestamps are in UTC according to ISO 8601, for example
2026-10-14T08:00:00.000Z. lastModifiedis the time of the last change in content at procuris. It is not the time at the contracting authority. The value only increases.checkedAtis the data state, meaning when procuris last checked the record. A newcheckedAton its own is not a change in content. It does not changelastModifiedand does not trigger an event.- Skip unknown fields and values. New fields and values can be added, for example a new value for
archiveReason. Have your system skip both instead of aborting, because an abort stops the sync until the next adjustment.
Fields of the tender
| Field | Type | Meaning |
|---|---|---|
id | string (UUID) | fixed key of the tender, stays the same through corrections. Use it for changes and, together with mergedInto, against duplicates. |
status | open or archived | open: running. archived: ended, see archiveReason. |
archiveReason | string or null | expired (deadline passed), cancelled (procedure cancelled), awarded (contract awarded), merged (merged with another record). For open the value is null. |
mergedInto | string (UUID) or null | for merged, the id of the record that remains. Otherwise null. |
title | string | title of the notice |
description | string or null | description of the work |
tenderNumber | string or null | tender number of the contracting authority |
url | string | public page of the notice at procuris |
publicationDate | timestamp | first publication |
submissionDate | timestamp or null | submission deadline |
participationDeadline | timestamp or null | participation deadline in two-stage procedures |
lastModified | timestamp | last change in content at procuris, see above |
checkedAt | timestamp | data state, see above |
contractAmount | object or null | contract value, see below |
procedureType | string or null | procedure type according to the eForms code list procurement-procedure-type, for example open (open procedure) or restricted (restricted procedure) |
contractNature | string or null | works (construction work), supplies (deliveries), services (services) |
legislation | string or null | legal basis, where published |
organizations | list | organizations involved, see below |
cpvClassifications | list | CPV codes with cpvCode (string, eight digits) and title (string). CPV is the European vocabulary of types of work. Can be empty. |
regionCodes | list of strings | regions according to NUTS, the European division into areas, for example DEG for Thuringia. Can be empty. |
realizedLocation | string or null | place of performance as free text |
lots | list | lots, see below. Empty if the tender is not divided into lots. |
sources | list | original sources, see below. At least one entry. |
eForms is the EU format for notices. The code lists are published by the Publications Office of the EU.
Contract value
| Field | Type | Meaning |
|---|---|---|
value | number | amount excluding VAT, for example 351000 |
currency | string | currency according to ISO 4217, mostly EUR. procuris does not convert other currencies into euros. |
estimated | boolean | true: estimated, because the contracting authority has not published a value. false: published value. |
Only the contract value can be estimated. This applies to the tender and to the lots. If there is neither a published nor an estimated value, contractAmount is null.
Organizations
| Field | Type | Meaning |
|---|---|---|
id | string (UUID) | fixed key of the organization. If procuris recognizes the same city administration in several tenders, it carries the same id there. Two different id values do not rule out that it is the same body. |
name | string | name |
role | string | contractingParty (contracting authority), procurementOffice (procurement office, if it is not the contracting authority itself), reviewBody (review body, responsible for review procedures) |
contactName | string or null | contact person or office |
email | string or null | email address |
phone | string or null | phone number |
address | object or null | address, see below |
address has these fields:
| Field | Type | Meaning |
|---|---|---|
street | string or null | street and house number |
postalCode | string or null | postal code |
city | string or null | city |
countryCode | string or null | country as a two-letter code according to ISO 3166-1 alpha-2, for example DE |
Lots
Lots are parts of a tender that you can bid on separately.
| Field | Type | Meaning |
|---|---|---|
lotNumber | string | lot number as the contracting authority assigns it, for example 1 or LOT-0002 |
title | string | title of the lot |
description | string or null | description |
contractAmount | object or null | value of the lot, same structure as above |
submissionDate | timestamp or null | the lot's own deadline. null: the deadline of the tender applies. |
cpvClassifications | list | CPV codes of the lot. Empty: the codes of the tender apply. |
Sources
If a tender appears on several portals, it has several entries in sources.
| Field | Type | Meaning |
|---|---|---|
name | string | name of the portal, for example TED |
url | string or null | address of the notice on the portal |
publishedAt | timestamp or null | publication on this portal |
How to process the fields
- Create records by
idand update them by the sameid. This gives one entry peridin your system. Duplicates that procuris detects only later are resolved throughmerged(the point after next). - Overwrite a record only if the new
lastModifiedis greater than the stored one. Otherwise a late webhook message overwrites a newer state. - If a record arrives with
archiveReasonset tomerged, merge it in your system with the record frommergedInto. If the remaining record is missing in your system, fetch it with API access viaGET /v1/tenders/{mergedInto}. Without API access, if your system only receives webhooks (variant B under CRM and ERP), close the old entry and notemergedIntoon it. The remaining tender only enters your system when an event for it arrives. In variant B that happens when it is a hit of a selected saved search, or when it gets a change event as an earlier hit. - For
estimated: true, show the contract value as an estimate, so that nobody calculates with the amount as if it had been published.
Related pages
Request a quote
Tell us what you want to use or connect. Your quote is based on that scope.