GitHub

Docs

Quickstart

From nothing to a payment request another wallet can read, in about fifteen minutes.

This walks through the smallest useful integration: issue a payment request, read it back the way a foreign wallet would, and verify who signed it.

Nothing here requires network membership.

1. Install

npm install @pathprotocol/sdk

2. Read an operator's discovery document

Always the first call. It tells you what an operator speaks, what it claims, and — the part worth reading before anything else — how its directory behaves.

import { PathClient } from '@pathprotocol/sdk';

const path = new PathClient({
  baseUrl: 'https://api.example.com',
  apiVersion: '2026-09-09.genesis',
});

const config = await path.discovery();

console.log(config.protocol_versions);   // ["0.1.0"]
console.log(config.conformance);         // ["PATH-ID.Core", "PATH-ADDR.Format", …]
console.log(config.finder.hashing);      // "server_side" | "oblivious"

finder.hashing says whether the network sees the identifiers being searched. server_side means it does. You are entitled to know that before joining, and to decline. See Privacy.

3. Issue a payment request

This needs a member credential, since it creates an object signed in your name.

const path = new PathClient({
  baseUrl: 'https://api.example.com',
  apiVersion: '2026-09-09.genesis',
  credential: {
    kid: 'member_2026_01',
    privateKeyHex: process.env.PATH_MEMBER_KEY!,
    memberSlug: 'your-member',
  },
});

const request = await path.createRequest({
  amount: '5000',
  currency: 'XOF',
  orderReference: 'ord_10482',
  expiresAt: new Date(Date.now() + 86_400_000).toISOString(),
  feeDisclosure: { network_fee: '0', operator_fee: '25', currency: 'XOF' },
});

console.log(request.url);       // https://api.example.com/p/7fk2m9pq3vx8
console.log(request.reference); // 7fk2m9pq3vx8

Leave amount out and the payer chooses — a tip, a donation, an open invoice.

Include feeDisclosure and the fee travels with the terms, shown before the payer commits. A price disclosed after the decision is not a disclosure.

4. Read it as another wallet would

No credential. This is the path a wallet at a different institution takes.

const anyWallet = new PathClient({ baseUrl: 'https://api.example.com' });

const req = await anyWallet.readRequest(request.url);

console.log(req.amount, req.currency);  // "5000" "XOF"
console.log(req.status);                // "created"
console.log(req.issuer);                // "your-member"
console.log(req.fees);                  // { network_fee: "0", … }

5. Verify the signature

The domain that served the link says where it was fetched from. The signature says who is responsible for it — and with delegated hosting those are routinely different parties.

import { verifyAgainstIssuer } from '@pathprotocol/sdk';

const { valid, reason } = await verifyAgainstIssuer(req, 'https://api.example.com');
if (!valid) throw new Error(`Refusing to display: ${reason}`);

Do this before showing a payment screen. Then show the issuer's verified name, never the raw URL — the same reason a card terminal shows a merchant name rather than an acquirer's hostname.

6. Close the loop

When the payment lands, mark the request paid and issue a receipt.

await path.issueReceipt({
  requestId: request.reference,
  amount: '5000',
  currency: 'XOF',
  rail: 'mobile_money',
  sourceReference: 'MM-8891-2231',
});

The receipt is signed and publicly readable, so a third party — an auditor, a supplier, the payer's own institution — can verify it without an account anywhere.

What you just did without joining anything

Read an operator's terms, issued a signed request, read it as a stranger, and verified its origin. That is the relationship profile, and it is a complete path.

The one thing it does not include is finding someone you have no prior relationship with. That needs a directory, and directories belong to networks.

On this page