Documentation

Fund an order, get a person paid.

Everything an agent needs to turn crypto into a fiat payment made by a person: what to install, what it costs, what the IDs mean, and how to get unclaimed funds back.

Reading this as an agent? The same content is in plain text at /llms-full.txt.

On this page

Overview

PayHumans turns a payment an agent wants made into an order a person can fill. The agent locks crypto in escrow and states the terms: who gets paid, on which payment platform, in which currency, and at what rate. A person claims the order, sends the fiat from their own account, proves the payment, and receives the crypto.

Two things move, in two places. Crypto moves on-chain between the agent, the escrow contract and the person who pays. Fiat moves off-chain, from that person's payment account to the recipient. A proof of the fiat payment is the only thing that connects them.

Note

Creating an order does not pay anyone. It puts crypto in escrow and waits for a person. Treat the recipient as paid only when the order reports a fulfilled claim. See Status and partial fills.

Where funds sit

Every order settles the same way, whatever it was funded with.

  • The escrow is on Base. Orders are deposits in Peer's production escrow contract on Base (chain ID 8453). PayHumans deploys no contracts of its own.
  • The escrow holds USDC. Specifically USDC on Base, 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913.
  • Other assets are converted first. Funding from another chain or asset means a swap or bridge into USDC on Base, carried out by a routing provider before the deposit. There is no escrow on Solana, Ethereum or Bitcoin.
  • The order belongs to your Base account. With an EVM key, that is the key's own address. With a Solana key, the CLI derives a Base account from the key, so the agent still manages one secret. Keep that key: it is the only way to withdraw.
  • PayHumans never holds funds or keys. The CLI signs locally. Between the route and the deposit, funds sit in your own Base account.
Your keyFunding walletYour crypto, on its own chain
1Source network fee
In transitRouteProvider swaps or bridges to USDC on Base
2Route fee, quoted before you sign
Your keyYour Base accountUSDC on Base. It owns the order.
3Base gas for the approval and deposit
Peer contractEscrowUSDC locked for the order
Withdrawing sends unclaimed USDC from escrow back to your Base account.
Agent guide

Quickstart

The payhumans-ai-cli package installs one executable, payhumans. It needs Node.js 22 or newer. Results are JSON on stdout; errors are JSON on stderr with a non-zero exit code.

npm install -g payhumans-ai-cli
the whole flow
npm install -g payhumans-ai-cli

# 1. What can be paid, and what can fund it
payhumans platforms
payhumans routes

# 2. Preview an order. Nothing is signed or sent.
payhumans deposit create --platform revolut --recipient '<revtag>' \
  --amount 5 --currency USD --rate 0.98

# 3. Same command with an ID, a source spend cap and --yes
payhumans deposit create --platform revolut --recipient '<revtag>' \
  --amount 5 --currency USD --rate 0.98 \
  --operation-id invoice-1042 --max-source-spend 5.5 --yes

# 4. Watch it, then take back whatever was not claimed
payhumans deposit show <deposit-id>
payhumans deposit withdraw --id <deposit-id> \
  --operation-id invoice-1042-withdraw --yes

Every command that spends is a preview until you pass --yes. The sections below cover each step. payhumans --help and payhumans <command> --help are the authority for the version you installed.

Wallets and keys

The agent uses a wallet it already controls. There is no account to create, no API key, and no hosted wallet. Give the CLI one signing key through your secret manager, for the chain you fund from.

VariablePurpose
PAYHUMANS_SOLANA_KEYSolana signing key for a Solana funding wallet: a base58 secret or a Solana CLI JSON array.
PAYHUMANS_SOLANA_KEY_FILEPath to a file holding that key, instead of the variable above.
PAYHUMANS_EVM_KEY0x-prefixed private key for an EVM funding wallet (Ethereum, Base, Arbitrum, Optimism, Polygon). Also owns the order when funding with bitcoin. PAYHUMANS_PRIVATE_KEY is accepted as an alias.
PAYHUMANS_EVM_KEY_FILEPath to a file holding that key. PAYHUMANS_PRIVATE_KEY_FILE is accepted as an alias.
PAYHUMANS_STATE_DIROptional. Where operation journals are kept. Defaults to ~/.payhumans/operations. Keep and back up this directory: it is what protects a retry from paying twice.
PAYHUMANS_SOLANA_RPC_URLOptional. Your own Solana RPC endpoint.
PAYHUMANS_ESCROW_RPC_URLOptional. Your own Base RPC endpoint.
PAYHUMANS_RPC_<chainId>Optional. Your own RPC endpoint for one EVM chain, for example PAYHUMANS_RPC_1 for Ethereum.
PAYHUMANS_EVM_RPC_URLOptional. Your own RPC endpoint for whichever EVM source chain you selected.
PAYHUMANS_RELAY_API_KEYOptional. Your own Relay API key.
PAYHUMANS_NEAR_INTENTS_TOKENOptional. Your own NEAR Intents token, used only by the bitcoin route.
Risk

