Buyer Quick Start — 6 Steps to Pay via x402
You have a Solana wallet and received HTTP 402 from a seller. Here's what to do.
Status. pr402 and the
exactrail are live on Solana Mainnet (https://ipay.sh) and Devnet (https://preview.ipay.sh); same service also served onhttps://agent.pay402.me/https://preview.agent.pay402.me(not deprecated). Forsla-escrow, theoracle_authorityon the payment is chosen by the seller — trust that authority explicitly before funding.
Install
Fastest path — use the published SDK. One command does the whole loop below.
# Node (≥ 18)
npm i -g @pr402/client
pr402-buy --resource <URL> --payer <keypair.json> --mint <MINT>
# Rust (1.75+)
cargo install pr402-client
pr402-buy --resource <URL> --payer <keypair.json> --mint <MINT>
# Zero-install (Node)
npx @pr402/client pr402-buy --resource <URL> --payer <keypair.json> --mint <MINT>Both packages also expose a library — X402AgentClient — for embedding in long-running agents. See the package READMEs (npm, crates.io).
The six steps below document the protocol underneath, for implementing from scratch in other languages or verifying the SDK's behavior.
Replace $BASE with the facilitator URL the seller documents. Run curl -sS "$BASE/api/v1/facilitator/health" | jq .solanaNetwork to confirm the cluster.
Do not silently substitute a different facilitator origin than the seller documented. payTo, program ids, asset allowlists, and oracle authorities are deployment-specific.
Step 0 — Find a seller (optional)
Already have a 402 response? Skip to Step 1. Looking for paid resources? The facilitator exposes a public directory of verified, opted-in sellers:
curl -sS "$BASE/api/v1/facilitator/providers?limit=50" | jq '.entries[] | {displayName, serviceUrl, tags, settlementMode, splMint}'Each entry gives you serviceUrl, tags[], displayName, and the rail pubkeys (splitVaultPda, splMint) — enough to build an accepts[] line without waiting for a 402. Single-wallet lookup: GET /api/v1/facilitator/providers/{wallet}. The facilitator verifies wallet control only; it does not vet the advertised service — treat listings as a directory, not a recommendation.
Step 1 — Confirm the facilitator supports your scheme
curl -sS "$BASE/api/v1/facilitator/capabilities" | jq '.features'Check unsignedExactPaymentTxBuild: true (for exact) or unsignedSlaEscrowPaymentTxBuild: true (for sla-escrow).
Step 2 — Save the 402 response
From the seller's 402 body, save:
accepts[]— pick one line matching your wallet's chain/assetresource— the resource descriptor
Step 3 — Build an unsigned transaction
pr402's build endpoints do more than convenience — they're how the facilitator communicates its current tx shape (compute budget, token program, vault PDAs). Implementing transaction construction yourself means tracking pr402 policy changes manually.
For exact (instant payment):
curl -sS -X POST "$BASE/api/v1/facilitator/build-exact-payment-tx" \
-H "Content-Type: application/json" \
-d '{
"payer": "<YOUR_PUBKEY>",
"accepted": <THE_ACCEPTS_LINE_YOU_CHOSE>,
"resource": <RESOURCE_FROM_402>
}'For sla-escrow (time-bound escrow):
curl -sS -X POST "$BASE/api/v1/facilitator/build-sla-escrow-payment-tx" \
-H "Content-Type: application/json" \
-d '{
"payer": "<YOUR_PUBKEY>",
"accepted": <THE_ACCEPTS_LINE_YOU_CHOSE>,
"resource": <RESOURCE_FROM_402>,
"slaHash": "<64_HEX_CHARS>",
"oracleAuthority": "<ORACLE_PUBKEY>"
}'Response gives you transaction (base64 unsigned tx) and verifyBodyTemplate (pre-filled verify/settle body). If your 402 line uses v2:solana:exact or v2:solana:sla-escrow, the template’s scheme fields are normalized to wire exact / sla-escrow — use them as returned.
Step 4 — Sign the transaction
- Decode
transaction→ base64 → bincode →VersionedTransaction - Sign at index
payerSignatureIndex(from response) with your Solana keypair - Re-encode:
VersionedTransaction→ bincode → base64 - Replace
verifyBodyTemplate.paymentPayload.payload.transactionwith the signed base64
Step 5 — Verify then settle
# Verify
curl -sS -X POST "$BASE/api/v1/facilitator/verify" \
-H "Content-Type: application/json" \
-d @verify-body.json | jq .
# Settle (same body)
curl -sS -X POST "$BASE/api/v1/facilitator/settle" \
-H "Content-Type: application/json" \
-d @verify-body.json | jq .Success: { "success": true, "transaction": "<SOLANA_SIGNATURE>" }
Step 6 — Access the paid resource
Send the filled verifyBodyTemplate JSON to the seller in the PAYMENT-SIGNATURE header:
curl -sS "<SELLER_RESOURCE_URL>" \
-H "PAYMENT-SIGNATURE: $(cat verify-body.json)"The seller forwards it to /settle and serves you the resource.
If anything fails with blockhash errors, go back to Step 3 — Solana blockhashes expire in ~60 seconds.
Full reference: API overview · {FACILITATOR}/openapi.json · Agent integration (or GET /agent-integration.md on the facilitator).
Buyer launch checklist
- Cache
GET /capabilitiesper facilitator host and invalidate it on failed build/verify responses. - Treat
verifyBodyTemplateas authoritative; only replace the transaction payload after signing. - Record
correlationIdfrom/verifyand reuse it on/settlewhen present. - For
sla-escrow, verify the oracle authority and profile id before funding.
