# PennyBot buyer quickstart

This executable Node.js example inspects payment terms first. It only attempts payment when you deliberately add --pay. Default target: the published 29-byte fixed vector.

## 1. Inspect without a wallet or payment

Use Node.js 22 or later. Save [pennybot-buyer.mjs](https://playbrightgaming.com/agents/pennybot-buyer.mjs) in a new local folder, review it, then run:

```sh
node pennybot-buyer.mjs
node pennybot-buyer.mjs https://example.com/
```

Inspection uses only built-in Node modules. It requests one unsigned 402 challenge, checks the primary route, x402 v2, exact scheme, Base mainnet, USDC token, 900 atomic units ($0.0009), and the public receiver pinned in the example. It does not access a key, sign, or pay. Changed terms stop the example for review; the live challenge remains authoritative.

## 2. Make one purchase, when authorized by your own spending policy

In that new local folder, install the same x402 SDK version used by this example:

```sh
npm init -y
npm install --save-exact @x402/fetch@2.28.0 @x402/evm@2.28.0 viem@2.57.2
```

Provide your own funded Base-mainnet USDC wallet key as PENNYBOT_PRIVATE_KEY through your local secret manager or process environment. Never put it in a URL, source file, chat, or support message. The seller never needs your private key. The example does not read .env or any saved wallet file.

```sh
node pennybot-buyer.mjs --pay
node pennybot-buyer.mjs https://example.com/ --pay
```

Each command above is a separate possible $0.0009 USDC purchase; run only the one you intend. Funding/bridging and any wallet/network costs are separate from the service fee. The example follows no redirects from the payment endpoint, sends one signed request, and performs no paid retry. It signs the checked live challenge using the SDK and the same exact target URL.

## 3. Verify and keep the output

On a paid response, the example saves response evidence to a new pennybot-result-*.json file in your current folder before validation. It requires service HTTP 200, a successful PAYMENT-RESPONSE on the expected network with a transaction ID, matching requestedUrl, and the receipt's required fields and basic bounds. For the fixed vector, it also checks the known hash and byte count. Use the [full JSON Schema](https://playbrightgaming.com/agents/receipt.schema.json) in production consumers.

The JSON status is the target site's status, so target 404/500 can be a valid paid result. The example does not prove semantic truth, independently verify chain finality, or create server-side recovery.

If the signed request returns an error, disconnects, or lacks a valid result/payment receipt, the example stops with paid_attempt_unresolved_no_retry. It does not conclude zero charge. Keep the evidence, examine the original transaction through your wallet/payment provider, and use the [delivery and retry guidance](https://playbrightgaming.com/agents/reality-receipt.md#delivery-and-retries). There is currently no durable recovery or idempotent replay API.

The free path has been run against the live endpoint. Paid orchestration and failure behavior are tested with isolated fixtures; this quickstart's new paid path has not itself been exercised with real funds. The [official x402 fetch SDK documentation](https://github.com/coinbase/x402/tree/main/typescript/packages/http/fetch) describes the client API.
