Skip to main content

Fees, settlement and refunds

What an order costs, what arrives in your wallet, and how to account for it.

Everything here applies to every way of creating orders: the Telegram bot, WooCommerce, Shopify, the SDK and payment links.

What you pay​

The standard software fee is charged per successful payment: Base is 2.95% on payment app orders and 1% on pay with crypto, Pro is 4.95% and 1%, and Concierge rates are agreed with the team. The full table, with the monthly caps and what each plan includes, is in plans and support. Concierge terms can add account specific splits; use your account terms and the checkout quote for the total.

  • Same rate on every payment app. Base and Pro charge the same percentage whichever payment app the customer uses. Only Concierge accounts can carry a different rate per platform.
  • No other charges on Base and Pro. No setup fee, subscription, monthly minimum, payout fee or gas. Peer submits the settlement transaction on Base and pays its gas.
  • Sandbox is free. There is no free allowance on live orders; the fee applies from the first live payment.
  • Deducted at settlement. Standard Base and Pro fees are deducted onchain, so what lands in your wallet is already net. Concierge accounts follow their agreed terms, which can include flat fee invoicing.

The peer's rate​

Peer Pay is a marketplace. Each payment is filled by a peer offering liquidity for that platform, currency and size, and that peer sets a rate. Two rates matter.

RateWhat it isWhere you see it
Market rateThe reference rate between the customer's currency and USD, snapshotted for each payment. USD is always 1.currencyPerUsdRate on the payment
Peer's rateThe rate the filling peer offers. The gap above the market rate is the spread.Reflected in the USDC released at settlement, separately from onchain fees

Peer converts a fiat priced order to USDC at the market rate when the order is created, and credits the customer's payment to the order at the market rate too. The spread is what the peer keeps. When the peer's rate is at or better than market, the spread is zero.

What to expect in practice​

There is no fixed spread to quote. Peers price their own liquidity and reprice it as they like, so the spread moves with the payment platform, the currency, the order size and the time of day, and it is zero or negative when a peer is willing to fill at or under market. Your plan's fee is the only fixed part of the cost.

Three things move it in a predictable direction.

  • Platform and currency. Each platform and currency pair is its own pool of peers. A pool with many peers competing prices close to market; a thin pool prices wider and is more often unavailable. Enabling every platform your customers use widens the pool.
  • Order size. One peer fills one payment, so the whole amount has to fit inside a single peer's available balance and order range. Larger orders draw from fewer peers, which shows up as wider spreads and more unavailable quotes than the same cap gives at a smaller size.
  • Your cap. Under merchant pays, buyer pays, or split the max fee bounds the fee plus spread you will accept. It never lowers a peer's price; it only decides which quotes are shown.

The number to plan with is your own realized cost. Every settled payment carries the market rate, the peer's rate, the fee and the net USDC (the fields below), so after a few dozen orders you can compute your actual average and spread range per platform and set the cap from data rather than from the ceiling. Before go-live, quote availability tells you whether an amount can be filled at your cap right now and, when it cannot, which nearby amounts can.

Who pays​

Who pays the fee under Settings, Payments decides who bears the fee and the spread. How the setting works, and how to cap what you pay, is in fee models.

The table and example below describe standard pricing with the spread added separately. If your account has spread-inclusive pricing, the spread reduces the software fee instead of being added on top; quotes that exceed the configured fee budget are unavailable. Use your account terms and the final checkout quote for that configuration.

ModeThe customer sendsYou receiveCap
Merchant paysExactly the order amount: 100.00 USD on a 100.00 USD order.The order amount in USDC, less the fee and the spread.Max fee configuration caps fee plus spread together (how it is checked). New accounts start at 20 percent.
Buyer paysThe order amount plus the fee and the spread.The full order amount in USDC at the market rate.The same configured fee-plus-spread cap, defaulting to 20% for new accounts.
SplitThe order amount plus the buyer share of total fees.The gross payment in USDC, less all fees and spread.The same cap on total fee plus spread as merchant pays, before allocating costs by the buyer share.

