GitHub

Docs

Discovery

What an operator publishes about itself, why it is unauthenticated, and the fields a prospective member should read first.

LIVE

The document

Fig. 01 — Discovery

Unauthenticated, always. Anyone considering an integration has to read it before there is a relationship to authenticate. A discovery document behind a key is a brochure.

{
  "protocol_versions": ["0.2.0", "0.1.0"],
  "protocol_version_latest": "0.2.0",
  "api_versions": ["2026-09-09.genesis", "2026-10-04.genesis"],
  "api_version_latest": "2026-10-04.genesis",

  "operator": {
    "slug": "example-member",
    "domain": "api.example.com",
    "jurisdiction": "US"
  },

  "network": {
    "slug": "example-network",
    "legal_name": "Example Network Foundation",
    "rulebook": { "url": "https://…", "version": "1.0" }
  },

  "conformance": [
    "PATH-CORE.Discovery",
    "PATH-ID.Core",
    "PATH-ID.Attestations",
    "PATH-ID.Ownership",
    "PATH-ADDR.Format",
    "PATH-ADDR.Standing",
    "PATH-ADDR.Targets",
    "PATH-REQ.Link",
    "PATH-FINDER.Relationship",
    "PATH-SETTLE.Receipts"
  ],

  "endpoints": {
    "sonar": "https://api.example.com/api/path/v1/sonar",
    "resolver": "https://api.example.com/api/path/v1/resolver",
    "finder": "https://api.example.com/api/path/v1/finder",
    "requests": "https://api.example.com/api/path/v1/requests",
    "attestations": "https://api.example.com/api/path/v1/attestations",
    "ownership": "https://api.example.com/api/path/v1/ownership-bindings",
    "receipts": "https://api.example.com/api/path/v1/receipts",
    "keys": "https://api.example.com/.well-known/path-keys"
  },

  "hosts": ["api.example.com", "pay.example.com"],

  "capabilities": {
    "address_profiles": ["directory", "relationship"],
    "identifier_types": ["phone", "email", "bank_account", "lei", "reg", "tax"],
    "interop_types": ["path.address", "path.request", "path.checkout", "path.receipt"]
  },

  "finder": {
    "sonar_mode": "central",
    "holder_confirmation": "required",
    "sonar_access": "member_credential",
    "hashing": "server_side",
    "hash_function": "argon2id",
    "discoverability_levels": ["private", "network", "public"],
    "search_log_retention_days": 30,
    "coverage": { "phone": ["+1"], "reg": ["US"] }
  },

  "gateway": {},

  "reserved": {
    "liquidity": { "route_field": "declared", "populated": false }
  }
}

endpoints are absolute URLs, chosen by the operator. The paths above are the reference implementation's mount, under /api/path/v1. Another operator publishes different paths. A client calls the URL it was given. GET /.well-known/path-configuration, GET /.well-known/path-keys and GET /path/{reference} are the paths the protocol fixes.

Read the finder block first

If you are evaluating whether to join a network, this block is the material part. Everything else is capability; this is terms.

FieldWhat it tells you
hashingserver_side means the network sees the identifiers being searched. oblivious means it does not
sonar_modecentral — the network answers. broadcast — members ask each other
sonar_accessmember_credential or open
holder_confirmationWhether you co-sign answers about your own customers
search_log_retention_daysHow long searches are kept
coverageWhat this member may hold — countries, prefixes, identifier types

gateway is not coverage

Two blocks, two meanings.

SaysAbout
finder.coveragewhich of my own entries a broadcast search should reach me formy customers
gatewaywhich rails I can reach destinations on that are not my customersstrangers
"gateway": { "pix": ["+55"] }

This is where a gateway is advertised, and the only place. A member reaching non-customers is not registered in a directory index. A rail footprint is information the member already publishes. Who holds a given key is other people's customers. A gateway does not appear in a SONAR answer.

Empty here, and PATH-FINDER.Gateway is not declared.

hashing: server_side means the network sees the identifiers being searched. A member is entitled to read that before joining. See Privacy.

Declaring is committing

A profile announced and not honoured is a non-conformity, not an approximation. The conformance suite exists to contradict a declaration, and a third party can run it without asking permission.

This is what makes conformance worth more than a marketing claim: it is falsifiable.

Keys

Fig. 02 — Keys
GET /.well-known/path-keys
{
  "keys": [
    {
      "kid": "op_example_2026_01",
      "kty": "OKP",
      "crv": "Ed25519",
      "alg": "EdDSA",
      "use": "sig",
      "public_key_hex": "…"
    }
  ]
}

A verifier reads the kid from an envelope and fetches the matching key from the issuer's own document. Never from a third party, never from whoever served the envelope — an operator vouching for another's key rebuilds the hierarchy the protocol avoids.

Rotation is publish-then-switch. The new key appears alongside the old, then new envelopes carry the new kid. Old envelopes stay verifiable. Retire a key only once nothing in circulation still references it.

Caching

The document SHOULD be cached, and MUST be refetched when an envelope arrives with an unknown kid — that is the signal of a rotation you have not picked up, and it is distinct from a bad signature.

A sensible default is an hour, with a refetch on unknown kid.

Signing the document

An operator MAY sign the document itself, so its content does not rest on TLS alone. Where it does, the signature covers the whole document and uses a key published in the same path-keys endpoint.


On this page