createCheckoutSession
Creates a new checkout session for a payment.
Signature
function createCheckoutSession(
params: CreateSessionRequest,
opts: CheckoutClientOptions
): Promise<CreateSessionResponse>
Parameters
params: CreateSessionRequest
The SDK supports two checkout modes: exact-token (default) and exact-fiat.
Exact-Token Mode (Default)
Specify the exact USDC amount the merchant should receive. The customer pays whatever fiat amount is needed to cover this.
| Property | Type | Required | Description |
|---|---|---|---|
merchantId | string | Yes | Your merchant ID |
amountUsdc | string | Yes | Amount in USDC (e.g., "50.00") |
destinationChainId | number | Yes | Target chain ID (see Supported Chains) |
destinationToken | string | Yes | Token address (USDC on target chain) |
recipientAddress | string | Yes | Wallet to receive funds |
successUrl | string | No | Redirect URL after successful payment |
cancelUrl | string | No | Redirect URL if user cancels |
metadata | Record<string, string> | No | Custom key-value pairs (passed to webhooks) |
enabledPaymentPlatforms | PaymentPlatformType[] | No | Restrict available payment platforms |
checkoutMode | 'exact-token' | No | Defaults to 'exact-token' |
Exact-Fiat Mode
Specify the exact fiat amount the customer should pay. The merchant receives whatever USDC amount results after fees.
| Property | Type | Required | Description |
|---|---|---|---|
merchantId | string | Yes | Your merchant ID |
checkoutMode | 'exact-fiat' | Yes | Must be 'exact-fiat' |
fiatAmount | string | Yes | Fiat amount to charge (e.g., "100.00") |
fiatCurrency | string | Yes | Currency code (e.g., "USD") |
maxFeePercentage | number | No | Maximum acceptable fee percentage |
destinationChainId | number | Yes | Target chain ID |
destinationToken | string | Yes | Token address (USDC on target chain) |
recipientAddress | string | Yes | Wallet to receive funds |
successUrl | string | No | Redirect URL after successful payment |
cancelUrl | string | No | Redirect URL if user cancels |
metadata | Record<string, string> | No | Custom key-value pairs |
enabledPaymentPlatforms | PaymentPlatformType[] | No | Restrict available payment platforms |
opts: CheckoutClientOptions
| Property | Type | Required | Description |
|---|---|---|---|
apiBaseUrl | string | Yes | API server URL |
apiKey | string | Yes | Your merchant API key |
checkoutBaseUrl | string | No | Checkout UI URL (defaults to apiBaseUrl) |
fetcher | typeof fetch | No | Custom fetch implementation |
Returns
interface CreateSessionResponse {
session: CheckoutSession;
sessionToken: string; // Required for checkout URL
checkoutUrl: string; // Pre-built checkout URL with token
bridge?: BridgeInfo; // Present for cross-chain payments
}
interface BridgeInfo {
required: boolean;
inputAmount?: string; // Amount on Base (includes fees)
outputAmount?: string; // Expected output after bridge
feeAmount?: string; // Bridge fee
minOutputAmount?: string;
estimatedTimeSeconds?: number;
}
The response includes:
- session: Full session object with all details
- sessionToken: One-time token required to access the checkout URL
- checkoutUrl: Ready-to-use URL with session ID and token
- bridge: Bridge details if payment requires cross-chain delivery
The sessionToken is only returned when the session is created. Store it if you need to construct checkout URLs later.
Supported Chains
Payments can be delivered to multiple chains:
| Chain ID | Chain Name | Type |
|---|---|---|
| 8453 | Base | EVM (Origin) |
| 1 | Ethereum | EVM |
| 10 | Optimism | EVM |
| 42161 | Arbitrum | EVM |
| 137 | Polygon | EVM |
| 324 | zkSync Era | EVM |
| 59144 | Linea | EVM |
| 534352 | Scroll | EVM |
| 999 | HyperEVM | EVM |
| 34268394551451 | Solana | Non-EVM |
Payments on chains other than Base require bridging via Across Protocol. The bridge field in the response will contain details about fees and estimated time.
Recipient Address and Defaults
The recipientAddress parameter specifies where funds should be delivered. When omitted, the SDK uses your merchant's default wallet address based on the destination chain:
- EVM chains (Base, Ethereum, Arbitrum, etc.): Uses your Privy EVM wallet address (
0x...) - Solana: Uses your Privy Solana wallet address (base58 format)
These wallet addresses are automatically created when you first log into the merchant dashboard. You can view them in Settings → Wallets.
Address Formats
| Chain Type | Format | Example |
|---|---|---|
| EVM | Hex (0x prefix) | 0x742d35Cc6634C0532925a3b844Bc9e7595f8fE71 |
| Solana | Base58 | 7K6...<base58 address> |
Override Default Address
You can always specify a custom recipientAddress to override the default:
const response = await createCheckoutSession(
{
merchantId: 'merchant_abc123',
amountUsdc: '100.00',
destinationChainId: 34268394551451, // Solana
destinationToken: 'USDC',
recipientAddress: 'YourCustomSolanaAddress...', // Override default
},
opts
);
If you haven't logged into the merchant dashboard, or your destination chain type doesn't have a default wallet, you must provide recipientAddress explicitly.
Examples
Basic Checkout (Exact-Token)
import { createCheckoutSession } from '@zkp2p-pay/sdk';
const response = await createCheckoutSession(
{
merchantId: 'merchant_abc123',
amountUsdc: '99.99',
destinationChainId: 8453,
destinationToken: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
recipientAddress: '0x742d35Cc6634C0532925a3b844Bc9e7595f8fE71',
successUrl: 'https://mystore.com/order/success',
cancelUrl: 'https://mystore.com/cart',
metadata: {
orderId: 'order_12345',
customerId: 'cust_67890',
},
},
{
apiBaseUrl: 'https://api.pay.zkp2p.xyz',
apiKey: process.env.ZKPAY_API_KEY!,
}
);
console.log('Session ID:', response.session.id);
console.log('Session Token:', response.sessionToken);
console.log('Checkout URL:', response.checkoutUrl);
Fixed Fiat Price (Exact-Fiat)
Useful when you want the customer to pay an exact fiat amount (e.g., "$100"):
const response = await createCheckoutSession(
{
merchantId: 'merchant_abc123',
checkoutMode: 'exact-fiat',
fiatAmount: '100.00',
fiatCurrency: 'USD',
maxFeePercentage: 2.0, // Accept up to 2% fee
destinationChainId: 8453,
destinationToken: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
recipientAddress: '0x742d35Cc6634C0532925a3b844Bc9e7595f8fE71',
successUrl: 'https://mystore.com/order/success',
},
{
apiBaseUrl: 'https://api.pay.zkp2p.xyz',
apiKey: process.env.ZKPAY_API_KEY!,
}
);
Restrict Payment Platforms
Only allow specific payment platforms:
const response = await createCheckoutSession(
{
merchantId: 'merchant_abc123',
amountUsdc: '50.00',
destinationChainId: 8453,
destinationToken: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
recipientAddress: '0x742d35Cc6634C0532925a3b844Bc9e7595f8fE71',
enabledPaymentPlatforms: ['venmo', 'cashapp'], // Only US platforms
},
{
apiBaseUrl: 'https://api.pay.zkp2p.xyz',
apiKey: process.env.ZKPAY_API_KEY!,
}
);
Cross-Chain Payment (Arbitrum)
const response = await createCheckoutSession(
{
merchantId: 'merchant_abc123',
amountUsdc: '100.00',
destinationChainId: 42161, // Arbitrum
destinationToken: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831', // USDC on Arbitrum
recipientAddress: '0x742d35Cc6634C0532925a3b844Bc9e7595f8fE71',
},
{
apiBaseUrl: 'https://api.pay.zkp2p.xyz',
apiKey: process.env.ZKPAY_API_KEY!,
}
);
if (response.bridge?.required) {
console.log('Bridge fee:', response.bridge.feeAmount);
console.log('Estimated time:', response.bridge.estimatedTimeSeconds, 'seconds');
}
Error Handling
The function throws an error if:
- The API key is missing or invalid
- The request parameters are invalid
- The API request fails
- Fee exceeds
maxFeePercentage(for exact-fiat mode)
try {
const response = await createCheckoutSession(params, opts);
} catch (error) {
console.error('Failed to create session:', error.message);
}
Notes
- The
amountUsdcshould be a decimal string (e.g.,"50.00", not50) - The
metadataobject is limited to string values - Session IDs are unique and can be used to track the payment
- Sessions expire after 1 hour by default
- The
sessionTokenis only available at creation time