Skip to content

How it works

Discovery starts at a domain and fetches outward from it. A consumer needs to be given example.org and nothing else; everything after that follows from what each document says.

The ontology lives at a well-known URI, so a consumer can go straight to it rather than being told where to look. Many publishers redirect from there to wherever the file actually lives.

Terminal window
curl -L https://example.org/.well-known/ours.json

It is the root document. It carries the publisher’s identity and three pointers: where the models live, where the vocabularies live, and where the mappings live.

{
"resourceType": "Ontology",
"id": "example-org",
"url": "https://ours.example.org/ontology.json",
"version": "1.0.0",
"publisher": "ExampleOrg",
"models": "https://ours.example.org/models.json",
"vocabularies": "https://ours.example.org/vocabularies.json",
"mappings": "https://ours.example.org/mappings.json"
}

All three pointers are required, including from a publisher who has none of something. The reason is that a consumer cannot tell an omitted pointer from one that has not been published yet, and would have to guess whether to keep looking. An empty bundle at a live URL is a definite answer.

Each pointer resolves to a document, and a document is either one resource or a Bundle collecting several. A consumer fetches only what the integration in front of it calls for. Reconciling two systems’ patient records means fetching the model for a patient, not the whole catalogue.

Terminal window
curl https://ours.example.org/models.json

Publishers legitimately choose differently here. One serves a bundle of every model; another serves a file per model and a bundle that lists them. Readers handle both, so the choice is a publishing convenience rather than something a consumer has to be told.

A model says what it means, points at its JSON Schema, and lists what it aligns to through mapsTo. Each alignment names an external system, the external schema it corresponds to, how closely the correspondence holds, and, where one exists, a mapping document that performs the conversion.

{
"resourceType": "Model",
"id": "person",
"url": "https://ours.example.org/models/person.json",
"version": "1.0.0",
"system": "internal",
"name": "Person",
"schema": "https://api.example.org/schemas/User.schema.json",
"mapsTo": [
{
"system": "http://hl7.org/fhir",
"schema": "http://hl7.org/fhir/StructureDefinition/Patient",
"mapping": "https://ours.example.org/mappings/user-to-fhir-patient.json",
"type": "one-to-one"
}
]
}

type is worth reading before the data is. A consumer about to transform across a partial alignment learns that the result will be lossy here, rather than from the gaps in the output.

The document at mapping is a FHIR StructureMap or ConceptMap. Because it is ordinary FHIR, a mapping engine can execute it without being told anything about OURS, and a consumer that already speaks FHIR needs no new machinery to convert the data.

A publisher who has described an alignment but not yet written a transformation for it leaves mapping off that entry. There the absence reads cleanly: the alignment is right in front of the consumer, so leaving the mapping out says “no executable map for this one” without ambiguity.

Nothing in the sequence required the publisher and the consumer to have spoken. The publisher put files at URLs, one of which anybody can guess from the domain alone. The consumer fetched them in the order the files themselves dictate.

That is the whole of the coordination, and it is why the ontology has to be complete enough to answer questions rather than merely correct about the ones it happens to answer. A consumer who has to come and ask you something has already lost the thing the format was for.

Publish an ontology goes through the same sequence from the other side.