Documentation
Reference
The SDK, the CLI, and what a server needs to get paid. Each package in the repository also carries a README with setup, environment, and test commands.
@payhole/sdk
Node 22 or newer. The x402 core is isomorphic and is what the extension uses; payholeFetch and the CLI are Node only.
payholeFetch(options)
Returns a fetch that pays 402s with a session key against a BudgetAccount. Options: sessionKey, budgetAccount, optional rpcUrl, chainId, usdg, maxAmount (base units), onPaid, onPull. Under the key's cap the payment is silent; over it the call throws PaymentRefusedError with a reason of cap-exceeded, key-not-live, or a contract error name. Nothing is signed when refused.
Lower level
parsePaymentRequired reads a 402 (version 2 header or version 1 body); selectOffer keeps only exact, USDG, EIP-3009 offers on chain 4663; preparePayment signs the authorization and encodes the header; parseSettleResponse reads the settlement. readSessionKey and ensureKeyFunds talk to the BudgetAccount. domainHash and claimTypedData cover the registry.
import { payholeFetch, PaymentRefusedError } from "@payhole/sdk";

const fetchPaid = payholeFetch({
  sessionKey: process.env.PAYHOLE_SESSION_KEY,
  budgetAccount: "0xYourBudgetAccount",
  maxAmount: 500_000n, // USDG base units, 6 decimals
});
const res = await fetchPaid("https://api.example.com/report");
payhole CLI
payhole key createGenerate a session key into the key file and print its address. The pocket owner registers it from the extension's Agents tab with a cap and an expiry.
payhole key import | address | exportStore an existing key, print the address, or print the private key.
payhole statusCap, spent, remaining, expiry, and the key's USDG and ETH balances.
payhole pay <url> [--method] [--data] [--header] [--max] [--quiet]Fetch a URL and pay its 402 if the cap allows. Exit codes: 0 success, 1 error, 2 refused, 3 no acceptable offer.
PAYHOLE_BUDGET_ACCOUNT, PAYHOLE_KEY_FILE, PAYHOLE_SESSION_KEY, PAYHOLE_RPC_URLEnvironment. Without a budget account the CLI pays from the key's own USDG balance, which is only meant for interop checks.
The session key needs a little ETH for gas: pulling USDG from the BudgetAccount is a transaction the key sends itself. Signing the x402 authorization costs nothing; the facilitator settles it.
Accept x402 on your server
Answer an unpaid request with 402 and a PAYMENT-REQUIRED header carrying a base64 JSON payment request. Verify and settle the retried request through any facilitator that supports the exact scheme on Robinhood Chain. The extension reads the header from the response even when your CORS policy does not expose it, because it observes responses from a privileged context.
HTTP/1.1 402 Payment Required
Cache-Control: no-store
PAYMENT-REQUIRED: base64({
  "x402Version": 2,
  "resource": { "url": "https://api.example.com/report", "description": "One report", "mimeType": "application/json" },
  "accepts": [{
    "scheme": "exact",
    "network": "eip155:4663",
    "asset": "0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168",
    "amount": "20000",
    "payTo": "0xYourWallet",
    "maxTimeoutSeconds": 300,
    "extra": { "name": "Global Dollar", "version": "1" }
  }]
})
amount is in USDG base units (6 decimals; 20000 is 0.02 USDG). The retried request carries PAYMENT-SIGNATURE. Post it with the same requirements to a facilitator's /verify and /settle, then answer 200 with PAYMENT-RESPONSE. Facilitators confirmed on chain 4663: Naven at facilitator.naven.network and Primer at x402.primer.systems.
Robinhood Chain, chain id 4663, settlement in USDG onlyPrivacyx.com/payhole_x402payhole.org