Skip to main content

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

ParameterTypeRequiredDescription
amountstringYesPayment amount as a decimal string (e.g., "50.00")
currencystringYesCurrency code (e.g., "USD")
requestIdstringNoIdempotency 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:
1

Creates the session

Calls your server’s POST /api/payment-sessions endpoint with the amount and currency.
2

Initializes the SDK

Loads the SDK bundle (if not already loaded) and initializes it with your merchant configuration.
3

Opens the modal

Calls sdk.open() with the session ID and token. The customer sees the payment modal with wallet options.
4

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.