Docs
Discovery
What an operator publishes about itself, why it is unauthenticated, and the fields a prospective member should read first.
The document
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.1.0"],
"api_versions": ["2026-09-09.genesis"],
"api_version_latest": "2026-09-09.genesis",
"operator": {
"slug": "example-member",
"domain": "api.example.com",
"jurisdiction": "SN"
},
"network": {
"slug": "example-network",
"legal_name": "Example Network Foundation",
"rulebook": { "url": "https://…", "version": "1.0" }
},
"conformance": [
"PATH-CORE.Discovery",
"PATH-ID.Core",
"PATH-ADDR.Format",
"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",
"receipts": "https://api.example.com/api/path/v1/receipts",
"keys": "https://api.example.com/.well-known/path-keys"
},
"capabilities": {
"address_profiles": ["directory", "relationship"],
"identifier_types": ["phone", "email", "bank_account", "lei", "reg", "tax"],
"interop_kinds": ["pay", "request", "checkout", "connect", "mandate", "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": ["+221", "+225"], "reg": ["SN"] }
},
"reserved": {
"liquidity": { "route_field": "declared", "populated": false }
}
}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.
| Field | What it tells you |
|---|---|
hashing | server_side means the network sees the identifiers being searched. oblivious means it does not |
sonar_mode | central — the network answers. broadcast — members ask each other |
sonar_access | member_credential or open |
holder_confirmation | Whether you co-sign answers about your own customers |
search_log_retention_days | How long searches are kept |
coverage | What this member may hold — countries, prefixes, identifier types |
hashing: server_side is the honest declaration of a real exposure, not a defect to hide. A member
is entitled to read it before joining and to decline. 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
{
"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.