The customer sees one final amount per payment app on the checkout before they pay. It already includes the fee and the peer's rate, and it is not itemized.

Worked example​

A 100.00 USD order on standard pricing, with the filling peer's rate 1 percent above the market rate. Amounts are rounded to cents. The real spread is whatever the peer offers at that moment, and zero when their rate is at or better than market.

Merchant pays, BaseMerchant pays, ProBuyer pays, Base
Customer sends100.00 USD100.00 USD104.07 USD
USDC the peer releases99.01 USDC99.01 USDC103.04 USDC
Spread, kept by the peer0.99 USD0.99 USD1.03 USD, paid by the customer
Software fee, on the USDC released2.92 USDC (2.95%)4.90 USDC (4.95%)3.04 USDC (2.95%), paid by the customer
You receive96.09 USDC94.11 USDC100.00 USDC

Under merchant pays the customer pays the list price and both the spread and the fee come out of what settles. Under buyer pays the checkout grosses the price up so that, after the fee, exactly the order amount settles, and the customer sees one final number that already includes the fee and the spread.

Under split, the percentage is the buyer share of total fees, including the quote costs on fiat, Apple Pay, and crypto. A 30:70 buyer:merchant ratio allocates 30% of those costs to the buyer and 70% to you. At 0:100 you pay all fees; at 100:0 the buyer pays all fees. The dashboard uses 10% steps, and orders keep the share saved at creation.

What settles to your wallet​

Verified payment app payments release USDC on Base to your merchant wallet, or are bridged onward when payout routing points at another chain or token. Crypto payments follow their configured payout route and can settle on another chain. Peer never holds the funds and cannot reverse a settlement. There is no fiat payout: SEPA and bank payouts are not offered. Withdraw in the Peer app or route the USDC yourself.

Reconcile on the order, not the amount​

Under merchant pays, netSettledUsdcAmount can be lower than requestedUsdcAmount, because fees and the peer's rate affect what you receive. The order still completes: Peer credits the order with the customer's full payment converted at the market rate, and marks it FULFILLED when the outstanding balance is within the completion threshold. A fulfilled order can retain a small nonzero remainingUsdcAmount.

Under split, the principal credited is (1 - s) * buyerPaidUSD + s * netSettlement, where s = buyerFeeShareBps / 10000 and buyerPaidUSD is the payment converted at market. For example, at 50:50, a buyer payment worth $105 and net settlement of $95 credits $100 of principal. Net settlement can be below the order total here too.

A handler that rejects a settlement because the settled USDC is below the order total can reject a fulfilled merchant pays or split order. Instead:

  1. Release goods on ORDER_FULFILLED, or when data.order.status is FULFILLED.
  2. Book netSettledUsdcAmount as the USDC received and totalUsdcFeeAmount as the onchain fees. The latter excludes the peer's spread; keep the fiat amount and market rate to reconcile the exchange-rate difference separately. For Relay crypto payments, read the fee fields from the Payments API a few minutes after PAYMENT_SETTLED, because the webhook snapshot can carry an estimate.
  3. Under buyer pays, each payment's netSettledUsdcAmount contributes to the order total. Reconcile all settled payments on the order and account for any penalty.

Fields for your ledger​

The PAYMENT_SETTLED and ORDER_FULFILLED webhooks carry order and payment snapshots. The Payments API returns payment fields; fetch the matching order from the Orders API using orderId for its fiat metadata.

  • paymentAmount, currency: What the customer sent, in their currency.
  • currencyPerUsdRate: The market rate used for that payment, in the customer's currency per USD.
  • quote.conversionRate: The peer's rate for that payment, in the customer's currency per USDC. The gap above currencyPerUsdRate is the spread.
  • netSettledUsdcAmount: USDC delivered to your wallet.
  • totalUsdcFeeAmount: Onchain fees in USDC: gross USDC released minus net USDC settled. Excludes the peer's spread.
  • fulfillTransaction: The settlement transaction hash. Payment app settlements are on Base; for Relay crypto payments it is the destination chain transaction, so use the order's destinationChainId to pick the explorer.
  • order.metadata: Contains requestedFiatAmount and requestedFiatCurrency, the price you set when the order was created in fiat.

