Skip to content

Ontology

The Ontology is the root of a publisher’s OURS resources. It carries the publisher’s identity and three pointers to everything else, and it is what a consumer fetches first.

Field Type
resourceType string, required Always Ontology.
id string, required Short identifier for the ontology.
url URL, required Where the ontology is served.
version string, required The ontology’s version.
publisher string, required Who publishes it. Optional on other resources, required here.
models URL, required A document of Model resources.
vocabularies URL, required A document of Vocabulary resources.
mappings URL, required A document of the StructureMaps and ConceptMaps referenced by alignments.
name string, optional Human-readable name.
description string, optional What this ontology covers.
{
"resourceType": "Ontology",
"id": "example-org",
"url": "https://ours.example.org/ontology.json",
"version": "1.0.0",
"publisher": "ExampleOrg",
"name": "ExampleOrg ontology",
"description": "Models and vocabularies behind the ExampleOrg public API.",
"models": "https://ours.example.org/models.json",
"vocabularies": "https://ours.example.org/vocabularies.json",
"mappings": "https://ours.example.org/mappings.json"
}

Including from a publisher who has none of that thing, who serves an empty bundle at the URL instead of leaving it out.

“Has this publisher written any executable transformations?” is exactly the question a consumer arrives with. An omitted mappings pointer answers it with silence, and whether an artefact has been written yet is not a reason to be unanswerable about it.

For a small ontology you may serve the models and vocabularies inside the ontology document itself, as bundles, and save a consumer two round trips.

This stops being a kindness as the ontology grows. A consumer that wanted one model pays for all of them, on every fetch, and cannot cache the parts separately. For anything beyond a handful of resources, publish the documents at their own URLs and let the pointers do their job.

A consumer that has your domain and nothing else finds the ontology here:

https://example.org/.well-known/ours.json

This is an RFC 8615 well-known URI, the same mechanism security.txt and OpenID discovery use. It is what makes “no prior coordination” literal rather than nearly true: without it a consumer still has to be told one unguessable address, which is a small piece of coordination, and small pieces of coordination are what the format exists to remove.

Serve it either of two ways.

Serve the ontology at the well-known URI. Then url is that address:

{
"resourceType": "Ontology",
"url": "https://example.org/.well-known/ours.json",
"...": "..."
}

Redirect to where the ontology actually lives. A 301 or 302, whose target is the address in url:

GET https://example.org/.well-known/ours.json
-> 302 https://ours.example.org/ontology.json

The redirect is usually the more convenient of the two, because it leaves the ontology on whatever host already serves your static files while discovery stays on the domain people know you by. The target has to be the value of url, so that a consumer following the redirect ends up somewhere that agrees with itself. Anything else leaves them with two candidate identities and no rule for choosing between them.

Use the domain a consumer would think of first, which is usually the one your public site is on rather than the one your API is on. Somebody integrating with ExampleOrg will try example.org before they try anything else.

The ours suffix is not yet registered with IANA.

Nothing constrains the addresses in models, vocabularies and mappings beyond their being stable and fetchable. A dedicated subdomain keeps the ontology separable from the API it describes, and is the shape the examples here use:

https://ours.example.org/models.json

What the format does require is that every resource is served at the URL in its own url field.