---
title: SDK API reference
description: The full public surface of @piprail/sdk — every export grouped by job, with the headline APIs marked and a link to where each one is documented.
sidebar:
  order: 1
---

## Introduction

This is the map of everything `@piprail/sdk` exports — grouped by the job it does, with the
**headline** APIs marked and the **advanced** tiers (wire codecs, low-level `exact`, the driver
SPI) kept clearly separate. Each group links to the page that documents it in full.

Two entry points cover the 99% case: **`requirePayment` / `createPaymentGate`** to *get paid*,
and **`PipRailClient`** to *pay*. Everything else is built on those.

```ts
import { requirePayment, PipRailClient } from '@piprail/sdk'
```

## Accept payments (server side)

The server-side surface. `requirePayment` is Express/Connect middleware; `createPaymentGate` is
the same logic, framework-free.

| Export | Kind | Marked |
| --- | --- | --- |
| `requirePayment` | fn | **Headline** |
| `createPaymentGate` | fn | **Headline** |
| `deliverReceipt` | fn | Reliable receipt webhook — signed + retried POST to **your** endpoint |
| `toInvalidBody` | fn | Deprecated |
| `RequirePaymentOptions`, `AcceptOption`, `ExactRailOption` | type | carries `onPaid` / `onPaidError` / `awaitOnPaid` **and their failure mirrors `onFailed` / `onFailedError` / `awaitOnFailed`**; `mimeType` (→ v2 `resource.mimeType` + the self-describe `endpoint`) |
| `ChainSelector`, `TokenInput` | type | — |
| `PaymentGate`, `VerifyPaymentResult` | type | — |
| `PaidReceipt` | type | The enriched receipt `onPaid` receives |
| `FailedPayment` | type | The failure object `onFailed` receives — `{ code, detail, transient }` (the mirror of `PaidReceipt`) |
| `DeliverReceiptOptions`, `DeliverAttempt`, `DeliverResult` | type | — |
| `X402InvalidBody` | type | — |
| `ExpressLike{Request,Response,Next,Middleware}` | type | — |

See [requirePayment & createPaymentGate](/accepting-payments/require-payment-and-gate/),
[Defining accepts](/accepting-payments/defining-accepts/),
[Verifying payments](/accepting-payments/verifying-payments/), and
[Receipts & onPaid](/accepting-payments/receipts-and-onpaid/) (the `PaidReceipt`, `onPaidError`,
`awaitOnPaid`, and `deliverReceipt` — plus the failure mirror `onFailed` / `FailedPayment` /
`onFailedError` / `awaitOnFailed`, fired when a submitted proof is rejected).