Never put a key in a command argument, a prompt, a log, or this website. The CLI reads keys only from the environment or a key file, and redacts them from its error output.

The browser login on payhumans.ai is separate and optional. It exists for people recovering a claim made on this site, and agents never need it.

Balances

payhumans wallet prints two things: the balance of the asset you fund from, and your Base account with its USDC and ETH. Pass the source you plan to use.

balances
payhumans wallet                                             # USDC on Solana (default)
payhumans wallet --source-chain solana --source-asset SOL
payhumans wallet --source-chain ethereum --source-asset ETH
  • The funding wallet needs the asset itself plus that chain's network fee: a little SOL on Solana, a little ETH on an EVM chain.
  • The Base account needs a little ETH for the approval and the deposit. When you fund from another chain the CLI buys a small amount through the route if the balance is low. When you fund from Base, or with bitcoin, it must already hold ETH: the CLI checks for at least 0.00002, and the transactions can cost more than that.
  • USDC already in your Base account is used first. Only the shortfall is routed from your funding wallet.

Platforms and recipients

An order names one payment platform, one fiat currency and one recipient. Ask the CLI what is supported rather than hard-coding it; the catalog changes.

Keep three sets apart. 12 platforms are in the Peer catalog and can be named in an order. 10 of them can be filled in the Peer mobile app. 8 of those can be chosen in the app's order alerts.

discover
payhumans platforms        # payment platforms, currencies, recipient rules
payhumans routes           # crypto sources the CLI can fund from
payhumans routes --live    # plus what the routing providers advertise right now

Recipient identifiers

Each platform identifies a recipient differently, and some need a one-time step before they can receive. This table reflects Peer's rules on 2026-10-04; payhumans platforms is the authority.

PlatformRecipient is aBefore the first orderIn Peer appAlerts
VenmovenmoVenmo usernameUSDChecked against the live Venmo profile when the order is created.YesYes
RevolutrevolutRevtagUSD, EUR, GBP and 21 moreChecked against the public Revolut profile when the order is created.YesYes
Cash AppcashappCashtag, without the leading $USDThe Cash App profile must be public and resolve.YesYes
WisewiseWisetag, without the leading @USD, CNY, EUR and 28 moreA recipient Peer has not seen before must verify the account once. The recipient does this themselves; an agent cannot. An already verified recipient can be reused.YesYes
PayPalpaypalPayPal.me username, not an emailUSD, EUR, GBP and 4 moreSame one-time verification as Wise. The recipient must be a personal PayPal account.YesYes
ZellezelleEnrolled email address, lowercaseUSDFormat check only. Nothing confirms the email is enrolled with Zelle, so confirm it with the recipient.YesYes
Chimechime$ChimeSign, lowercase, with the leading $USDFormat check only. Confirm the ChimeSign with the recipient.YesYes
MonzomonzoMonzo.me usernameGBPChecked against the Monzo profile when the order is created.YesYes
Mercado Pagomercadopago22-digit CVUARSChecksum validation only.NoNo
UPIupiVPA such as name@bank, lowercaseINRFormat check only. In the Peer app the payer proves the payment through Amazon Pay: person-to-person UPI from a linked bank account. UPI Lite and merchant payments are not supported.Newer versionsNo
AlipayalipayAlipay account emailCNYSame one-time verification as Wise.Newer versionsNo
X MoneyxmoneyX username, without the leading @USDFormat check only. Nothing confirms the account exists or has X Money enabled, so confirm it with the recipient.NoNo

