GitHub

SDK reference

Settlement

Issuing receipts, reading them, and verifying one produced by someone else.

issueReceipt(input)

Requires a credential.

const receipt = await path.issueReceipt({
  requestId: '7fk2m9pq3vx8',
  payerMember: 'member-b',
  amount: '5000',
  currency: 'XOF',
  rail: 'mobile_money',
  sourceReference: 'MM-8891-2231',
});

receipt.reference; // "rcpt_9a41c8f2b731"
receipt.signature;
receipt.kid;
FieldNotes
requestIdOptional — a spontaneous payment has no request
sourceTxHashFor rails that have one
sourceReferenceFor rails that do not. At least one of the two
attestationsOptional signed claims travelling with the receipt

Separate from marking a request paid, because payment and proof are two events that can be seconds or hours apart. Conflating them forces every integration to pretend a mobile-money transfer settles as fast as a signature.


readReceipt(reference)

No credential.

const receipt = await path.readReceipt('rcpt_9a41c8f2b731');

Public because a receipt is only useful if a third party can check it — a supplier, an auditor, the payer's own institution. Behind a credential, the only people who could verify a settlement would be the two who already agree about it.


Verifying someone else's

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

const { valid, reason } = await verifyAgainstIssuer(receipt, 'https://api.other-member.com');

The key comes from the issuer's own discovery document. Not from whoever handed you the receipt, and not from a central registry: an operator vouching for another's key rebuilds the hierarchy the protocol avoids, and means compromising one operator compromises statements about others.

Offline

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

const valid = verifyEnvelope(receipt, cachedIssuerPublicKey);

Once you hold the key, verification needs no network at all. That is what lets a receipt be shown as a QR code and checked by someone with no account anywhere — the concrete form of finality is a verifiable state, not a promise.

Unknown key id

const { valid, reason } = await verifyAgainstIssuer(receipt, issuerUrl);
// reason: 'Issuer publishes no key with kid "op_example_2026_02"'

Reported distinctly from a bad signature, because it usually means a rotation you have not picked up. Refetch the issuer's document and try again before concluding anything.


The reserved field

receipt.route; // null, always, in v0.1

Declared on every receipt and never populated. When liquidity routing is specified it will carry the legs, providers and shares.

Carry it through untouched. Do not strip it, and do not reject an object because a newer counterparty populated it — dropping unknown fields is the most common way to break forward compatibility, and it fails silently.

On this page