Store the webhook payload with your own order record, keeping the settlement hash and its chain, and every line traces to an onchain transaction.

Deriving the spread and the fiat value at receipt​

The spread is not a field. Derive it, and the fiat value of what you received, from the fields above. A 100.00 EUR payment at a market rate of 0.90 EUR per USD, filled by a peer priced 1 percent above market on Base: the peer released 110.01 USDC, the fee was 3.25 USDC and 106.76 USDC settled.

LineFormulaExample
Gross USDC at marketpaymentAmount / currencyPerUsdRate100.00 / 0.90 = 111.11 USDC
USDC the peer releasednetSettledUsdcAmount + totalUsdcFeeAmount106.76 + 3.25 = 110.01 USDC
Spread in USDCgross at market minus USDC released111.11 - 110.01 = 1.10 USDC
Fiat value receivednetSettledUsdcAmount x currencyPerUsdRate106.76 x 0.90 = 96.08 EUR
Fee in fiattotalUsdcFeeAmount x currencyPerUsdRate3.25 x 0.90 = 2.93 EUR
Spread in fiatpaymentAmount minus the two lines above100.00 - 96.08 - 2.93 = 0.99 EUR

currencyPerUsdRate is snapshotted per payment, so each line uses its own rate. Book the fiat value received as the revenue recognized at settlement, the fee and the spread as costs, and fulfillTransaction as the reference. Where your accounting needs crypto valued in fiat at the moment of receipt, this is that valuation.

Statements and exports​

Standard Base and Pro plans do not issue monthly fee invoices or settlement statements. Concierge invoicing follows your agreement. Your records are:

  • Orders CSV. Orders in the Merchant Portal exports up to 5,000 rows with order ID, method, amount requested, amount settled, settlement token and chain, status and created time. It does not carry the fiat amount, the rate, the fee or the transaction hash.
  • Payments API. List payments filtered by status=SETTLED returns the payment fields listed above. Paginate through the results and join each orderId to the Orders API for the order metadata.
  • Webhooks. The same fields arrive on PAYMENT_SETTLED, so a handler that stores payloads builds the ledger as you go.

There is no processor in the flow, so there is no processor invoice to file. For standard payment app orders your customer pays a peer on their own app, the protocol releases USDC from onchain escrow to your wallet, and the fee comes out of that release. The settlement transaction and the fields above are the record. Concierge invoicing follows your agreement.

Refunds​

Settlement is one way. Peer cannot pull USDC back out of your wallet or reverse a payment on the customer's app. A refund is a new transaction that you start and fund. Only the Owner can read, create or cancel refunds. Refunds are available to live merchants only; the action is not offered in Sandbox Mode.

How it works​

  1. An Owner opens the order under Orders in the Merchant Portal and starts the refund. There is no API key endpoint for refunds.
  2. Enter and verify your customer's original platform handle in Refund To. The field starts empty: Peer uses the handle you submit and does not recover it from the original payment. Peer then posts the refund as a USDC offer funded from your merchant wallet on Base, to that recipient. Your wallet has to be delegated to the Peer signer under Settings and hold enough USDC.
  3. A peer sends your customer the fiat on the same platform and takes the USDC. The offer is priced about one percent better than the market rate so it is picked up quickly, so expect to post about one percent more USDC than the market rate implies.
  4. The order's refundStatus moves from NONE to PENDING to COMPLETED, firing REFUND_PENDING and REFUND_COMPLETED. The order records the USDC you posted and, once a peer fills it, the refund transaction hash. A refund you cancel before a peer takes it returns the USDC to your wallet and fires no event.

