SDK reference
PathClient
Construction, options, and how the transport handles versions, idempotency and signing.
Construction
import { PathClient } from '@pathprotocol/sdk';
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',
},
timeoutMs: 15_000,
});Options
| Option | Type | Default | Notes |
|---|---|---|---|
baseUrl | string | — | Operator base URL. Trailing slash optional |
apiVersion | string | The version the SDK was built against | Pin it explicitly |
credential | object | none | Omit for public-only use |
fetch | typeof fetch | global | Inject for testing or a custom agent |
timeoutMs | number | 15000 | Aborts the request |
credential
| Field | Notes |
|---|---|
kid | Your key id, as registered with the network |
privateKeyHex | Ed25519 seed, 32 bytes, hex. Never in client code |
memberSlug | Your member slug, used in signed answers |
Calling a credentialed method without one throws before any request is made, with a message naming the option — a network round trip to discover a missing configuration value is wasted time.
What the transport does for you
Versions. Path-Version and Path-Protocol-Version on every request.
Signing. For credentialed calls, builds Path-Key-Id, Path-Timestamp and Path-Signature
over method, path, timestamp and body digest.
Idempotency. Pass a key to createRequest and it becomes Path-Idempotency-Key. A replay
returns the original object — which is what you want on the retry after a timeout, when you do not
know whether the first call landed.
Errors. Non-2xx responses become PathApiError carrying the code, the
message and the request_id.
Timeouts. Via AbortController, so an unreachable operator fails in seconds rather than hanging.
Public without a credential
const anyone = new PathClient({ baseUrl: 'https://api.example.com' });
await anyone.discovery();
await anyone.keys();
await anyone.readRequest('7fk2m9pq3vx8');
await anyone.readReceipt('rcpt_9a41c8f2b731');
await anyone.resolver('path:4a91c2f7e8d3');
await anyone.getCheckoutSession('cs_4b81f2c7');That set is the relationship profile — a complete path from key to capability that requires
membership of nothing.
Methods
| Method | Credential | |
|---|---|---|
discovery() | — | Discovery |
keys() | — | |
sonar(params) | ✓ | Reachability |
resolver(address, endpoint?) | — | |
finder(params) | ✓ | |
createRequest(input, idempotencyKey?) | ✓ | Requests |
readRequest(referenceOrUrl, opts?) | — | |
revokeRequest(reference) | ✓ | |
createCheckoutSession(input) | ✓ | |
getCheckoutSession(id) | — | |
issueReceipt(input) | ✓ | Settlement |
readReceipt(reference) | — |
Multiple operators
One client per operator. They are cheap, hold no connection pool of their own, and keeping them separate avoids the mistake of signing a request to operator B with a credential issued by operator A.
const own = new PathClient({ baseUrl: OUR_API, credential });
const peer = new PathClient({ baseUrl: 'https://api.member-b.com' });