> ## Documentation Index
> Fetch the complete documentation index at: https://docs.agentscore.com/llms.txt
> Use this file to discover all available pages before exploring further.

# AgentScore Pay (CLI)

> @agent-score/pay; one CLI for agent payments across the x402/MPP ecosystem. Built by AgentScore.

`@agent-score/pay` is the universal agent-payment CLI for shell-tool LLM agents. It manages encrypted keystores, parses 402 challenges from any merchant, signs the right credential per rail, and submits the request; all from one shell command.

AgentScore Pay works with **any x402/MPP merchant in the ecosystem**; AgentScore-gated or not. It contacts AgentScore APIs only when the merchant's 402 challenge requires AgentScore identity. For everything else, pay walks the open x402 protocol like any other compliant client.

| Built by                    | AgentScore                                                                                                       |
| --------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| Native rails                | x402 EVM (Base mainnet/sepolia), MPP (Tempo mainnet/Moderato testnet, Solana mainnet/devnet via `solana/charge`) |
| Discovers via               | x402 Bazaar (Coinbase) + mpp.dev/services                                                                        |
| Identity                    | merchant-driven: pass `X-Operator-Token`, `X-Wallet-Address`, both, or neither                                   |
| Hints for unsupported rails | yes: points to the right tool (e.g. [`link-cli`](https://github.com/stripe/link-cli) for Stripe SPT)             |

## Installation

<CodeGroup>
  ```bash npm theme={"dark"}
  npm install -g @agent-score/pay
  ```

  ```bash Homebrew (macOS) theme={"dark"}
  brew install agentscore/tap/agentscore-pay
  ```

  ```bash npx (no install) theme={"dark"}
  npx @agent-score/pay <command>
  ```
</CodeGroup>

Releases are signed with [Sigstore cosign](https://www.sigstore.dev/) (keyless, GitHub OIDC). The Homebrew formula tarball is sha256-pinned to the npm release.

## First-run setup

Create encrypted keystores for all three native chains in one shot:

```bash theme={"dark"}
agentscore-pay init
```

By default this creates a single BIP-39 mnemonic and derives an EVM wallet (used for both Tempo and Base) and a Solana wallet. Pass `--no-mnemonic` for separate raw keys per chain. The keystore is encrypted with AES-256-GCM (scrypt KDF); set `AGENTSCORE_PAY_PASSPHRASE` to skip the prompt in scripts.

To get testnet funds:

```bash theme={"dark"}
agentscore-pay faucet --chain base    # prints Circle + Coinbase faucet URLs
agentscore-pay faucet --chain solana  # prints Circle + faucet.solana.com
agentscore-pay init --fund-tempo-testnet  # auto-funds via tempo_fundAddress
```

Verify balances:

```bash theme={"dark"}
agentscore-pay balance --network testnet
```

## Paying any x402 endpoint

`agentscore-pay pay` is a drop-in replacement for `curl`. It hits the URL, parses the 402 challenge, signs the credential on the appropriate rail, submits via the right header, and returns the merchant's 200 response. Works with any merchant that speaks x402 or MPP on a rail pay can sign.

```bash theme={"dark"}
agentscore-pay pay POST https://merchant.example/api \
  --chain base \
  -H 'Content-Type: application/json' \
  -d '{"product_id":"...","quantity":1}' \
  --max-spend 5
```

Flags:

| Flag                                 | Purpose                                                                                                                                                                   |
| ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--chain {base,solana,tempo}`        | Which keystore to sign with. Determines rail (x402 EVM on base, MPP `solana/charge` on solana, MPP `tempo/charge` on tempo).                                              |
| `--network {mainnet,testnet}`        | Which network to target. Defaults to mainnet.                                                                                                                             |
| `--max-spend <usd>`                  | Hard cap on the payment amount; aborts before signing if exceeded.                                                                                                        |
| `--name <name>`                      | Use a named keystore instead of `default` (multi-wallet setups).                                                                                                          |
| `-H` / `-d`                          | curl-compatible header / body flags.                                                                                                                                      |
| `--format {toon,json,yaml,md,jsonl}` | Output format. `--json` is shorthand for `--format json`. TOON is the default in agent contexts (token-efficient).                                                        |
| `--dry-run`                          | Show what would be signed and sent without submitting. Useful for agent dev/debug: preview rail selection, signer wallet, expected request shape before any real payment. |

### Idempotency

Every `agentscore-pay pay` invocation generates a stable `X-Idempotency-Key` header; a SHA-256 hash of `(url + method + body + signer)`; so retries within a single invocation reuse the same key. Merchants that honor Stripe-pattern dedup (which includes most production payment systems) won't double-charge if a payment settles but the network response is lost mid-flight. Pass your own `-H 'X-Idempotency-Key: <value>'` to override the auto-generated key (useful for cross-process idempotency: same logical purchase across multiple `agentscore-pay pay` invocations).

### Test-mode addresses

AgentScore reserves seven EVM addresses (`0x0000…0001` through `0x0000…0007`) as deterministic test fixtures; KYC verified, sanctions clear, age gates passing; so dev/test merchants don't burn real KYC credits. `agentscore-pay` recognizes these automatically; the recognizer `isAgentScoreTestAddress(addr)` and `AGENTSCORE_TEST_ADDRESSES` are exported from `@agent-score/sdk` (the canonical home) for your own dev/test fixtures.

### Decimals handling

Spec-compliant 402 responses carry `decimals` in the rail requirements. When a merchant omits it, pay applies a strict policy: canonical USDC (matched against the per-chain Circle USDC registry) silently uses 6 decimals; any unrecognized asset triggers `merchant_spec_violation` and aborts before signing. Refusing to guess avoids orders-of-magnitude mis-billing on tokens with non-6-decimal precision.

## Discovery and probing

Find merchants and probe challenges before paying:

```bash theme={"dark"}
agentscore-pay discover --limit 10                     # browse the x402 Bazaar + mpp.dev registry
agentscore-pay discover --chain base --max-price 0.01  # filter to your rail and budget
agentscore-pay check POST https://merchant.example/api -d '...'  # see all rails the merchant accepts
agentscore-pay fund-estimate https://merchant.example/api -d '...'  # how many calls your balance covers per rail
```

`check` and `discover` surface **all** rails the merchant accepts; including ones pay can't fund directly. For unsupported rails pay knows about (Polygon, other x402 networks, Stripe SPT, …) it prints a structured hint pointing to the right tool, so the agent can complete the payment with a sibling CLI without trial-and-error.

Example (`check` output against a multi-rail merchant):

```
POST https://merchant.example/api → 402 Payment Required (x402)

Accepted rails (natively supported by agentscore-pay):
  x402  exact/eip155:8453             $0.01  pay_to=0xAbC1
  mpp   solana/charge                 $0.01  pay_to=2LWb…

Other rails accepted (use a compatible client):
  x402  Polygon (x402)                 $0.01
         → https://polygon.technology
  x402  Stripe Shared Payment Token    $0.01
         → @stripe/link-cli (npm i -g @stripe/link-cli)
```

## Identity model

AgentScore Pay is identity-agnostic; it only sends what the merchant or the agent asks for. The `X-Operator-Token` and `X-Wallet-Address` headers are AgentScore's identity scheme; merchants that don't use AgentScore can ignore them entirely (or use their own identity headers; pay forwards anything the agent passes via `-H`).

For AgentScore-gated merchants, two paths:

* **Operator token**: pass `-H 'X-Operator-Token: opc_...'` OR run `agentscore-pay passport login` once and pay auto-attaches it on every settle leg. Reusable across every AgentScore merchant until expiry. Required for rails that have no wallet signature (Stripe SPT, card).
* **Wallet auth**: pass `-H 'X-Wallet-Address: 0x...'` (or Solana base58). Works on rails that carry a wallet signature (Tempo MPP, Solana MPP, x402 EIP-3009 on Base). The wallet must resolve to the same operator as the payment signer; same-operator linked wallets are fungible.

### AgentScore Passport (one-command identity)

```bash theme={"dark"}
agentscore-pay passport login    # opens verify URL, polls until verified, saves opc_ to ~/.agentscore/passport.json
agentscore-pay passport status   # token prefix + expiry
agentscore-pay passport logout   # revoke remote + remove local file
```

After `passport login`, every subsequent `agentscore-pay <url>` call auto-attaches `X-Operator-Token` from the stored Passport. Suppress with `--skip-passport` for explicit-anonymous traffic; caller-supplied `-H "X-Operator-Token: ..."` always wins.

**Token lifecycle:** the access `operator_token` is 24h and the rotating `refresh_token` is 90d. agentscore-pay refreshes the access token silently on the next call after it expires; no agent action needed. The user is only prompted to re-verify in browser (`Open this URL to renew:`) when both have expired (\~90 days of inactivity), or when the Passport was minted via cold-start bootstrap rather than `passport login` (merchant-initiated sessions don't issue a refresh\_token). `agentscore-pay`'s "expires in N days" warning fires only when re-verify is genuinely needed, not on every short-lived access rotation.

### Header precedence

Order of preference for the identity header pay attaches on the settle leg:

1. Caller-supplied `-H 'X-Operator-Token: ...'` or `-H 'X-Wallet-Address: ...'`; wins
2. Stored Passport's `operator_token`; auto-attached as `X-Operator-Token` (skip with `--skip-passport`)
3. `X-Wallet-Address` from the `--chain` keystore; last-resort fallback for first-payment flows where the merchant's gate captures the wallet under the operator

## Native rails

| Rail                 | Networks                                               | Header                   | Recovery                                                                             |
| -------------------- | ------------------------------------------------------ | ------------------------ | ------------------------------------------------------------------------------------ |
| **x402 exact** (EVM) | Base mainnet (`eip155:8453`), Sepolia (`eip155:84532`) | `X-Payment`              | EIP-3009 USDC `TransferWithAuthorization`; gasless from agent (facilitator pays gas) |
| **Solana MPP**       | Solana mainnet-beta, devnet                            | `Authorization: Payment` | MPP `solana/charge` directive signed against the merchant's challenge                |
| **Tempo MPP**        | Tempo mainnet (4217), Moderato testnet (42431)         | `Authorization: Payment` | MPP `tempo/charge` directive signed against the merchant's challenge                 |

Address normalization is network-aware; EVM addresses are lowercased before comparison; Solana base58 addresses are preserved verbatim because base58 is case-sensitive.

## Other commands

```bash theme={"dark"}
agentscore-pay wallet list                                   # list named keystores per chain
agentscore-pay wallet create --chain base --name trading     # add a named wallet
agentscore-pay wallet import --chain solana --mnemonic "..." # import BIP-39 phrase

agentscore-pay qr --chain base --amount 5    # ASCII QR with EIP-681 / solana: URI
agentscore-pay fund --chain base             # Receive QR + balance polling, send USDC from any wallet, exchange, or fiat onramp
agentscore-pay fund --chain base --via stripe-onramp --amount 25  # Stripe Crypto Onramp (card → USDC) on base/solana mainnet; pay never auto-opens browser, prints the hosted crypto.link.com URL
agentscore-pay fund --chain base --via stripe-onramp --amount 25 --quote-only  # Preview the Stripe onramp price (fees + USDC out) without minting a session
agentscore-pay send --chain base --to 0xRecipient --amount 5                    # Raw USDC transfer (default --asset usdc)
agentscore-pay send --chain base --to 0xRecipient --amount 0.005 --asset native # Send 0.005 ETH (native gas) on Base
agentscore-pay send --chain solana --to <base58> --amount 0.01 --asset native   # Send 0.01 SOL on Solana
agentscore-pay revoke --chain base --token <addr> --spender <addr>  # revoke an ERC-20 allowance (EVM only)

agentscore-pay whoami                        # wallets + balances + active config in one payload
agentscore-pay history --limit 20            # past payments from ~/.agentscore/history.jsonl
agentscore-pay limits set --daily 5 --per-call 0.5 --per-merchant 2  # persistent USD caps
agentscore-pay unlock --for 1h               # cache passphrase to ~/.agentscore/.unlock (TTL ≤ 8h)

agentscore-pay agent-guide                   # structured how-to for LLM tool-loop agents

# Passport (no API key required, public session endpoint)
agentscore-pay passport login                # one-command browser login → operator_token saved + auto-attached
agentscore-pay passport status               # token prefix + expiry
agentscore-pay passport logout               # remove local; remote revoke if AGENTSCORE_API_KEY is set

# Other identity commands (require AGENTSCORE_API_KEY)
agentscore-pay reputation 0xabc...           # cached trust reputation lookup
agentscore-pay assess --address 0xabc... --require-kyc --min-age 21
agentscore-pay sessions create --context "wine purchase"   # low-level session API; passport login is the wrapper most agents want
agentscore-pay credentials list
agentscore-pay credentials create --label "claude-code" --ttl-days 7
agentscore-pay associate-wallet --operator-token opc_... --wallet-address 0xabc... --network evm
```

Run `agentscore-pay --help` (or `agentscore-pay <command> --help`) for full flags. For LLM agents, `agent-guide` prints a structured how-to (golden path, testnet path, funding, auxiliary commands, pitfalls, identity-error recovery patterns, exit codes); also available as JSON via `--format json`.

### Identity-error recovery + quota observability

`assess`, `sessions`, `credentials`, and `associate-wallet` surface the SDK's typed errors as structured CliErrors. The JSON envelope's `code` discriminates the recovery path: `config_error` (API-key issue OR token-expired/invalid; `extra` carries `verify_url`/`session_id`/`poll_secret` for the verify-poll flow), `insufficient_balance` (endpoint not enabled; surface to user), `quota_exceeded` (account cap reached; surface to user, agent retry won't fix), `network_error` (transient; retry with backoff). `agentscore-pay agent-guide` lists each pattern with the exact recovery action.

The `pay <url>` command additionally throws two non-TTY-only codes when a Passport-required state is hit; surfaced as a structured envelope instead of blocking on the inline browser-redirect flow, so unattended agents can route to `passport login`. `passport_login_required` fires when the stored Passport's access token expired AND silent refresh did not succeed (extra carries `previous_token_prefix`); `passport_required_by_merchant` fires when a merchant returns 403 with bootstrap fields and the agent has no usable Passport (extra carries `verify_url`/`session_id`/`poll_secret`/`poll_url`/`order_id`). Both have `next_steps.action: "passport_login"`. In a human TTY, pay drives the inline browser flow itself instead of throwing.

When the account has a per-period quota, `assess` (and other identity commands) emits a `quota: { limit, used, reset }` block on the success envelope, captured from `X-Quota-Limit` / `X-Quota-Used` / `X-Quota-Reset` response headers. Agents can monitor approach-to-cap proactively (warn at 80%, alert at 95%) before hitting `quota_exceeded`.

```bash theme={"dark"}
agentscore-pay assess --address 0xabc... --json | jq '.quota'
# → { "limit": 1000, "used": 780, "reset": "2026-06-01T00:00:00Z" }
```

## Unlocking the keystore

Three precedence-ordered options for the passphrase prompt:

| Mechanism                                  | Best for                                                       | Persistence                                                                                              |
| ------------------------------------------ | -------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
| `AGENTSCORE_PAY_PASSPHRASE=<pass>` env var | Containers, CI, serverless, daemons, any non-interactive agent | Process / shell session                                                                                  |
| `agentscore-pay unlock --for 1h`           | Interactive shell where you'll run multiple commands           | Cached in `~/.agentscore/.unlock` (mode `0600`) until TTL expires (max 8h); `unlock --clear` wipes early |
| Per-call interactive prompt                | First-time setup, one-off commands                             | None                                                                                                     |

**Env var wins when set**; it produces no on-disk artifact and is the right primitive for every agent context (CI secrets, container env, K8s secrets, Lambda config, MCP host config). When env vars aren't controllable (e.g. an interactive Claude Code session running locally), `unlock` is the fallback.

For agent authors: prefer the env var and read it from your secret store at agent startup. Don't bake it into the agent's prompt or memory. `agentscore-pay agent-guide` emits a structured how-to with the precedence baked in.

## MCP server

`agentscore-pay --mcp` runs the CLI as a stdio JSON-RPC MCP server, exposing every command (wallet + payment + identity) as a tool. `agentscore-pay mcp add` registers the binary with Claude Code, Cursor, Amp, and other MCP-aware agents. `agentscore-pay --llms` emits a markdown manifest of every command (or `--llms --format json` for JSON Schema).

## Scripting

Output adapts to context; terminal use gets pretty-printed, pipes/agents get a structured envelope (TOON by default; token-efficient, \~40% fewer tokens than JSON). Pass `--json` (or `--format yaml|md|jsonl`) to lock the format. `AGENTSCORE_PAY_PASSPHRASE` skips the passphrase prompt for unattended runs:

```bash theme={"dark"}
RESPONSE=$(AGENTSCORE_PAY_PASSPHRASE=$PAY_PASS \
  agentscore-pay pay POST "$URL" \
    -H 'Content-Type: application/json' \
    -d "$BODY" \
    --max-spend "$MAX_SPEND" \
    --json)
echo "$RESPONSE" | jq .body.order
```

Exit codes are documented in `agentscore-pay --help`; non-zero exits indicate an error category (`invalid_input`, `unsupported_rail`, `network_error`, `merchant_error`, etc.) so scripts can branch.

## Source + releases

* npm: [npmjs.com/package/@agent-score/pay](https://www.npmjs.com/package/@agent-score/pay)
* GitHub: [github.com/agentscore/pay](https://github.com/agentscore/pay)
* Homebrew tap: [github.com/agentscore/homebrew-tap](https://github.com/agentscore/homebrew-tap)

Each release publishes signed native binaries (darwin-arm64, darwin-x64, linux-arm64, linux-x64, windows-x64) alongside the npm package, with cosign signatures + certificates for offline verification.
