Skip to main content

Peer Pay CLI

peer-pay-cli runs a local Peer Pay mock backend and manages your hosted merchant account. Test orders and webhooks without exposing your application to the internet. Sign up and configure your merchant from the same terminal.

Missing required arguments can be filled in interactively: peer-pay-cli webhooks test opens an arrow-key webhook selector, while peer-pay-cli webhooks test WEBHOOK_ID runs immediately. Only missing required inputs prompt; optional filters stay optional. Prompts write to stderr, including with --json. Piped stdin retains the usual missing-argument errors. See argument sources.

Install​

Requires Node.js 22 or newer.

npm install -g @zkp2p/peer-pay-cli

Check the installation:

peer-pay-cli --version
peer-pay-cli --help

Test locally​

Start your application's webhook handler, then start the mock backend in a separate terminal:

peer-pay-cli serve --state ./peer-pay.json

The backend listens at http://127.0.0.1:4020. It creates a local profile and stays running until you press Ctrl+C. No Peer account or database is required. Open that URL in a browser for the local ledger, quickstart commands, endpoint and documentation links, and command reference; the landing page never shows credentials. Keep the state file out of version control; it contains local credentials.

In another terminal, register your handler and create an order:

peer-pay-cli --local webhooks create \
--url http://localhost:3000/webhooks/peer-pay \
--events PAYMENT_SETTLED,ORDER_FULFILLED

peer-pay-cli --local orders create --amount 10

Copy the returned order.id and use it as ORDER_ID below:

peer-pay-cli --local payments create ORDER_ID --rail venmo
peer-pay-cli --local simulate ORDER_ID --event PAYMENT_SETTLED
peer-pay-cli --local orders get ORDER_ID
peer-pay-cli --local status

The order becomes FULFILLED. Your handler receives signed PAYMENT_SETTLED and ORDER_FULFILLED requests. status reports verification after the fulfillment webhook receives a successful HTTP response. No money moves.

To inspect delivery attempts, use the webhook.id returned when you registered the handler:

peer-pay-cli --local webhooks deliveries WEBHOOK_ID

Connect your application​

Export credentials directly to a new file:

peer-pay-cli --local credentials export --output .env.peer-pay --webhook-id WEBHOOK_ID

This writes PEER_PAY_API_URL, PEER_PAY_API_KEY, and PEER_PAY_WEBHOOK_SECRET. Load them through your application's environment configuration and add the file to .gitignore. Existing files are never overwritten.

Re-login uses the server-authorized API key. If the server withholds the key (for example, for a cashier), the CLI clears that profile's cached API key, order tokens, and webhook secrets. Previously copied merchant keys require server-side rotation to revoke them.

Point the SDK at the local API:

import { createCheckout } from '@zkp2p/pay-sdk';

const checkout = await createCheckout(
{ requestedUsdcAmount: '10' },
{
apiBaseUrl: process.env.PEER_PAY_API_URL!,
apiKey: process.env.PEER_PAY_API_KEY!,
},
);

console.log(checkout.order.id);

SDK 5.0.0 and later accept idempotencyKey and returns a null checkout URL on replay, matching the API's token policy. The API body field and peer-pay-cli orders create --idempotency-key already support it. Save the original checkout URL; replay does not recover it.

The mock serves API endpoints and a root landing page. Use the CLI to create payment attempts and simulate outcomes for this order; do not open its checkout URL. Test redirects, embedded checkout, and the customer payment experience against the hosted sandbox.

Verify webhook signatures over the raw request body, apply a timestamp tolerance, and deduplicate events by ID. See Webhook verification.

Test other outcomes​

# List all supported event names.
peer-pay-cli --local local events

# Settle part of an order, then create another payment for the remainder.
peer-pay-cli --local simulate ORDER_ID --event PAYMENT_SETTLED --payment-id PAYMENT_ID --amount 4
peer-pay-cli --local payments create ORDER_ID --rail venmo

# Fail an open payment attempt.
peer-pay-cli --local simulate ORDER_ID --event PAYMENT_FAILED --payment-id PAYMENT_ID

# Shorten the expiry for newly created payments.
peer-pay-cli --local local settings --data '{"quoteTtlSeconds":30}'

The simulator covers all 18 order, payment, refund, bridge, and chargeback events. Transitions must be valid: refunds and chargebacks require settled funds, and bridge events follow their normal lifecycle. See Simulation commands.

Set up your merchant​

Use a separate profile for your hosted merchant:

peer-pay-cli login --email owner@example.com
peer-pay-cli setup

Login sends an email code and creates your merchant account if needed. Setup asks for your business details and payment preferences, then shows the changes before applying them. You do not need to open the dashboard.

Follow Merchant setup from the terminal for the full walkthrough, JSON setup files, hosted sandbox testing, and going live.

Local and hosted profiles​

ProfileBackendWebhook destinationPayments
localMock on your computerYour localhost handlerSimulated
<name>-sandboxHosted sandbox, created by sandbox enable or setupPublic HTTPS endpointSandbox tests
<name>Hosted merchant account, named automatically by login or explicitly with --profilePublic HTTPS endpointLive orders require the merchant's configured plan and permissions

After you log in, commands target your Peer Pay account; add --local to target the mock, or peer-pay-cli use local. See profile selection for the precedence order, automatic naming, and how the active profile changes. Local verification does not complete hosted onboarding.

Help and output​

peer-pay-cli orders --help
peer-pay-cli orders create --help
peer-pay-cli orders create --amount 10 --json