:::note
`onFailed` is the exact mirror of `onPaid`: it fires only when a SUBMITTED proof is **rejected**
(a `kind:'invalid'` verdict from `gate.verify()` — wrong amount, expired, replayed, unknown asset,
wrong recipient, bad signature, …), never on a normal no-proof first-request 402 and never when
`verify()` *throws* (a transient RPC blip or a 5xx `SettlementError` isn't a verdict). The
`FailedPayment` it receives carries the SAME machine `code` the buyer's client is told, so both
sides see one consistent reason. `transient` is `true` only for the two transient codes
(`tx_not_found` / `insufficient_confirmations`) — the proof may still be settling and the buyer
auto-retries, so alert on `!transient`. See
[Why payments fail](/errors/why-payments-fail/) and [VerifyErrorCode](/errors/verify-error-code/).
:::

## Pay (agent side)

The client. One `PipRailClient` binds a chain + wallet and exposes the read-only trio
(`quote` → `estimateCost` → `planPayment`) plus `fetch`. `MultiChainPayer` carries one wallet
per chain and auto-routes a 402 to whichever chain can settle it.

| Export | Kind | Marked |
| --- | --- | --- |
| `PipRailClient` | class | **Headline** |
| `MultiChainPayer` | class | **Headline** — one buyer, a wallet per chain |
| `planAcross`, `fetchAcross` | fn | plan / pay across an array of single-chain clients |
| `PipRailClientOptions`, `MultiChainPayerOptions`, `WalletInput`, `PaymentScheme` | type | — |
| `PayingClient` | type | the read-+-pay surface both `PipRailClient` and `MultiChainPayer` satisfy |
| `PipRailQuote`, `PipRailCostQuote`, `PipRailEvent` | type | the `payment-failed` event gained `code?` / `detail?` and ALSO fires on a pre-send DECLINE (policy / `onBeforePay` / no settleable rail) |
| `PaymentPlan`, `PayOption`, `PayBlocker`, `PayWarning` | type | — |
| `SessionBudget`, `SpendRemaining` | type | — |

See [Quote](/making-payments/quote/), [Estimate cost](/making-payments/estimate-cost/),
[planPayment()](/making-payments/plan-payment/),
[fetch & autoRoute](/making-payments/fetch-and-autoroute/),
[Multi-chain buying](/making-payments/multi-chain/),
[Events](/making-payments/events/), and [Wallets by family](/making-payments/wallets-by-family/).

:::tip
The `payment-failed` event (on `onEvent`) now carries an optional `code?` + `detail?`. On a
**server rejection** that's the SAME canonical `code` the merchant's `onFailed` hook receives (a
[VerifyErrorCode](/errors/verify-error-code/)); on a **pre-send client decline** it's the decline
reason (e.g. `'BUDGET'` / `'APPROVAL'` / `'MAX_AMOUNT'`). `payment-failed` also fires on those
pre-send declines now (policy, `onBeforePay`, or no settleable rail) — previously those *only*
threw. The typed `PaymentDeclinedError` throw is unchanged and zero funds still move, so a consumer
watching `onEvent` alone now learns of **every** failure type, not just server rejections. See
[Events](/making-payments/events/).
:::

## Spend controls

The policy + ledger primitives. `evaluatePolicy` is the pure decision function the client and
MCP both call before any spend. The ledger + store are how caps survive a restart and span chains
— still no backend, no database, no fee: `SpendLedger` is in-memory and a `SpendStore` is a
caller-owned file (or anything you implement).

| Export | Kind | Marked |
| --- | --- | --- |
| `evaluatePolicy` | fn | **Headline** |
| `SpendLedger` | class | Share one across several clients for a cross-chain grand total (`MultiChainPayer.fromWallets` wires it for you) |
| `memorySpendStore` | fn | A `SpendStore` backed by an in-memory array — `memorySpendStore(seed?)`; from `@piprail/sdk` |
| `fileSpendStore` | fn | A durable JSONL `SpendStore` — `fileSpendStore(path)`; from `@piprail/sdk/node` (Node-only, keeps `node:fs` out of the browser bundle) |
| `denomOf` | fn | Pure — `denomOf(symbol, asset, policy)` → the unit a token folds into, or none |
| `BUILTIN_DENOMS`, `DENOM_PRECISION` | const | the built-in symbol→unit map (USDC/USDT/USD1/FDUSD/RLUSD → `'USD'`, EURC → `'EUR'`) and the fixed-point precision (`24`) |
| `PaymentPolicy`, `PaymentIntent`, `PolicyDecision`, `PolicyDenyCode` | type | `PaymentPolicy` gained `maxTotalPerDenom` / `denomFor` / `maxPayments` / `maxPaymentsPerWindow` / `warnAtFraction`; `PolicyDenyCode` gained `MAX_TOTAL_DENOM` / `MAX_PAYMENTS` / `WINDOW_COUNT` |
| `SpendStore` | type | `{ load(): SpendRecord[]; append(record): void }` — pass as the client's `spendStore` to persist the ledger (never throws) |
| `SpendRecord`, `SpendSummary`, `SpendAssetTotal`, `SpendDenomTotal` | type | `SpendSummary` gained `byDenom: SpendDenomTotal[]`; `SpendRecord` gained optional `decimals` / `denom` |
| `DenomRemaining`, `CountStatus` | type | the per-denomination remaining row + the payment-count status `SessionBudget` now also reports |

See [Payment policy](/spend-controls/payment-policy/),
[Total budget](/spend-controls/total-budget/),
[Time envelope](/spend-controls/time-envelope/),
[evaluatePolicy()](/spend-controls/evaluate-policy/), and
[Spend ledger](/spend-controls/spend-ledger/).

## Agent toolkit

`paymentTools(client)` returns the tool set an autonomous LLM drives; the renderers and guide
make a bound client legible to the model.

| Export | Kind | Marked |
| --- | --- | --- |
| `paymentTools` | fn | **Headline** |
| `AgentTool`, `ToolAnnotations` | type | — |
| `summarizePlan`, `explainDecline`, `formatSpendReport`, `describeChallenge` | fn | — |
| `PIPRAIL_AGENT_GUIDE`, `agentGuide` | const / fn | — |
| `classifyChallenge` | fn | — |
| `ChallengeTriage`, `ChallengeVerdict` | type | — |
| `buildSelfDescription`, `buildEndpointInfo`, `BRAND` | fn / const | the `extensions.piprail` self-description builder, the `endpoint` sub-block assembler, + brand single-source-of-truth |
| `SelfDescription`, `SelfDescribeRail`, `SelfDescribeEndpoint` | type | the self-describe block, a rail in it, and the agent-readable `endpoint` (summary/input/output) |

See [Payment tools](/agent-toolkit/payment-tools/), [The 7 tools](/agent-toolkit/the-7-tools/),
[Renderers](/agent-toolkit/renderers/), [Agent guide](/agent-toolkit/agent-guide/), and
[Challenge triage](/agent-toolkit/challenge-triage/).

## Chains

`CHAINS` is the built-in EVM mainnet registry (each preset carries its canonical token
addresses); `resolveChain` turns a `chain` value into a `ResolvedChain`.

| Export | Kind |
| --- | --- |
| `CHAINS`, `resolveChain` | const / fn |
| `ChainInput`, `ChainName`, `ResolvedChain` | type |
| `ChainPreset`, `TokenInfo` | type |

See [Chains overview](/chains/overview/) and [Chains & tokens](/concepts/chains-and-tokens/).

## Discovery

Be found, and find others — on the open x402 indexes, with nothing PipRail-hosted. The builders
are pure (emit static artifacts); the `register*` / `searchOpenIndexes` functions talk to the
free public directories.

| Export | Kind |
| --- | --- |
| `buildOpenApi`, `buildWellKnownX402`, `buildX402DnsTxt`, `buildBazaarExtension`, `GENERATOR` | fn / const |
| `discoveryHeaders`, `POWERED_BY`, `renderLandingPage` | fn / const | self-describing HTTP surfaces — the Link/`x-powered-by` header bag + the human HTML landing page |
| `searchOpenIndexes`, `register402Index`, `registerX402Scan` | fn |
| `claim402IndexDomain`, `verify402IndexDomain` | fn |
| `normalizeNetwork`, `getDirectoryInfo`, `decorateOutcome`, `DIRECTORY_INFO` | fn / const |
| `rankResources`, `scoreResource` | fn | client-side relevance ranking of merged results (the engine behind a multi-word `discover()` query) |
| `appendKeywords` | fn | fold `tags` into a description as a searchable `· Keywords: …` tail (402 Index search is literal) |
| `appendAttribution`, `REGISTER_ATTRIBUTION` | fn / const | the opt-in `· Built with @piprail/sdk` listing marker |
| `PaymentRail`, `ResourceDescription`, `ManifestInput` | type | `ResourceDescription` carries an optional `mimeType` (v2 ResourceInfo) |
| `OpenApiDocument`, `OpenApiOperation`, `WellKnownX402`, `X402DnsRecord` | type |
| `DiscoveryDescriptor`, `BazaarExtension` | type | `DiscoveryDescriptor` gained `summary` — feeds both `extensions.bazaar` and `extensions.piprail.endpoint` |
| `DiscoverySource`, `DiscoverySort`, `DiscoveredRail`, `DiscoveredResource` | type | `DiscoveredResource` gained `tags` / `reliabilityScore` / `health` / `verified` / `score` |
| `RegisterOutcome`, `RegisterInput`, `SearchOpenIndexesOptions` | type | `RegisterInput` + `SearchOpenIndexesOptions` gained the category / tags / asset / reliability / sort fields |
| `DirectoryInfo`, `ListingVisibility`, `DomainClaim`, `DomainVerification` | type |
| `DiscoverOptions`, `RegisterOptions` | type | `DiscoverOptions` gained category / asset / minReliability / verified / paymentValid / sort / order; `RegisterOptions` gained category / tags / provider / contactEmail / probeBody |

See [Discover & register](/discovery/discover-and-register/),
[Open indexes](/discovery/open-indexes/), [Emitters](/discovery/emitters/), and
[Domain verification](/discovery/domain-verification/).

## Errors

Every thrown error is a typed `PipRailError` subclass with a stable `.code`.

| Export | Kind |
| --- | --- |
| `PipRailError` | class (base) |
| `InsufficientFundsError`, `RecipientNotReadyError` | class |
| `WrongChainError`, `WrongFamilyError`, `UnknownTokenError` | class |
| `MissingDriverError`, `UnsupportedNetworkError`, `UnsupportedSchemeError` | class |
| `PaymentTimeoutError`, `ConfirmationTimeoutError`, `MaxRetriesExceededError` | class |
| `PaymentDeclinedError`, `InvalidEnvelopeError`, `NoCompatibleAcceptError` | class |
| `NonReplayableBodyError`, `SettlementError`, `WalletRequiredError` | class |
| `toInsufficientFundsError` | fn |
| `DeclineReasonCode` | type |

See [Error model](/errors/error-model/), [Error hierarchy](/errors/error-hierarchy/),
[VerifyErrorCode](/errors/verify-error-code/), and [Why payments fail](/errors/why-payments-fail/).

## Advanced: wire codecs

The raw envelope codecs, for building a client or server by hand. `PipRailClient` and
`createPaymentGate` cover the 99% case — reach for these only when you're hand-rolling the wire
format (server: `buildChallengeHeader` → verify → `buildReceiptHeader`; client: `parseChallenge`
→ `buildSignatureHeader` → `parseReceipt`).

| Export | Kind |
| --- | --- |
| `pickAccept` | fn |
| `parseChallenge`, `parseReceipt`, `parseSettleResponse` | fn |
| `parseSignatureHeader`, `parseExactPaymentHeader` | fn |
| `buildChallengeHeader`, `buildSignatureHeader`, `buildExactSignatureHeader`, `buildReceiptHeader` | fn |
| `HEADER_REQUIRED`, `HEADER_SIGNATURE`, `HEADER_RESPONSE`, `HEADER_SIGNATURE_V1`, `HEADER_RESPONSE_V1` | const |
| `Caip2`, `AssetId`, `AddressId` | type |
| `VerifyResult`, `VerifyErrorCode` | type |
| `X402AcceptEntry`, `X402ExactAcceptEntry`, `X402AnyAccept`, `X402Challenge` | type |
| `X402PaymentSignature`, `X402Receipt`, `X402ResourceObject`, `SettleOutcome` | type |
| `ExactAuthorizationWire`, `ExactPaymentPayload`, `ParsedExactPayment` | type |

See [Wire codecs](/reference/wire-codecs/) and [VerifyErrorCode](/errors/verify-error-code/).

## Advanced: low-level exact (EVM — EIP-3009 + Permit2)

The standard x402 `exact` scheme at the codec tier. For the high-level paths use
`PipRailClient({ schemes: ['exact'] })` (buyer) or `createPaymentGate({ exact })` (seller) — these
exports are for hand-rolled clients, v1 servers, and custom flows. The `exact` scheme has six
asset-transfer methods: **EIP-3009** (`transferWithAuthorization`, on EVM tokens that implement it) and
**Permit2** (for EVM ERC-20s that don't — e.g. Binance-Peg USDC/USDT on BNB), plus **SVM** (Solana —
any SPL token, the merchant is the fee payer), **Algorand**, **Aptos**, and **NEAR** on their respective
L1s. The codecs in the table below are the EVM tier (EIP-3009 + Permit2); the non-EVM payloads — SVM's
`{ transaction }` shape (`ExactSvmPaymentPayload`), Algorand (`ExactAlgorandPaymentPayload`), Aptos
(`ExactAptosPaymentPayload`), NEAR (`ExactNearPaymentPayload`) — are built/verified inside their
respective drivers. See [Gasless payments](/making-payments/gasless-payments/).

| Export | Kind | Note |
| --- | --- | --- |
| `parseExactRequirements`, `chainIdForExactNetwork`, `encodeXPaymentHeader` | fn | EVM tier |
| `readExactDomain`, `eip3009Abi` | fn / const | reads/uses a token's true on-chain EIP-712 domain (EVM) |
| `EXACT_NETWORK_SLUGS`, `EIP3009_TYPES` | const | — |
| `PERMIT2_ADDRESS`, `X402_EXACT_PERMIT2_PROXY`, `PERMIT2_WITNESS_TYPES` | const | Permit2 method: the canonical Permit2 + x402ExactPermit2Proxy + witness types |
| `PERMIT2_PROXY_CHAIN_IDS`, `isPermit2ProxyChain` | const / fn | EVM chains where the x402 Permit2 proxy is deployed (where the Permit2 exact method can settle) |
| `buildExactAuthorization` | fn | Deprecated — trusts the server-supplied domain |
| `ExactAccept`, `ExactAuthorization`, `BuildExactParams` | type | — |
| `Permit2Authorization`, `Permit2PaymentPayload`, `ExactPaymentPayloadAny` | type | the per-method wire payloads (EIP-3009 / Permit2 / SVM / Algorand / Aptos / NEAR); `ParsedExactPayment` is a union on `method` (`'eip3009'`/`'permit2'`/`'svm'`/`'algorand'`/`'aptos'`/`'near'`) |

## Advanced: exact facilitator (Mode B) — `facilitator.js`

The Mode-B facilitator path (`createPaymentGate({ exact: { settle: { facilitator } } })`) delegates
verify + settle to a third-party facilitator you choose. PipRail hosts nothing.

| Export | Kind | Note |
| --- | --- | --- |
| `settleViaFacilitator` | fn | Run the two-POST verify→settle contract against a facilitator URL. |
| `parseFacilitatorSupported`, `facilitatorCoverage` | fn | Read a facilitator's `GET /supported` → which (scheme, network) pairs it settles (never throws). |
| `KNOWN_FACILITATORS`, `knownFacilitatorsFor`, `firstKeylessFacilitator` | const / fn | The keyless-facilitator coverage data map (which keyless facilitator settles `exact` on a network). |
| `FacilitatorConfig` | type | The facilitator's base `url` + optional `authHeaders` provider. |
| `FacilitatorPaymentRequirements` | type | The trusted `exact` requirements posted to the facilitator. |
| `SettleViaFacilitatorInput`, `FacilitatorSupportedKind`, `KnownFacilitator` | type | input to `settleViaFacilitator`; the `/supported` kinds; a coverage-map entry. |

See the [exact rail (seller)](/accepting-payments/exact-rail-seller/) page for how to wire it, and
[Facilitator coverage](/accepting-payments/facilitator-coverage/) for the keyless-facilitator data map.

See [Low-level exact](/reference/exact-lowlevel/),
[exact rail (seller)](/accepting-payments/exact-rail-seller/), and
[exact (buyer)](/making-payments/exact-buyer/).

## Advanced: driver SPI

Bring your own chain family. `registerDriver` adds a family that implements the `PaymentDriver`
contract; the rest are the contract's types.

| Export | Kind |
| --- | --- |
| `registerDriver` | fn |
| `PaymentDriver`, `ChainFamily` | type |
| `ResolvedNetwork`, `ResolveOptions`, `ResolvedToken`, `CostEstimate` | type |
| `WalletHandle`, `WalletBalance`, `DiscoverySigner`, `ConfirmInfo` | type |
| `RecipientReason` | type |
| `EvmToken`, `SolanaToken`, `TonToken`, `StellarToken`, `XrplToken` | type |
| `TronToken`, `NearToken`, `SuiToken`, `AptosToken`, `AlgorandToken` | type |

See [Driver SPI](/reference/driver-spi/) and
[PaymentDriver architecture](/concepts/payment-driver-architecture/).

:::note
The public API is exactly what `@piprail/sdk` re-exports from its entry point. Anything reachable
only by deep-importing an internal module is not part of the contract and may change without a
major version bump.
:::