“In Peer app” says whether people can fill orders on that platform in the Peer mobile app. “Newer versions” (UPI and Alipay) means support is in the app's current source but we have not confirmed it in the store build. An order on a platform marked “No” (Mercado Pago and X Money) can be created, but cannot be filled through the current Peer mobile app; other Peer surfaces may differ. “Alerts” says whether the app's opt-in order alerts can be set for that platform. All of this comes from the app's source and has not been observed on a production device.

Validate and register

Check a recipient before you fund anything. Registering stores the recipient's payment details with Peer so the app can show them to whoever claims; it moves no crypto. deposit create --yes registers for you if you skip this.

recipient
payhumans recipient validate --platform revolut --recipient '<revtag>'
payhumans recipient register --platform revolut --recipient '<revtag>'         # preview
payhumans recipient register --platform revolut --recipient '<revtag>' --yes
payhumans recipient show --platform revolut --hash '<registered-payee-hash>'
Risk

Validation checks the format, and on some platforms that the profile exists. It never proves the handle belongs to the person you mean to pay. Confirm the exact identifier with the recipient; fiat sent to a wrong handle is gone.

Wise, PayPal and Alipay need the recipient's help

On these platforms a recipient Peer has not seen before must prove they own the account, once, in a desktop browser with the Peer extension. The pages are app.peer.xyz/sell/wise, app.peer.xyz/sell/paypal and, for Alipay, app.peer.xyz/sell (see Peer's seller guide). An agent cannot do this for them. Until it is done, the CLI stops with RECIPIENT_REGISTRATION_REQUIRED before any funds move. A recipient who is already verified can be reused.

Funding routes

You choose what to fund with using --source-chain and --source-asset. The default is USDC on Solana. The CLI converts to USDC on Base through a routing provider (Relay) and refuses a source it cannot route before anything is sent. The table separates routes tested with real funds from routes that are implemented but still untested.

Fund withOnStatusNotes
USDCSolanaTested on mainnetMainnet deposits 5962, 5968 and 5970 on October 2, 2026: funded, created, withdrawn and returned to the Solana wallet.
USDCBaseListed, not testedAlready the settlement asset, so there is no conversion and no route fee. The wallet must already hold ETH on Base for gas.
USDCEthereum, Arbitrum, Optimism, PolygonListed, not testedBridged to USDC on Base by the routing provider.
ETHEthereum, BaseTested on mainnetIndependent installed-CLI tests funded 5 USDC each: Ethereum deposit 6020 and Base deposit 6021 on October 4. This verifies funding, not fiat payment.
ETHArbitrum, OptimismListed, not testedSwapped to USDC on Base by the routing provider.
SOLSolanaTested on mainnetNative SOL funded 5 USDC in mainnet deposit 6019 on October 4. The unused escrow was withdrawn to its Base owner.
BTC (native)BitcoinTested on mainnetAn external native Bitcoin wallet funded 10 USDC in deposit 6022 through NEAR Intents on October 4; the unused escrow was withdrawn on Base. You send BTC yourself once. Provider minimums vary and Bitcoin network fees are extra. The CLI never holds a Bitcoin key; wrapped bitcoin is not accepted.
Tested on mainnet
PayHumans funded, created and withdrew a real deposit through this route.
Listed, not tested
Implemented in the CLI. PayHumans has not yet funded a deposit through it. A preview that succeeds is a quote, not a funded test.
Not available
The CLI rejects this source. Nothing is sent.
  • A listed route still needs a live quote. Availability, minimum size and fees are decided when you preview, not by this table.
  • Native bitcoin works differently. The CLI holds no Bitcoin key. It returns a deposit address, an exact amount and a deadline from the provider (NEAR Intents); you send BTC once from your own wallet, then resume the operation. It needs --refund-address, an EVM key to own the order, and ETH on Base for gas. The provider's minimum varies: a quote for a 5 USDC order was rejected and one for 10 USDC succeeded. Your Bitcoin network fee is extra, and a failed route may refund less than you sent. Never send after the deadline, or twice. On October 4, native BTC funded 10 USDC in mainnet deposit 6022; the unused funds were recovered on Base. Fiat payment remains unverified.
  • Wrapped bitcoin is not bitcoin. WBTC, cbBTC and similar tokens are separate assets and are not accepted.

Preview and cost

Run deposit create without --yes. With a key configured, the CLI checks the recipient's format, fetches a live route quote, and prints the plan. With no key it prints the terms only. Either way nothing is registered, signed or sent.

preview
# Preview: prints the plan as JSON. Nothing is signed or sent.
payhumans deposit create --platform revolut --recipient '<revtag>' \
  --amount 5 --currency USD --rate 0.98
another source
# The same order, funded from ETH on Ethereum instead
payhumans deposit create --platform revolut --recipient '<revtag>' \
  --amount 5 --currency USD --rate 0.98 \
  --source-chain ethereum --source-asset ETH

What an order costs you

CostWhat it isIn the preview
The rate--amount is the gross USDC in escrow, and --rate is fiat sent per USDC of escrow claimed. At 0.98, a claim of 5 USDC asks for $4.90, rounded up to a cent.fiatForFullDeposit
Route feeThe routing provider's charge to convert your asset to USDC on Base. Zero when you fund with USDC on Base.routes.funding
Network feesGas on the source chain, and on Base for the approval and deposit.routes.gas, caps

totalSourceInput is what the route takes from your funding wallet, in the source asset, with the route's fees included. Network gas you pay directly is on top of it.

Peer's own fees are not yours to pay. They are taken from the USDC the person claims, so someone who claims 5 USDC receives a little less than 5. The Peer app shows them the exact net amount before they commit.

Limits you set

The CLI stops before signing if a quote exceeds any limit. --max-source-spend is required to execute; the others have defaults.

--max-source-spend
What the route may take from your funding asset, in that asset's units: the amount converted, fees priced into the route, and any Base gas the route buys. Required with --yes. For USDC sources, --max-spend is accepted as an alias and also caps the deposit itself.
--max-route-fee-usd
The routing provider's service and relay fees, in USD. Default 2.
--slippage-bps
Swap slippage tolerance. Default 50, range 0 to 100.
--max-source-gas
Execution gas on the source chain. Default 0.002 SOL or 0.001 ETH. A ceiling, not an amount held in reserve.
--max-base-gas
Execution gas on Base for the approval and deposit. Default 0.0001 ETH.
Risk

The limits do not cover every cost. These are extra:

  • L1 data fees that Base and other rollups add on top of execution gas.
  • Solana account rent.
  • The Bitcoin network fee on a payment you send from your own wallet.

Leave a small margin for them. Each limit also covers one order only, so keep your own budget across orders.

Create an order

Repeat the command you previewed and add three things: an operation ID you choose, a source spend limit, and --yes.

create
# Same command, plus an operation ID, a source spend cap and --yes.
payhumans deposit create --platform revolut --recipient '<revtag>' \
  --amount 5 --currency USD --rate 0.98 \
  --operation-id invoice-1042 --max-source-spend 5.5 --yes

In order, the CLI then:

  1. Validates and registers the recipient, and prepares the deposit. No funds have moved yet.
  2. Runs the route: your asset becomes USDC in your Base account.
  3. Approves the escrow for exactly the order amount.
  4. Creates the deposit and reads its ID from the transaction receipt.
  5. Turns off Peer's dispute protection for the order's platform. That removes the stake a person would otherwise have to post to claim, and nothing else: Peer's other eligibility rules still apply. You accept the risk of a payment being reversed after release. Pass --require-stake to keep it on.

The result includes depositId, compositeDepositId, transactionHash, each route's requestId and status, and a claimUrl.

Orders several people can fill

--min and --max set the smallest and largest single claim, in gross USDC. By default a claim can be anything from 1 USDC up to the whole order. Each claim is a separate fiat payment, so the recipient may receive several smaller payments instead of one.

partial fills
# One order that several people can fill, 1 to 5 USDC at a time
payhumans deposit create --platform revolut --recipient '<revtag>' \
  --amount 20 --currency USD --rate 0.98 --min 1 --max 5

All flags

FlagNeededMeaning
--platform <name>AlwaysPayment platform, from payhumans platforms.
--recipient <id>AlwaysWho gets the fiat, in that platform's identifier format.
--amount <usdc>AlwaysUSDC to put in escrow. This is the gross amount, before Peer's fees.
--currency <code>AlwaysFiat currency the recipient is paid in.
--rate <fiat-per-usdc>AlwaysFiat a person sends per USDC of escrow they claim. 0.98 means $4.90 for a 5 USDC claim. Peer's fees then come out of that USDC, so the person receives a little less than they claimed.
--source-chain <chain>Default solanaWhere the funding crypto is: ethereum, base, arbitrum, optimism, polygon, solana or bitcoin.
--source-asset <asset>Default USDCETH, SOL, USDC or BTC, depending on the chain.
--min <usdc>, --max <usdc>OptionalSmallest and largest single claim. Defaults: 1 USDC (or the full amount if smaller) and the full amount.
--operation-id <id>With --yesYour own unique ID for this payment. Reuse it on every retry: the CLI then resumes the saved operation from its local journal instead of starting a new payment.
--max-source-spend <amount>With --yesMost of the source asset the route may take, including fees priced into the route and any Base gas it buys. Network gas you pay directly is not included. For USDC sources, --max-spend is accepted as an alias and also caps the deposit.
--max-route-fee-usd <usd>Default 2Most the routing provider may charge in service and relay fees, in USD. Source network gas is separate.
--slippage-bps <bps>Default 50Swap slippage tolerance, 0 to 100 basis points.
--max-source-gas <native>Default 0.002 SOL or 0.001 ETHCeiling on source-chain execution gas. Solana account rent and your own Bitcoin transaction fee are not covered by it.
--max-base-gas <eth>Default 0.0001Ceiling on Base execution gas for the approval and deposit. The L1 data fee Base adds can be extra.
--require-stakeOptionalKeep Peer's dispute protection on, so people must post stake to claim.
--refund-address <btc-address>Bitcoin onlyYour own mainnet Bitcoin address, used if the provider has to refund. A refund can be less than you sent.
--yesTo executeSign and send. Without it every command is a preview.

Identifiers

Five IDs appear in the output. Store them all with your record of the payment.

IDComes fromUse it to
operationIdYou choose it. One per payment; 1 to 80 letters, digits, hyphens or underscores.Retry or resume. While its local journal exists, the same ID resumes the saved operation instead of starting a new payment.
depositIdThe escrow contract, when the deposit is created.Read status and withdraw.
compositeDepositIdThe escrow address and deposit ID joined by an underscore.Refer to the order unambiguously in Peer's APIs and app.
intent hashEach claim a person makes. Listed under intents in deposit show.Tell claims apart and see which were fulfilled.
requestIdThe routing provider, one per swap or bridge.Reconcile a slow or failed route before retrying.

Status and partial fills

deposit show needs no key. It reports where the order's USDC is right now and lists every claim. Top-level balances are decimal USDC; nested intent amount fields use 6-decimal base units (1000000 means 1 USDC), labeled by intentAmountUnits. The disputeProtection field reports current platform policy and stake requirements; null means unknown or closed, not disabled.

status
payhumans deposit show <deposit-id>
payhumans deposit list --owner '<Base-deposit-owner-address>'
# Or derive the owner from your configured source wallet:
payhumans deposit list --source-chain ethereum --source-asset ETH
Example order20 USDC funded, claims of 1 to 5 USDC
Funded funded
USDC the agent put into the order.
Available available
USDC nobody has claimed. Open to be claimed, or withdrawn by the agent.
Reserved reserved
USDC held for a person's active claim. Locked until that claim is fulfilled, cancelled, or expires and is cleared.
Fulfilled fulfilled
USDC released from escrow against verified fiat payments. Gross: the people who paid received this less Peer's fees.
Withdrawn withdrawn
USDC the agent took back.
funded = available + reserved + fulfilled + withdrawn
  • A claim is not a payment. A claim in the SIGNALED state is a reservation. Only FULFILLED means the escrow released USDC against a verified fiat payment.
  • Fiat delivered so far is about fulfilled multiplied by your rate; each claim's fiat amount is rounded up to a cent. For proof of one payment, read that claim's receipt fields under intents.
  • Amounts are gross. fulfilled is what left escrow. The people who paid received that less Peer's fees.
  • Two sources, two speeds. available and reserved are read from the chain. funded, fulfilled, withdrawn and intents come from Peer's indexer and can trail by a short time. If indexed is false, the indexed fields are null rather than zero, and only the chain values are present.
  • Polling. Once a minute is plenty. An order is finished when available and reserved are both zero.

Expiry and cancellation

  • A claim reserves USDC for a limited window set by Peer. Its expiry time is on the claim.
  • The person can cancel a claim they have not paid. The reserved USDC becomes available again.
  • If the window passes without a valid proof, the claim is no longer valid. Its USDC may still show as reserved until Peer clears the expired claim; after that it can be claimed again or withdrawn. Check the claim's status before acting.
  • The agent cannot cancel someone else's active claim, and should not try to work around one: that person may already have sent the fiat.
  • An order itself does not expire. It stays open until it is filled or you withdraw.
States of the USDC in an orderAvailable USDC becomes reserved when a person claims it. A valid payment proof before the claim expires releases it to that person. If the claim expires or is cancelled, the USDC becomes available again. The agent can withdraw available USDC at any time.a person claimspays and provesbefore the claim expiresclaim expires or is cancellednothing is paid outagent withdrawsavailable USDC onlyFiat sent, but the proof fails or is late:the escrow does not pay, and the fiat is not recoverable hereAvailableUSDC open to claimReservedclaimed, clock runningFulfilledUSDC released to payerWithdrawnUSDC back with the agent

Recovery and withdrawal

An interrupted run

The CLI keeps a local journal in ~/.payhumans/operations (override with PAYHUMANS_STATE_DIR). If a run crashes or a route is slow, resume it from there.

operations
payhumans operations list
payhumans operations show invoice-1042
payhumans operations resume invoice-1042          # preview
payhumans operations resume invoice-1042 --yes
  • Every signed crypto operation writes a journal of its steps there, named by operation ID. Recipient registration moves no crypto and creates no operation journal.
  • It holds public data only: recipient handles, addresses, quote and route request IDs, unsigned transaction data, transaction hashes and nonces, your limits, and deposit IDs. It never holds private keys.
  • Retry protection lives in that journal. Reusing an operation ID resumes the saved operation only while its journal exists, so keep the directory and back it up. If it is deleted, the CLI no longer knows what was already sent.
  • An operation ID cannot be reused with different parameters, and a wallet lock stops two CLI runs from using one wallet at once. Do not use the same wallet from another tool while an operation is in flight.
  • A different operation ID is a different payment. Do not answer a timeout by choosing a new ID: inspect the operation and resume it.
Risk

The journal is the protection, not the ID alone. If funds have already left your wallet and the journal is gone, or you pick a new ID, the CLI can fund a second order. When unsure, read operations show, check the route and transaction it lists, and resume.

Take back unclaimed funds

deposit withdraw removes available USDC from the order (all of it unless you pass --amount) and sends it to your Base account. It never touches reserved USDC and never cancels a claim.

The command signs with the wallet selected by --source-chain and --source-asset. The default is the Solana key, so pass the same source you funded with.

withdraw
payhumans deposit withdraw --id <deposit-id>              # preview
payhumans deposit withdraw --id <deposit-id> \
  --operation-id invoice-1042-withdraw --yes

# Funded from an EVM wallet? Name it, so the CLI signs with that key.
payhumans deposit withdraw --id <deposit-id> \
  --source-chain ethereum --source-asset ETH \
  --operation-id invoice-1042-withdraw --yes

Send it home

After a withdrawal the USDC is in your Base account. With an EVM key, that is already your wallet. With a Solana key, return routes it back to the same Solana wallet as USDC; --min-receive is required and bounds fees and slippage. There is no route back to bitcoin.

return
payhumans return --amount 5                             # preview, shows minimum received
payhumans return --amount 5 --min-receive 4.8 \
  --operation-id invoice-1042-return --yes

Remove the stake requirement

If dispute protection is still on for an order, people must post stake to claim it. deposit open-claims turns it off for one platform on one order. It removes that stake requirement only; Peer's other eligibility rules still apply.

open claims
payhumans deposit open-claims --id <deposit-id> --platform revolut \
  --operation-id invoice-1042-open --yes

Errors

A failed command exits non-zero and writes one JSON object to stderr. Stdout carries only successful results, so it is safe to parse.

stderr
{
  "error": {
    "code": "RECIPIENT_REGISTRATION_REQUIRED",
    "message": "...",
    "next": "..."
  }
}
  • INVALID_ARGUMENT: a flag is missing or malformed. Nothing was sent.
  • RECIPIENT_REGISTRATION_REQUIRED: the recipient must complete Peer's one-time verification. Nothing was sent. Retry the same operation ID afterwards.
  • OPERATION_NOT_FOUND: no journal exists for that ID in the current state directory. Run operations list and check PAYHUMANS_STATE_DIR. If funds may already have moved, reconcile the original transaction before starting a new operation.
  • REQUEST_FAILED: anything else. Read message; if a run with --yes had started, inspect the operation before retrying.
Human guide

How people fill orders

An order is an ordinary Peer deposit, so people fill it in the Peer mobile app, from its P2P tab or Buy USDC flow. From their side they are buying USDC at your rate by paying your recipient. There is no PayHumans account, and nothing to enrol in beyond the app itself. This workflow is taken from the app's current source; we have not yet observed it on a production device.

  1. They choose a currency and a payment platform they already use.
  2. The app lists open orders by price. They pick one and claim some or all of it.
  3. They send the exact fiat amount to the recipient shown, from their own account.
  4. They verify the payment inside the app. The escrow releases the USDC to them, less Peer's fees.
Note

Nobody is guaranteed to see your order. An order can appear in the Peer app once Peer has indexed it, if it passes the app's filters and eligibility rules: a platform and currency the app supports, enough unreserved USDC, a usable exchange rate, a minimum order value (about $1 by default), and the person's own platform, amount and price filters.

The app's alerts for new orders are opt-in, limited to 8 platforms (Venmo, Revolut, Cash App, Wise, PayPal, Zelle, Chime and Monzo), filtered by price and by a minimum size that defaults to $25, and rate-limited. Delivery has not been verified. A small order can sit unclaimed.

10 platforms can be filled in the app: Venmo, Revolut, Cash App, Wise, PayPal, Zelle, Chime and Monzo, and in newer versions UPI and Alipay. UPI payments are proved through Amazon Pay, and Zelle payments from Bank of America or Citi.

The full walkthrough for people, with download links, is at /earn.

Lifecycle

Who does what, in order. Blue cells are a person's actions.

1Fund
2Claim
3Pay
4Prove
5Release
Agent
Creates the order: recipient, platform, amount, rate
Sees the claim as fulfilled in status
Escrow
USDC locked. Order is open.
That amount is reserved. The claim's clock starts.
Checks the proof against the claim
Releases the reserved USDC to the person
Person
Claims some or all of it in the Peer app
Sends fiat from their own account
Verifies the payment in the app
Recipient
Receives the fiat

Web claim links

The CLI returns a claimUrl of the form payhumans.ai/earn?deposit=<id>. It opens the claim page, which shows that order's live terms read from the escrow. Share it with a person so they can check the recipient, amount and rate before they look for the order in the Peer app.

The same page keeps the original browser flow working: sign in with email or a passkey, claim, and verify with the Peer browser extension. Claims made that way, and their ?intent= and ?claimTx= links, can still be reopened, verified or cancelled there.

Reference

Verification limits

Payment verification is done by Peer's verification service and escrow contract, not by PayHumans. It has limits worth knowing.

  • Only supported platforms and currencies can be proved, and support differs between them.
  • The proof must match the claim: recipient, amount, currency, and a payment made after the claim.
  • A proof shows a payment left the person's account. It does not cover later reversals, disputes or holds by the payment platform.
  • Changes on a payment platform can temporarily break verification for it.

About PayHumans

PayHumans.ai is an independent project. It began as a website prototype on March 27, 2026. The CLI, the live escrow integration and this site were built from October 2, 2026 onward.

The escrow contracts, payment verification, SDKs and mobile app are Peer's existing infrastructure, not new work by PayHumans. Routing is provided by Relay, and by NEAR Intents for external-wallet native bitcoin. Privy provides the optional browser login on the claim page.

Prepared for Chiang Mai Build Lab.

For machines