Dynamic Orders
Dynamic Orders recover a checkout when no liquidity covers the exact order amount. The checkout shows the customer specific nearby amounts that are available right now. If the customer picks one, the order is updated, payment options reload for the new amount, and you receive an ORDER_RESIZED webhook. Dynamic Orders are sometimes called dynamic quotes.
Enable Dynamic Orders
Dynamic Orders are disabled by default. A merchant owner or manager can enable them in the Merchant Dashboard:
- Open Settings → Payments and expand Advanced.
- Turn on Resizable orders.
- Select Save in the bar at the bottom of the page.
The setting becomes the default for new orders. It does not change orders that already exist.
If your account contains multiple merchant profiles, select each profile and enable the setting separately.
Create an order
The recommended integration is to omit dynamicOrdersEnabled when calling createCheckout. New orders then inherit the merchant setting:
import { createCheckout } from '@zkp2p/pay-sdk';
const checkout = await createCheckout(
{
requestedFiatAmount: '100.00',
requestedFiatCurrency: 'USD',
destinationChainId: 8453,
destinationToken: 'USDC',
},
{
apiBaseUrl: 'https://api.pay.peer.xyz',
checkoutBaseUrl: 'https://pay.peer.xyz',
apiKey: process.env.ZKPAY_API_KEY!,
},
);
The optional field is a per-order override:
| Value | Behavior |
|---|---|
| Omitted | Inherits the merchant's Dynamic Orders setting. |
false | Disables Dynamic Orders for this order. |
true | Enables the feature only when it is already enabled for the merchant. If the merchant setting is off, order creation returns 400 DYNAMIC_ORDERS_DISABLED. |
The resolved value is saved on the order at creation time. Changing the merchant setting later does not alter that order.
Customer experience
When no supported fiat payment method can cover the original amount, checkout can display Pay less and Pay more options. Each option is a specific amount backed by a live quote; it is not a continuous range.
After the customer selects an amount, Peer Pay:
- Confirms the order is still eligible to change.
- Updates its requested and remaining USDC amounts.
- Reloads payment methods for the selected amount.
- Emits an
ORDER_RESIZEDwebhook.
You receive the amount on the resized order, not the amount originally submitted to createCheckout.
Handle resized orders
Your webhook handler should treat the amounts in data.order and data.resize as authoritative:
{
"type": "ORDER_RESIZED",
"data": {
"order": {
"id": "cmf5k2x9d0001abcd1234efgh",
"requestedUsdcAmount": "95.000000",
"remainingUsdcAmount": "95.000000"
},
"resize": {
"previousAmountUsdc": "100.000000",
"newAmountUsdc": "95.000000"
}
}
}
Update the corresponding cart, deposit, or account credit to the new amount. The complete payload is under ORDER_RESIZED. Verify the signature and stay idempotent as you would for any other event; see webhook verification.
When suggestions do not appear
Nearby amounts are shown only when the order can safely be resized and at least one suggestion passes the pricing and order-limit checks. They may not appear when:
- Dynamic Orders were disabled when the order was created;
- an exact fiat payment quote is still available;
- the order has a payment attempt that can still settle, or has been partially settled;
- the checkout is an in-person order;
- the payout requires conversion outside Base USDC;
- no nearby quote satisfies the merchant's enabled rails, order-size limits, or fee settings. Nearby amounts also stay within the platform minimum and the 10,000 USDC order maximum, and a bank or app payment of the suggested amount, fees included, must fit the same per-payment limit;
- a larger amount would take a Base or Pro merchant past the plan's monthly fiat volume cap. Upward resizes are checked against the cap and rejected with
403 MERCHANT_MONTHLY_VOLUME_LIMIT_EXCEEDED; downward resizes are never capped. See monthly caps.
Suggestions are specific amounts backed by live quotes, not a range, so the set can change from one moment to the next.