Skip to main content

Protocol specification

HTML fallback

Embed OLPN JSON in a page's HTML when serving a separate file isn't practical.

Some hosts can't serve arbitrary JSON files at arbitrary paths. Ghost, for example, serves page and post templates but has no way to expose a static JSON file at /olpn.json. OLPN supports an HTML fallback: embed the same document body in a <script> tag on the page the JSON would have lived at, and the resolver will extract it.

Fetch order

For each document type, the resolver attempts the JSON URL first, then falls back to the HTML embed.

  1. Entity: {domain}/olpn.json, then {domain}/ (HTML with <script id="olpn-hub">).
  2. Property: {domain}/olpn-property.json, then {domain}/ (HTML with <script id="olpn-property">).
  3. Credential: {issuer}/{user}/olpn-credential.json, then {issuer}/{user}/ (HTML with <script id="olpn-credential">).

Script tag format

Each script tag is a standard HTML element with three attributes and a JSON payload:

<script id="olpn-hub" type="application/json">
{
  "version": "0.9",
  "network_id": "§:entity:example.com",
  "entity_type": "person",
  "details": { "name": "Example" },
  "properties": [],
  "credentials": [],
  "other_connections": []
}
</script>

The three IDs map to the three document types:

  • id="olpn-hub" — entity document payload. Body matches the shape of olpn.json.
  • id="olpn-property" — property document payload. Body matches olpn-property.json.
  • id="olpn-credential" — credential document payload. Body matches olpn-credential.json.

Attribute order

The resolver accepts both orderings of the id and type attributes. Any of these four forms is valid:

<script id="olpn-hub" type="application/json">...</script>
<script type="application/json" id="olpn-hub">...</script>
<script id='olpn-hub' type='application/json'>...</script>
<script type='application/json' id='olpn-hub'>...</script>

Single and double quotes are both accepted. No other attribute variations are supported. In particular, type="text/json" or missing type will cause the regex match to fail.

Placement in the page

The script tag can appear anywhere in the HTML. The resolver fetches the page, runs a regex over the full body, and parses the first match. We recommend placing it in <head> for cache-friendliness, but <body> works equally well.

Example: Ghost homepage with embedded entity

<!DOCTYPE html>
<html>
<head>
  <title>Example Firm</title>
  <script id="olpn-hub" type="application/json">
  {
    "version": "0.9",
    "network_id": "§:entity:example-firm.com",
    "entity_type": "organization",
    "details": {
      "name": "Example Firm",
      "legal_name": "Example Firm LLP",
      "domain": "example-firm.com"
    },
    "properties": [
      {
        "id": "§:property:example-firm.com",
        "url": "https://example-firm.com",
        "type": "Law Firm Website",
        "ownership": [
          { "network_id": "§:entity:example-firm.com" }
        ]
      }
    ],
    "credentials": []
  }
  </script>
</head>
<body>
  <h1>Example Firm</h1>
</body>
</html>

When to use which

Serve the JSON file directly when you can. It is cheaper to fetch, easier to cache, and does not require parsing HTML. Use the script tag only when your host makes the direct file impractical. A site can publish both without conflict; the resolver will prefer the JSON file.