Resolvable URLs

Every public version has one canonical URL to cite and share. It’s a linked-data “cool URI”: it resolves to a human page in a browser and to RDF for a machine.

Two different identifiers#

Don’t confuse these two URLs — they mean different things:

  • Your ontology’s own IRI — whatever you declared with owl:Ontology, e.g. http://example.org/health. This is your ontology’s real-world identity. It’s what other ontologies owl:imports to depend on you, and Ontoshire never rewrites it — see Imports & dependencies for how that identity is used to resolve dependencies by exact string match.
  • Ontoshire’s coordinate URL, /o/{owner}/{repo}/{version} — a citeable address for this specific published version, minted by Ontoshire at publish time. It exists regardless of what IRI (if any) the ontology declares internally, and it’s what the rest of this page describes.

The two often look unrelated — http://purl.obolibrary.org/obo/uberon.owl published as obolibrary/uberon resolves at /o/obolibrary/uberon/v1.0.0 — and that’s expected: an ontology’s identity is independent of who hosts it or where.

The canonical URL#

The metadata card on a version page surfaces it as Public URL:

canonical URL
https://ontoshire.com/o/{owner}/{repo}/{version}

# e.g.
https://ontoshire.com/o/acme/health/v1.2.0

This is also the URL the published DCAT manifest points at, so a tool that reads the manifest can dereference each distribution directly.

Content negotiation#

The same URL serves people and machines — it branches on the Accept header:

content negotiation
# Browser (Accept: text/html) → 303 redirect to the human page
curl -IL https://ontoshire.com/o/acme/health/v1.2.0

# Machine → the graph, in the serialization you ask for
curl -L -H "Accept: text/turtle"        https://ontoshire.com/o/acme/health/v1.2.0
curl -L -H "Accept: application/ld+json" https://ontoshire.com/o/acme/health/v1.2.0

# Or force a format explicitly (turtle | rdfxml | jsonld | ntriples)
curl -L https://ontoshire.com/o/acme/health/v1.2.0?format=jsonld

An empty or wildcard Accept defaults to Turtle. An explicit ?format= always wins over the header and skips negotiation entirely — this is what the manifest’s own dcat:downloadURLs use internally, so a tool reading the manifest never has to think about content negotiation at all.

The negotiation rule precisely: only an exact media-type match counts (a wildcard like */* or text/* never wins a specific type on its own) — among the types that do match exactly, HTML wins if its quality value is at least as high as the best matching RDF type’s; otherwise the highest-quality matching RDF type is served. A browser’s default Accept heavily favours HTML, so a plain visit gets the human page; a bare curl with no Accept header at all falls into the wildcard case and gets Turtle. The RDF response also carries Link: <…/ontologies/…>; rel="alternate"; type="text/html" pointing back at the human page, for tooling that wants to offer “view in browser”.

The shapes URL#

When a version ships SHACL shapes, they get their own canonical URL — surfaced as Shapes URL — that negotiates the same way:

shapes URL
https://ontoshire.com/o/acme/health/v1.2.0/shapes

The manifest URL#

The resolved DCAT manifest — surfaced as Manifest URL — lives alongside the two above:

manifest URL
https://ontoshire.com/o/acme/health/v1.2.0/manifest

It negotiates too — text/turtle, application/ld+json, or application/n-triples (an explicit ?format= works the same way as the URLs above). Two differences from the ontology/shapes URLs: there’s no HTML view to redirect a browser to (a manifest isn’t a page, so an empty/wildcard Accept — including a plain browser visit — gets Turtle), and RDF/XML isn’t offered for this one.

Private versions#

Public versions only. These URLs are for public ontologies. A private version resolves only for its owner in a signed-in browser session; to anyone else it returns 404 — indistinguishable from one that doesn’t exist. For programmatic pulls of your own private schemas, use the validation client with a token.

This is a deliberate design rule, applied identically across every one of these endpoints — the ontology, shapes, and manifest URLs, plus the dependency graph: forbidden and nonexistent must be indistinguishable. A 404 never tells you which one it was, because either answer could leak the existence of a private registration you have no business knowing about. There is no separate “403 Forbidden” response anywhere in this system for that reason.