SKILL.md
x402 buyer (pr402)
Help the user build a buyer that discovers paid resources, settles via pr402, and retries with proof.
Default rail: exact (SplitVault instant settlement via pr402). For sla-escrow, add oracle-specific fields — see ipay.sh/agent-integration.md and oracles Buyer Guide.
Subscription APIs: pay once per time window on POST /subscribe (same exact steps 1–5 below), then use Authorization: Bearer on data routes — see [references/subscription-client.md](references/subscription-client.md). Prefer x402-subscription-client.
Reference repo: x402-buyer-starter (Bash / TypeScript / Python — separate repo).
Facilitator source and live docs: miralandlabs/pr402 (individual account — not the miraland-labs org).
GitHub repos (x402 hub is virtual)
| Project | GitHub |
|---|---|
| pr402 facilitator + MCP source | miralandlabs/pr402 |
| Buyer starter | miraland-labs/x402-buyer-starter |
| Seller starter | miraland-labs/x402-seller-starter |
| Oracles workspace | miraland-labs/oracles |
| x402 hub (docs + x402-cli only) | miraland-labs/x402 |
| Subscription buyer SDK | miraland-labs/x402-subscription-client |
Pick a stack
| User context | Install | Skill reference |
|---|---|---|
| Cursor / Claude Desktop / MCP host | npx -y @pr402/mcp-server |
[references/mcp-and-sdk.md](references/mcp-and-sdk.md) |
| Node / TypeScript production agent | npm i @pr402/client |
[references/mcp-and-sdk.md](references/mcp-and-sdk.md) |
| TypeScript starter/demo | npm i @pr402/buyer-typescript |
Add the production safety checks below before using with funds |
| Quick CLI smoke test | npm i -g @pr402/client → pr402-buy |
Same default flow as MCP — [references/mcp-and-sdk.md](references/mcp-and-sdk.md) |
| Python agent | starter python/ or pip install langchain-pr402 |
starter README |
| Bash / DevOps | starter bash/ |
minimal curl + sign flow |
| http402 Forge digital goods | npm i -g @http402/forge-cli |
[references/forge-marketplace.md](references/forge-marketplace.md) |
Facilitator URLs
Default for examples and production integration:
| Recommended | Alternate (same APIs) | |
|---|---|---|
| Production (Mainnet) | https://ipay.sh |
https://agent.pay402.me |
Set PR402FACILITATORURL to the host the seller documents (usually https://ipay.sh on Mainnet).
Devnet testing only: https://preview.ipay.sh or https://preview.agent.pay402.me.
Confirm network: GET https://ipay.sh/api/v1/facilitator/health. Read wallet RPC from response — do not hardcode cluster RPC from docs.
Golden path (exact scheme)
Execute in order:
- Request resource — unpaid call returns HTTP 402 +
PaymentRequired(body and/orPAYMENT-REQUIREDheader). - Choose
accepts[]line — match payer wallet, network, asset, amount. - Build tx —
POST /api/v1/facilitator/build-exact-payment-txwith{ payer, accepted, resource }.
Normalize v2:solana:exact → exact on the request body (canonical wire form).
- Sign — deserialize base64 bincode
VersionedTransaction; sign atpayerSignatureIndex; paste signed tx intoverifyBodyTemplate.paymentPayload.payload.transaction. - Retry resource — send
PAYMENT-SIGNATUREas base64-encoded UTF-8 JSON. Raw JSON is compatibility-only. Do not call facilitator/verifyor/settlefirst in the SDK/MCP path — the seller gate handles settlement. - Seller settles — seller SDK (or middleware) calls facilitator
/settledirectly; verification runs immediately before broadcast. - Confirm — HTTP 200 + optional
PAYMENT-RESPONSEheader with on-chain settlement metadata.
For subscription purchase, run steps 1–5 against POST /api/v1/subscribe?tier=… instead of a data route; store the returned JWT and switch to Bearer auth — [references/subscription-client.md](references/subscription-client.md).
Full step detail: [references/exact-payment-flow.md](references/exact-payment-flow.md). Direct buyer-side /settle (manual curl / debugging only) is documented there under Advanced.
Advanced: direct facilitator settlement
Use only when not retrying through a seller gate — manual curl, facilitator API debugging, or custom flows without HTTP 402 retry. Not what pr402-buy, MCP, or x402-buyer-starter do by default:
- After step 4,
POST /api/v1/facilitator/settlewith the signed JSON body;/settleverifies internally. - Use
/verifyonly as a diagnostic and never deliver based on its result. If used, call/settleimmediately with the same proof. - Then retry the resource with
PAYMENT-SIGNATUREif the seller still requires proof.
Buyer safety requirements
- Accept only Solana
exactrails unless deliberately implementing a separate scheme. - Trust only official facilitator origins by default; require an explicit allowlist for self-hosted origins.
- Set an atomic-unit spend ceiling (
maxPaymentAmountin@pr402/client). - Reject build responses that change
scheme,network,asset,amount, orpayTo. - Confirm
payerSignatureIndexis a required signer slot owned by the buyer before signing.
pr402 vs generic x402 (buyer pitfalls)
| Topic | pr402 reality |
|---|---|
payTo |
On-chain vault / escrow PDA — not "send to seller wallet" |
| Tx shape | Facilitator-built shell; do not add address lookup tables |
| Fee payer | Facilitator often pays Solana fees on exact — do not send legacy buyerPaysTransactionFees |
| Facilitator host | Must match seller's documented origin |
| Mint allowlist | Wrong asset → explicit 400 with approved mints list |
| Blockhash expiry | Rebuild + re-sign on BLOCKHASH_EXPIRED |
| Facilitator upstream | 502 FACILITATOR_UPSTREAM → retry safely with backoff |
TypeScript production pattern
import { X402AgentClient } from "@pr402/client";
const client = new X402AgentClient(keypair, {
maxPaymentAmount: "1000000", // atomic units
});
const res = await client.fetchWithAutoPay(
"https://seller.example/api/premium",
preferredMint,
{ method: "POST", body: "..." },
);
When implementing for the user
- Prefer
@pr402/clientor MCP over hand-rolling proof bodies; they share the hardened production path. - Never commit payer keypairs — env var
PR402PAYERKEYPAIR_JSONor path outside repo. - Fund the payer wallet on Mainnet (production) or Devnet (when using
preview.ipay.sh). - Classify facilitator errors —
PAYMENTINVALID: fix proof;BLOCKHASHEXPIRED: rebuild;FACILITATOR_UPSTREAM: retry with backoff. Treat HTTP 200 JSONerrorfields as failure only as defensive starter handling. - Scheme normalization — always send wire
exactto build endpoint; cached proofs may use either alias on verify. - Forge vs HTTP 402 — Forge listings use
@http402/forge-client/ forge-mcp; generic APIs use pr402 buyer flow above. - Subscription APIs — if the seller gates only
/subscribeand returns a JWT, use [references/subscription-client.md](references/subscription-client.md) orx402-subscription-client; do not sendPAYMENT-SIGNATUREon every data call.
Live documentation
Production facilitator (default):
- https://ipay.sh/agent-integration.md — canonical runbook
- https://ipay.sh/quickstart-buyer.md — SDK default + manual curl steps
- x402-buyer-starter README — Bash / TypeScript / Python starter
- https://ipay.sh/agent-tools.json
- https://ipay.sh/openapi.json
Devnet equivalents live under https://preview.ipay.sh/… when testing on Devnet.
Related
pr402— entry router when integrator role is unclearpr402-seller— when the same project also sells APIspr402-facilitator— only when modifying the Rust facilitator codebase