An offer no peer has taken stays open until you cancel it. It does not expire and fires nothing while it waits, so watch refundStatus on orders you have refunded. If one sits, cancel it and post again, or refund the customer by another route.

Rules​

  • Refunds cover the full payment amount in the customer's currency: the customer gets back exactly what they paid, on the app they paid with, and you fund it in USDC. Partial refunds are not supported.
  • The software fee is not returned.
  • The order stays FULFILLED and keeps counting toward your monthly caps.
  • The order needs exactly one settled payment, made with Venmo, Cash App, PayPal, Zelle, Revolut, Wise or Monzo, settled to USDC on Base, in a supported currency (EUR, GBP and USD included), with no chargeback recorded.

Disputes​

Venmo and PayPal are the only platforms whose payments can be disputed after settlement. A successful dispute is paid from your stake; on every other platform a customer who wants money back goes through your refund.

Peer does not run an evidence portal, because the dispute is decided on the platform. Within 24 hours of notice you are expected to acknowledge it, name a contact, say who will refund if anyone, and produce order details, communications and proof of fulfillment, so keep those records for every order for at least 24 months.

What a chargeback does to order state, and how it reaches your server, is in chargebacks.

Integration facts at a glance​

QuestionAnswer
Which event releases goodsORDER_FULFILLED, or data.order.status equal to FULFILLED. PAYMENT_SETTLED carries the same order and payment snapshot and fires for every settled payment, including a partial one. The two can arrive in either order. See order status.
Signature headerX-Webhook-Signature: HMAC-SHA256 in lowercase hex, no prefix, over timestamp + "." + raw body, with the timestamp from X-Webhook-Timestamp. No other signature header is sent. See verification.
Idempotent order creationSend idempotencyKey in the body of POST /api/v1/orders, 8 to 128 characters of letters, digits, underscore and hyphen. A replay returns the original order; a replay with a different amount or mode returns 409 IDEMPOTENCY_KEY_CONFLICT. The SDK forwards the key from 5.0.0. Replays return no token; the SDK returns checkoutUrl: null. Save the original checkout URL.
Webhook retries7 attempts over about 35 hours. There is no manual redelivery; after an outage, read the order back through the Orders API. See the retry policy.
Order amount limitsAt least the platform minimum (10 USDC by default) and at most 10,000 USDC per order, the protocol's per-request limit, checked in USDC after any fiat conversion and in sandbox too. Above the maximum, creation returns 400 AMOUNT_ABOVE_MAX; split a larger purchase into several orders. Each bank or app payment must also settle at most 10,000 USDC including buyer-paid fees, so a PAYEE order at 1.5% fees can be paid that way up to about 9,850 USDC; above it those methods show as unavailable and a payment start returns 400 INTENT_ABOVE_MAX. See order amount limits.
Order validityOrders never expire. A fiat payment attempt has a 1 hour window, and a payment that lands after it still settles and fires PAYMENT_SETTLED. See the payment window.
Sandbox to liveSandbox and live are paired but separate workspaces, with separate API keys, webhook registrations and signing secrets. Register your live endpoint with the live key. Keys carry no prefix; GET /api/v1/integration/status reports which environment a key belongs to. See create a webhook.
Checkout languageEnglish. The checkout quotes in the customer's currency, picked automatically or pinned with Default currency under Settings, Payments. Your business name and logo appear on it.
Customer emailsPeer does not send your customer order confirmations or receipts. The only email Peer may send is a notification that support replied, to an address the customer gave in the checkout support chat. Send your own confirmation from your ORDER_FULFILLED handler.
Customer dataWhat Peer collects and how to exercise data rights is in the privacy policy. For anything else your privacy notice needs, email sales@peer.xyz.

Back to the advanced merchant guide, or the webhooks docs.