Server-Side: Create a Session
Create payment sessions from your backend using your API key. This returns a session ID and token that the client uses to open the payment modal.
// app/api/payment-sessions/route.ts (Next.js App Router)
import { NextResponse } from "next/server";
export async function POST(request: Request) {
const { amount, currency, requestId } = await request.json();
const response = await fetch(`${process.env.CUBEPAY_API_HOST}/payment-sessions`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${process.env.CUBEPAY_API_KEY}`,
},
body: JSON.stringify({
amount: String(amount),
currency: currency || "USD",
requestId,
}),
});
const session = await response.json();
return NextResponse.json({
paymentSessionId: session.paymentSessionId,
paymentSessionToken: session.paymentSessionToken,
});
}
Request Parameters
| Parameter | Type | Required | Description |
|---|
amount | string | Yes | Payment amount as a decimal string (e.g., "50.00") |
currency | string | Yes | Currency code (e.g., "USD") |
requestId | string | No | Idempotency key — pass your own UUID to prevent duplicate sessions |
Response
{
"paymentSessionId": "ps_abc123def456",
"paymentSessionToken": "eyJhbGciOiJIUzI1NiIs...",
"amount": "50.00",
"currency": "USD",
"network": "SEPOLIA",
"tokenSymbol": "USDC",
"oneTimeWalletAddress": "0x1234...abcd",
"status": "PENDING",
"createdAt": "2026-03-20T12:00:00Z"
}
The paymentSessionToken is a short-lived credential scoped to this session. Pass it to the client, but never log or store it permanently.
Client-Side: Launch the Payment Modal
Pass the session credentials to the SDK service to open the payment modal.
import { cubePayService } from "@/services/cubepay-sdk";
async function handlePayment(amount: number) {
try {
const result = await cubePayService.executePayment({
amount,
currency: "USD",
});
// Payment succeeded
console.log("Transaction hash:", result.transactionHash);
console.log("Session:", result.session);
} catch (error) {
// Payment failed or was cancelled
console.error("Payment error:", error);
}
}
What executePayment Does
The executePayment method handles the full payment lifecycle:
Creates the session
Calls your server’s POST /api/payment-sessions endpoint with the amount and currency.
Initializes the SDK
Loads the SDK bundle (if not already loaded) and initializes it with your merchant configuration.
Opens the modal
Calls sdk.open() with the session ID and token. The customer sees the payment modal with wallet options.
Returns the result
On success, returns the transaction hash and session details. On cancellation, throws a CubePayClosedError.
Using in a React Component
"use client";
import { useState } from "react";
import { cubePayService } from "@/services/cubepay-sdk";
export function PayButton({ amount }: { amount: number }) {
const [loading, setLoading] = useState(false);
const handleClick = async () => {
setLoading(true);
try {
const result = await cubePayService.executePayment({
amount,
currency: "USD",
});
// Redirect to success page or update UI
window.location.href = `/success?tx=${result.transactionHash}`;
} catch (error) {
if (error.name === "CubePayClosedError") {
// User closed the modal — not an error
console.log("Payment cancelled by user");
} else {
console.error("Payment failed:", error.message);
}
} finally {
setLoading(false);
}
};
return (
<button onClick={handleClick} disabled={loading}>
{loading ? "Processing..." : `Pay $${amount.toFixed(2)}`}
</button>
);
}
The SDK modal supports both mobile (drawer) and desktop (dialog) layouts automatically based on viewport size.
Next Steps
Learn how to Handle Payment Completion and confirm payments via webhooks.