Terminal output shows the result without the HTTP response wrapper. --json returns the full structured result; piping output also selects JSON automatically. Errors go to stderr and exit with status 1; successful commands exit with 0. Command output redacts credentials by default; see credential output for the exceptions and --show-secrets. To write saved credentials to an env file later, run credentials export --webhook-id WEBHOOK_ID.

The mock does not execute real payments, proof verification, liquidity selection, wallet transactions, billing, or emails. It stores merchant settings but does not render a checkout UI. Exchange rates are fixtures, not market prices.

See the command reference for every command, option, and example.

Use your coding agent​

Continue the application integration with Codex, Claude Code, OpenCode, or Gemini CLI:

peer-pay-cli handoff --harness codex --project ./my-store --launch

See handoff options for the supported agents, what the instructions contain, portable prompts, and continuing directly from setup.

Test Zcash deposits​

Enable near_intents_133701 in merchant settings before creating an order. Create the order with a Base USDC destination, then create a deposit:

peer-pay-cli --local merchant settings --data '{"enabledRails":["venmo","near_intents_133701"]}'
peer-pay-cli --local orders create --data '{"requestedUsdcAmount":"10","enabledRails":["near_intents_133701"],"destinationChainId":"8453","destinationToken":"USDC"}'
peer-pay-cli --local payments create ORDER_ID --rail near_intents_133701 --currency ZEC --refund-to YOUR_TRANSPARENT_ZCASH_ADDRESS
peer-pay-cli --local simulate ORDER_ID --event PAYMENT_SETTLED --payment-id PAYMENT_ID

The local mock uses the canonical NEAR Intents quote shape: a transparent deposit address, ZEC amounts in eight-decimal base units, a 20-minute deposit deadline, and the refund address. Its fixed rate is 0.01 ZEC per USDC, configurable through local settings. No funds move. Invalid refund addresses and unsupported tokens or destinations are rejected before creating a payment. The crypto choice in guided setup includes Zcash using its canonical rail name.

Test payouts locally​

With peer-pay-cli serve running on its default port, create a payout and simulate a Zelle payout:

peer-pay-cli payouts configure-local --local --rails zelle --payout-step 10
peer-pay-cli payouts create --local --email customer@example.com --amount 10 --funding-chain-id 8453 --funding-token 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 --idempotency-key local-payout-001

# Copy payoutId and the t query parameter from checkoutUrl in the create response.
PAYOUT_ID=PAYOUT_ID_FROM_RESPONSE
CASHOUT_TOKEN=LINK_TOKEN_FROM_CHECKOUT_URL
PLAYER_URL="http://127.0.0.1:4020/api/v1/cashout-checkout/$PAYOUT_ID"
peer-pay-cli payouts simulate-funding "$PAYOUT_ID" --local --status success --received 10

curl --fail-with-body "$PLAYER_URL/state" \
-H "x-cashout-token: $CASHOUT_TOKEN" -H 'Authorization: Bearer local-player:customer@example.com'
curl --fail-with-body -X PUT "$PLAYER_URL/payout-method" \
-H "x-cashout-token: $CASHOUT_TOKEN" -H 'Authorization: Bearer local-player:customer@example.com' \
-H 'Content-Type: application/json' --data '{"rail":"zelle","payeeHandle":"customer@example.com"}'
curl --fail-with-body -X POST "$PLAYER_URL/confirm" \
-H "x-cashout-token: $CASHOUT_TOKEN" -H 'Authorization: Bearer local-player:customer@example.com'

peer-pay-cli payouts resolve-send "$PAYOUT_ID" --local
peer-pay-cli payouts simulate-payment "$PAYOUT_ID" --local --step signaled
peer-pay-cli payouts simulate-payment "$PAYOUT_ID" --local --step fulfilled
peer-pay-cli payouts timeline "$PAYOUT_ID" --local
peer-pay-cli payouts emails "$PAYOUT_ID" --local

No funds move and no emails are sent; the final payout is SETTLED, with timeline entries and recorded customer emails. See Payout commands for the simulation options and Local customer checkout for all routes, auth headers and payout methods.

Choose your next step​

Run peer-pay-cli with no command in a terminal to pick from the interactive menu; see getting started for the menu items and the non-terminal behavior.

peer-pay-cli setup offers sign-in first if the selected profile has no hosted management session. After using a sandbox profile, peer-pay-cli use NAME switches back to its hosted profile. peer-pay-cli handoff asks for the agent and project, then confirms whether to launch; it works with either the local or hosted profile. Scripts remain flag-driven.

Run peer-pay-cli sandbox enable from a signed-in hosted profile to enable the remote sandbox, save <profile>-sandbox, and activate it. Use peer-pay-cli use NAME to return to your merchant account.

Simulate a payment creation pause​

Hosted payments create surfaces HTTP 503 with PAYMENTS_PAUSED when new payments are paused platform-wide. Orders and existing-payment processing remain available. Local mode implements the same creation error and checkout status:

curl --fail-with-body -X PATCH "$LOCAL_API_URL/local/settings" \
-H "x-api-key: $LOCAL_API_KEY" -H 'Content-Type: application/json' \
--data '{"paymentCreationPaused":true}'

Try peer-pay-cli payments create <orderId> --rail venmo against the local profile: it fails with PAYMENTS_PAUSED. The local order GET includes responseObject.paymentCreationPaused. Both creation endpoints and sandbox test orders reject while paused. Existing payment simulation/settlement and support recovery continue. Repeat the local settings PATCH with false to resume. This local runtime setting resets to false when the simulator restarts and never changes the hosted platform setting.