Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.x402r.org/llms.txt

Use this file to discover all available pages before exploring further.

@x402r/cli makes a single x402 payment from the command line. You point it at an address, provide a signer, and get back the response body plus a settlement transaction hash. The CLI carries zero provider SDK dependencies. Raw private keys, JSON-RPC signers (Privy, Turnkey, Fireblocks, Safe), and custom signer modules all work through the same interface.

Install

npx @x402r/cli pay <url> [options]
No project install required. Pin the version (for example, @x402r/cli@0.2.0) for reproducible scripted workflows.

Usage

x402r pay <url> [signer flags] [--chain <eip155:id>] [--rpc <url>] [--max-amount N] [--json]
If the endpoint does not return HTTP 402, the CLI short-circuits and prints the response body with exit code 0. The CLI sends no payment.

Signer configuration

Configure exactly one signer source. CLI flags take precedence over environment variables. If the CLI finds zero or more than one source, it exits with code 6.
SourceFlagEnvironment variable
Raw private key--key 0x...PRIVATE_KEY
Remote JSON-RPC--signer-url <url> and --signer-address 0x...SIGNER_URL and SIGNER_ADDRESS
Custom module--signer-module <pkg-or-path>SIGNER_MODULE
Environment variable names use no X402R_ prefix to match Foundry, Hardhat, and x402-reference conventions.

Request options

FlagDescription
--chain <eip155:id>Select a specific accepts[] entry when the merchant offers more than one chain. Required when more than one option exists.
--asset-transfer-method <eip3009|permit2>Select the token-collection path when the chosen accepts[] entry supports both EIP-3009 and Permit2. Required when more than one option exists.
--rpc <url>Override the RPC endpoint for on-chain reads. Required for chain IDs not in viem/chains.
--max-amount <n>Refuse to pay more than n atomic token units. Exits with code 3 if the price exceeds this.
--jsonEmit a single JSON envelope to stdout instead of plain text.

Supported chains

The CLI reads the chain from the 402 response’s accepts[].network field. Any EVM chain known to viem/chains works, including Base and Base Sepolia. For chain IDs viem/chains does not recognize, pass --rpc <url> with an RPC endpoint.

Exit codes

CodeMeaning
0Success
1Network error
2Malformed 402 response or unusable accepts[]
3Price exceeds --max-amount
4Signature rejected
5Settlement failed (merchant error after payment, or facilitator error)
6Signer resolution failed (none, more than one, or incomplete configuration)

Examples

Raw private key

PRIVATE_KEY=0xabc123... npx @x402r/cli pay https://api.example.com/paid-endpoint

JSON-RPC signer

Any endpoint that speaks eth_signTypedData_v4 works: Privy wallet RPC, Turnkey, Fireblocks, Safe, a local cast wallet endpoint, or a hardware wallet behind an RPC bridge.
npx @x402r/cli pay https://api.example.com/paid-endpoint \
  --signer-url https://signer.example/rpc \
  --signer-address 0x586486394C38A2a7d36B16a3FDaF366cd202d823

Custom module (Privy)

privy-signer.js
import { PrivyClient } from "@privy-io/server-auth";
import { createViemAccount } from "@privy-io/server-auth/viem";

export default async function () {
  const privy = new PrivyClient(
    process.env.PRIVY_APP_ID,
    process.env.PRIVY_APP_SECRET
  );
  return createViemAccount({
    walletId: process.env.PRIVY_WALLET_ID,
    address: process.env.PRIVY_WALLET_ADDRESS,
    privy,
  });
}
npx @x402r/cli pay https://api.example.com/paid-endpoint \
  --signer-module ./privy-signer.js

Custom module (Coinbase CDP)

cdp-signer.js
import { CdpClient } from "@coinbase/cdp-sdk";
import { toAccount } from "viem/accounts";

export default async function () {
  const cdp = new CdpClient();
  const acct = await cdp.evm.getOrCreateAccount({
    name: process.env.CDP_ACCOUNT_NAME,
  });
  return toAccount(acct);
}
npx @x402r/cli pay https://api.example.com/paid-endpoint \
  --signer-module ./cdp-signer.js

JSON output

With --json, the CLI writes a single JSON envelope to stdout:
{
  "body": "<merchant response body>",
  "status": 200,
  "tx": "0x...",
  "elapsedMs": 1234,
  "signer": { "kind": "key", "address": "0x..." }
}
The CLI drops the signer field when the endpoint returned a non-402 response (the CLI sent no payment).

Signer module contract

A custom signer module must default-export a factory function with the signature () => Promise<Account>. The returned object must be a viem Account with at least address and signTypedData. The CLI only needs typed-data signatures; the facilitator broadcasts the transaction.

Programmatic usage

You can also use the pay function and resolveSigner directly from TypeScript:
import { pay } from "@x402r/cli";
import type { PayResult } from "@x402r/cli";

const result: PayResult = await pay({
  url: "https://api.example.com/paid-endpoint",
  key: process.env.PRIVATE_KEY,
  json: true,
});

console.log(result.body);
console.log(result.tx);
The programmatic API uses the same PayFlags interface as the CLI binary. All options (chain, rpc, maxAmount, signer flags) are available.

Exports

The @x402r/cli package exports:
ExportTypeDescription
payfunctionExecute a one-shot payment against an endpoint
resolveSignerfunctionResolve a signer from flags and environment variables
CliErrorclassBase error class with typed exit codes
NetworkErrorclassExit code 1
Malformed402ErrorclassExit code 2
MaxAmountExceededErrorclassExit code 3
SignatureRejectedErrorclassExit code 4
SettlementErrorclassExit code 5
SignerResolutionErrorclassExit code 6

Next steps

Merchant guide

Accept payments and manage escrow releases.

Examples

Runnable examples for every SDK operation.