GitHub

Docs

PATH ADDRESS

Opaque, portable addresses; what they point at; and the standing terms on which they receive.

LIVE partially — addresses and receive targets are implemented; standing intent is DRAFT.

The address

Fig. 01 — Address
path:4a91c2f7e8d3

Nothing in it identifies a member, a network, a country or an institution. That is a deliberate trade, and both sides of it are worth stating.

What it buys: portability. A person changes provider — or changes network — and the address follows, because no part of it ever belonged to the institution. This is the strictest reading of "the alias belongs to the person".

What it costs: reachability. Something has to say where to look, and that something is PATH SONAR. An address alone tells a stranger nothing.

The alternative — encoding the member in the address, alice@member.example — makes lookups trivial and makes leaving expensive. Every saved destination breaks on the day someone switches provider, which is precisely the lock-in the protocol exists to remove.

Structural rule

An address is attached to a subject, never to an account. An address bound to a wallet dies with the wallet, and the portability above becomes a slogan. In the reference schema there is no foreign key from an address to any account for exactly this reason.

Rotation

An address can be rotated without changing the underlying identity. The new one is issued, the old one is revoked rather than deleted, and the link between them is kept.

That last point is not bookkeeping. A payer holding a saved destination deserves "this moved" rather than "this never existed" — the second reads as an error on the payer's side, and they will call support about it.

Two profiles

ProfileHow a stranger reaches itRequires
directoryVia a network's indexNetwork membership
relationshipThe counterparty already knows where to askNothing

relationship is not a lesser mode. It is the complete path from key to capability that needs permission from nobody, and it is what makes the protocol's openness checkable rather than asserted. A platform and its payment provider, two institutions with an agreement — they use it and join nothing.

Receive targets

What an address actually points at inside the member.

{
  "address_id": "addr_71bc",
  "targets": [
    { "kind": "p2p_wallet",  "asset": "USDC", "chain": "base", "is_default": true },
    { "kind": "va_deposit",  "rail": "mobile_money", "currency": "XOF" },
    { "kind": "external",    "rail": "sepa", "currency": "EUR" }
  ]
}

Targets never leave the member. What a caller sees is the capability summary the resolver returns — what can be sent, within what limits — and never the account identifiers behind it.

Standing intent

DRAFT

The permanent terms on which an address receives.

{
  "version": 3,
  "accepts": [
    { "asset": "USDC", "chain": "base" },
    { "rail": "mobile_money", "currency": "XOF" }
  ],
  "limits": { "max_single": "500000", "currency": "XOF" },
  "policy": { "unknown_sender": "quarantine" }
}

Versioned, never overwritten. A payer may have read version 3 an hour ago and be sending against it now. Overwriting makes it impossible to establish afterwards which terms were actually in force — which is exactly the question a dispute turns on.

Policy beats capability. A member may hold a USDC wallet and still decline USDC this month. The standing intent is the receiver's own statement and wins over what the raw targets imply.

A standing intent is a policyI accept USDC. A payment request is a claimyou owe me 5,000 for order 123. Different speech acts, different pillars. Merging them is how a system ends up unable to expire one or revoke the other.

Inbound states

DRAFT
Fig. 02 — Inbound
ReceivedScreeningMatchedConvertingDeliveredQuarantinedReturningReturnedFrozen
Quarantined exists because on-chain, you cannot decline to receive.

QUARANTINED is the state that has to exist, and the reason is specific to open rails: on-chain, you cannot decline to receive. If tainted funds arrive, the beneficiary already holds them by the time anyone notices. Funds must land in escrow, be screened, and only then trigger conversion — never the other way round.

Two things a specification should say and usually does not: RETURNED is an attempt, not a guarantee — the source may be an exchange hot wallet, a contract with no receive function, or a pooled address. And FROZEN is the terminal state when returning is impossible or legally forbidden, which is a real outcome and better named than improvised.

Resolving

What a caller gets back:

{
  "valid": true,
  "accepts": [{ "asset": "USDC", "chain": "base" }],
  "limits": { "max_single": "500000", "currency": "XOF" },
  "commitment": "8f29…",
  "protocol_version": "0.1.0",
  "signed_at": "2026-09-09T10:00:00Z",
  "kid": "op_example_2026_01",
  "signature": "…"
}

Capability and limits. Never the holder's name, institution, KYC tier or balance. A routing question gets a routing answer — anything more turns a lookup into a disclosure, and the whole privacy model rests on that not happening.

A revoked address answers revoked, not unknown. The payer needs the difference: one means try another route, the other means you have the wrong destination.


On this page