Data model
This page is for users of the Dataset Register: anyone querying the SPARQL endpoint, fetching dataset descriptions in RDF, or building applications on top of the register. It describes the consumer-facing, published data model: the RDF as it appears in the register after fetching, validating, mapping, and storing the providers’ input.
If you are a publisher (a data platform submitting dataset descriptions) you are looking for the input format and validation rules instead — see the Requirements for Datasets.
The register stores descriptions in DCAT, aligned with DCAT-AP-NL 3.0. Schema.org submissions are converted to DCAT at ingest, so consumers see the DCAT form regardless of how the data was originally submitted. The Schema.org ↔ DCAT alignment mostly follows the W3C DCAT 3 Alignment with Schema.org appendix.
Cardinalities reflect the data as stored, including auto-derived and auto-default values.
Property-column tags signal the source vocabulary:
- untagged — profiled by DCAT-AP-NL 3.0 (the default).
- DCAT — defined in DCAT 3.0 but not profiled by DCAT-AP-NL.
- DC — plain Dublin Core (
dct:) passthrough; not profiled by DCAT-AP-NL, DCAT-AP, or DCAT 3.0. - DCAT-AP-NL: Distribution only — DCAT-AP-NL profiles the property only on Distribution; the dataset-level usage is a register convenience.
NAL stands for Named Authority List, the EU Publications Office’s term for the controlled vocabularies it maintains (Languages, Frequency, Access Rights, File Type, etc.).
Dataset
The dcat:Dataset, dcat:Distribution, and
foaf:Agent shapes describe the public dataset description as stored.
dcat:Dataset
When a dataset’s RDF description is fetched and validated, it is stored as a dcat:Dataset in its
own graph. The URL of the graph corresponds to the dataset’s IRI.
A dataset MUST be identified by an HTTP(S) IRI: it is the stable, dereferenceable identifier the
register indexes and uses as the graph URL. A dataset expressed as a blank node, or with a
non-HTTP IRI, is rejected as invalid (HTTP 400) with a clear web-URI message – this holds for
both dcat:Dataset and schema:Dataset descriptions.
| DCAT term | Data type / notes | Cardinality |
|---|---|---|
dct:title | rdf:langString | 1..n (one per language) |
dct:identifier | Auto-derived from the dataset IRI | 1..1 |
dct:description | rdf:langString | 1..n (one per language) |
dct:license DCAT-AP-NL: Distribution only | IRI or literal in v1; v2.0: IRI required. Inherited by distributions that don’t specify their own. If the dataset has no IRI license, the register denormalises one IRI license from its distributions onto the dataset for query convenience. A license must exist on the dataset or on every distribution — see DistributionLicenseRequiredShape. | 0..1 |
dct:accessRights | EU Access Rights NAL IRI; defaults to PUBLIC | 1..1 |
dcat:theme | IRI from a controlled vocabulary; the EU Data Theme NAL value data-theme/EDUC is auto-assigned | 1..n |
dcat:contactPoint | vcard:Kind with vcard:fn and vcard:hasEmail (mailto: IRI) | 0..1 v2.0: 1..1 |
dct:language | EU Language Authority IRI | 0..n |
dcat:landingPage | IRI | 0..n |
dct:source | IRI | 0..n |
dct:created DC | xsd:date or xsd:dateTime; the lexical form may not be ISO 8601 in v1.v2.0: ISO 8601 value required | 0..1 |
dct:issued | xsd:date or xsd:dateTime; the lexical form may not be ISO 8601 in v1.v2.0: ISO 8601 value required | 0..1 |
dct:modified | xsd:date or xsd:dateTime; the lexical form may not be ISO 8601 in v1.v2.0: ISO 8601 value required | 0..1 |
dcat:version | xsd:string | 0..1 |
dct:creator | foaf:Organization or foaf:Person | 0..n v2.0: 1..n |
dct:publisher | foaf:Organization or foaf:Person | 0..1 v2.0: 1..1 |
dct:spatial | IRI (e.g. GeoNames). DCAT-AP-NL also allows dct:Location with dcat:bbox / dcat:centroid / dcat:geometry, but the register stores IRI references only. | 0..n |
dct:temporal | dct:PeriodOfTime blank node with dcat:startDate and/or dcat:endDate | 0..n |
dct:isPartOf DC | IRI or literal in v1 v2.0: HTTPS IRI required | 0..n |
dct:hasPart DCAT | IRI | 0..n |
dct:isReferencedBy | IRI | 0..n |
dct:accrualPeriodicity | EU Frequency NAL IRI | 0..1 |
dcat:distribution | dcat:Distribution (see below) | 0..n |
dcat:Distribution
The objects of dcat:distribution dataset properties have type dcat:Distribution.
| DCAT term | Data type / notes | Cardinality |
|---|---|---|
dcat:accessURL | IRI v2.0: HTTPS IRI | 1..1 |
dcat:mediaType | IANA media type IRI. Required for download distributions; APIs use dct:conformsTo instead. Any compression suffix is split off into dcat:compressFormat. | 0..n v2.0: 0..1 |
dcat:compressFormat | IANA media type IRI; added when e.g. +gzip is stripped from dcat:mediaType | 0..1 |
dct:conformsTo | Protocol IRI (e.g. <https://www.w3.org/TR/sparql11-protocol/> for SPARQL endpoints) | 0..1 |
dct:issued | xsd:date or xsd:dateTime | 0..1 |
dct:modified | xsd:date or xsd:dateTime | 0..1 |
dct:title | rdf:langString | 0..n |
dct:description | rdf:langString | 0..n |
dct:language | EU Language Authority IRI | 0..1 |
dct:license | IRI or literal in v1; v2.0: IRI required. Inherited from the dataset if not specified. The register requires a license to exist on the distribution or the dataset via DistributionLicenseRequiredShape. | 0..1 |
dcat:byteSize | xsd:integer (bytes) | 0..1 |
foaf:page | IRI to a documentation page (SPARQL UI, download landing page, etc.) v2.0: HTTPS required | 0..n |
odrl:hasPolicy | ODRL policy associated with the distribution | 0..n |
foaf:Agent
The objects of both the dct:creator and dct:publisher dataset properties are foaf:Agent
instances — concretely either foaf:Organization or foaf:Person. The publisher carries
additional properties beyond those available on the creator.
| Property | Data type / notes | Cardinality |
|---|---|---|
foaf:name | rdf:langString — the organization or person name | 1..n (one per language) |
foaf:nick | Alternate name (publisher only) | 0..n |
dct:identifier | Identifier (publisher only) | 0..1 |
foaf:mbox | Email address as a literal (publisher only) | 0..1 |
owl:sameAs | Equivalent entity IRI (publisher only) | 0..n |
Registration
The shapes below describe how the register tracks registrations themselves – not the public dataset description that consumers query.
schema:EntryPoint
A URL registered by clients is added as a schema:EntryPoint to the
Registrations graph
once its description passes validation. A submission that is
rejected with HTTP 400 is not stored,
so it never appears here.
Datasets are fetched from this URL on registration and when the crawler runs.
| Property | Description |
|---|---|
schema:additionalType | Computed registration status:
|
schema:datePosted | UTC datetime when the URL was registered. |
schema:dateRead | UTC datetime when the URL was last read by the application. The crawler updates this value when fetching descriptions. |
schema:status | The HTTP status code last encountered when fetching the URL. |
schema:validUntil | If the URL has become invalid, the UTC datetime at which it did so. |
schema:about | The schema:Datasets found at this URL. A registration URL may describe a single dataset (one entry) or a catalog of multiple datasets (multiple entries). The crawler updates this value when fetching descriptions. |
nde:warningCount (<https://def.nde.nl/registration#warningCount>) | xsd:integer — the number of sh:Warning-severity results the registration’s description produced at the last crawl. 0 (or absent) means it validated cleanly; a positive value surfaces as “registered with warnings” on the dataset page. Tracked per registration, so it covers all datasets at the URL together. The full report is in the SHACL validation report graph. |
schema:Dataset
Each dataset that is found at the schema:EntryPoint registration URL gets added as a
schema:Dataset to the
Registrations graph.
| Property | Description |
|---|---|
schema:dateRead | UTC datetime when the dataset was last read by the application. |
schema:subjectOf | From which registration URL the dataset was read. |
schema:Rating
A separate named graph keeps a schema:Rating for each dataset description, reached from a
dataset via the schema:contentRating property. It is the completeness rating, indicating
how complete the description is (which recommended properties it provides).
| Property | Description |
|---|---|
schema:bestRating | The highest possible rating (100). |
schema:worstRating | The lowest possible rating. |
schema:ratingValue | The completeness score. |
schema:ratingExplanation | Explanation for the rating: which properties are missing? |
Validation warnings used to be kept here as a second schema:Rating. They are now recorded per
registration as nde:warningCount — warnings concern the whole registration,
not an individual dataset — with the full report in the SHACL validation report
graph.
SHACL validation report
On every crawl, the register stores the full SHACL validation report for each registration’s description in a dedicated named graph, one per registration URL:
https://data.netwerkdigitaalerfgoed.nl/registry/shacl-validation/<URL-encoded registration URL>
For example, the report for https://example.com/datacatalog lives in the graph
https://data.netwerkdigitaalerfgoed.nl/registry/shacl-validation/https%3A%2F%2Fexample.com%2Fdatacatalog.
The graph holds the same sh:ValidationReport the validation endpoint returns —
the report of validating the publisher’s description as fetched, covering every dataset at the URL.
It is enrichment data produced by the register, replaced in full on each crawl, so it always
reflects the latest validation. The nde:warningCount on the registration is a
denormalised count of the sh:Warning-severity results in this report, kept on the registration so
applications can filter on it without reading the report.
Distribution health
For every distribution URL referenced by a registered dataset, the crawler periodically issues a probe (an HTTP HEAD/GET or a SPARQL ASK, depending on the distribution type) and records the outcome in a dedicated named graph:
https://datasetregister.netwerkdigitaalerfgoed.nl/sparql/distribution-health
Distribution health is enrichment data produced by the register, not metadata supplied by publishers. Keeping it in its own named graph – parallel to the dataset and registration graphs – makes that origin explicit: consumers can opt in or out of it cleanly, and the register can re-probe, prune, or reset the data without touching the published DCAT description.
Vocabulary prefix: nde-probe: <https://def.nde.nl/probe#>.
nde-probe:DistributionHealthRecord
Each probed URL appears as a nde-probe:DistributionHealthRecord whose IRI is the distribution URL itself.
| Property | Data type / notes | Cardinality |
|---|---|---|
nde-probe:lastProbedAt | xsd:dateTime — UTC timestamp of the most recent probe attempt. | 1..1 |
nde-probe:lastOutcome | Outcome IRI of the last probe; absent when the last probe succeeded. One of the IRIs listed under Probe outcomes below. | 0..1 |
nde-probe:lastSuccessAt | xsd:dateTime — UTC timestamp of the most recent successful probe, if any. | 0..1 |
nde-probe:firstFailureAt | xsd:dateTime — UTC timestamp at which the current failure streak began. Cleared on the next success. | 0..1 |
nde-probe:consecutiveFailures | xsd:integer — length of the current failure streak. Reset to 0 on the next success. | 1..1 |
nde-probe:sourceFingerprint | xsd:string — opaque source-change fingerprint observed on the last probe (the most recent of the declared dct:modified and the HTTP Last-Modified, combined with the byte size). The shared key the validity staleness gate compares against. Absent when none could be derived (e.g. a SPARQL endpoint). | 0..1 |
Probe outcomes
When a probe fails, nde-probe:lastOutcome is one of:
| Outcome IRI | Meaning |
|---|---|
nde-probe:NetworkError | Connection refused, DNS failure, TLS error, timeout, or any other non-HTTP transport failure. |
nde-probe:NotFound | HTTP 404 or 410. |
nde-probe:ServerError | HTTP 5xx. |
nde-probe:AuthRequired | HTTP 401 or 403. |
nde-probe:RateLimited | HTTP 429. |
nde-probe:ContentTypeMismatch | Response was reachable but served the wrong content type. For a data dump, its Content-Type did not match the declared dcat:mediaType / dct:format / schema:encodingFormat. For a SPARQL endpoint, the response was not a SPARQL results media type – most often an HTML page, meaning the access URL points to a SPARQL query web UI rather than the SPARQL protocol endpoint itself. The fix is to put the SPARQL protocol endpoint in dcat:accessURL (schema:contentUrl) and declare the query UI on foaf:page (schema:documentation) instead. |
nde-probe:ContentTypeMissing | Response had no Content-Type header at all. |
nde-probe:SparqlProbeFailed | The distribution declares a SPARQL endpoint (dct:conformsTo <https://www.w3.org/TR/sparql11-protocol/>) but the probe ASK query did not return a valid SPARQL result. |
An empty body and an unparseable body used to be reachability outcomes (nde-probe:EmptyBody, nde-probe:RdfParseFailed). They no longer are: a fetched body that is empty or does not parse is reachable, and the defect is recorded on the validity rail instead.
Effect on validation results
Probe failures also surface in the SHACL validation report as sh:ValidationResult nodes. See Validation: how probe failures appear in the report for the constraint components, the extra properties they carry, and how strict each caller (registration, validation, crawler) is.
Distribution validity
Where distribution health records reachability, distribution validity records whether a distribution’s fetched content actually parses as RDF. The crawler shallow-validates small RDF dumps (≤ 10 KB Turtle / N-Triples / N-Quads) and records the verdict — for every distribution it attempts, valid or not — as a DQV quality measurement in a dedicated named graph:
https://datasetregister.netwerkdigitaalerfgoed.nl/sparql/distribution-validity
Like distribution health, this is enrichment data produced by the register, kept in its own graph and replaced on every crawl. The same measurement shape is also produced by the Dataset Knowledge Graph, which deep-validates the full distribution; a consumer tells the two apart by which endpoint served the measurement, not by the RDF.
Vocabulary prefixes: dqv: <http://www.w3.org/ns/dqv#>, prov: <http://www.w3.org/ns/prov#>, metric: <https://def.nde.nl/metric#>, failure: <https://def.nde.nl/failure#>, dvf: <https://def.nde.nl/distribution-validity-failure#>, probe: <https://def.nde.nl/probe#>.
dqv:QualityMeasurement
Each validated distribution carries a dqv:QualityMeasurement of the boolean metric metric:distribution-rdf-valid, computed on the distribution’s access URL — the file itself, because validity is a property of the bytes, not of any dataset’s use of them.
| Property | Data type / notes | Cardinality |
|---|---|---|
dqv:isMeasurementOf | metric:distribution-rdf-valid. | 1..1 |
dqv:computedOn | The distribution’s access URL. | 1..1 |
dqv:value | xsd:boolean — true when the content parsed as RDF, false otherwise. | 1..1 |
prov:generatedAtTime | xsd:dateTime — when the verdict was produced. | 1..1 |
prov:wasGeneratedBy | A prov:Activity carrying prov:wasAssociatedWith the producer (the register crawler). | 1..1 |
probe:sourceFingerprint | xsd:string — the source fingerprint the verdict was judged against; matched against the health record’s fingerprint by the staleness gate. Absent when none could be derived. | 0..1 |
When the verdict is false, the activity additionally prov:qualifiedUsage a prov:Usage recording why:
| Property | Data type / notes | Cardinality |
|---|---|---|
failure:reason | A SKOS concept from the distribution-validity-failure scheme: dvf:parse-error (the content could not be parsed) or dvf:empty (it parsed but yielded no triples, or the body was empty). | 1..1 |
failure:message | xsd:string — best-effort parser message, where the parser provides one. Advisory only. | 0..1 |
Usability
reachability and validity are combined, on read, into a single usability verdict — usable, unusable, or unknown — that the browser surfaces as a per-distribution badge. The rule is:
- Reachability dominates: an unreachable distribution is
unusable(cause: unreachable), regardless of any validity verdict. - A reachable distribution with a
falsevalidity verdict isunusable(cause: invalid), with the reason and parser message. - A reachable distribution with a
truevalidity verdict isusable. - Staleness gate: a validity verdict applies only while its
probe:sourceFingerprintstill equals the currently-observed one; otherwise it decays tounknown, so a since-fixed distribution stops showing as broken. - Depth: a deep (Knowledge Graph) verdict wins over a shallow (register) one; a shallow verdict still counts but is flagged as not yet deeply confirmed.
Allow list
A registration URL must be on a domain that is allowed before it can be added to the Register.
The allow list lives in the
https://data.netwerkdigitaalerfgoed.nl/registry/allowed_domain_names RDF graph.
Each entry is a blank node with a single property:
| Property | Description |
|---|---|
https://data.netwerkdigitaalerfgoed.nl/allowed_domain_names/def/domain_name | Literal: either a registrable domain (example.com) or a specific subdomain (sub.example.com). A registrable domain implicitly covers all its subdomains. |
To modify the allow list, use the REST API (POST /allowed-domains); the SPARQL
endpoint is read-only.