Skip to main content
Create a checkout session that locks product version, pricing, and currency. This is the first step in the checkout flow for both one-time and subscription products. The typical flow is:
  1. Merchant creates a checkout session (server-side)
  2. Returns checkoutUrl to the frontend
  3. Buyer clicks the link and lands on the hosted checkout page
  4. Buyer fills in billing details, previews tax, and completes the order
POST /v1/actions/checkout/create-session
Authentication: API Key or Store Slug

Request Body (API Key)

FieldTypeRequiredDescription
storeIdstringYesStore ID in Short ID format (STO_xxx)
productIdstringYesProduct ID in Short ID format (PROD_xxx)
productTypestringYesonetime or subscription
currencystringYesISO 4217 currency code (e.g. USD, EUR, JPY)
priceSnapshotobjectNoOverride pricing at session creation (API Key only)
withTrialbooleanNoEnable trial period (subscription products only)
buyerEmailstringNoPre-fill buyer’s email on the checkout page
billingDetailobjectNoPre-fill billing details (see below)
successUrlstringNoOverride redirect URL after successful payment
expiresInSecondsnumberNoSession TTL in seconds (default: 2700 = 45 minutes, API Key only)
darkModebooleanNoEnable dark mode for the checkout page
metadataobjectNoCustom key-value pairs attached to the session

Request Body (Store Slug)

FieldTypeRequiredDescription
productIdstringYesProduct ID in Short ID format (PROD_xxx)
productTypestringYesonetime or subscription
currencystringYesISO 4217 currency code
withTrialbooleanNoEnable trial period (subscription products only)
buyerEmailstringNoPre-fill buyer’s email
billingDetailobjectNoPre-fill billing details (see below)
successUrlstringNoOverride redirect URL after successful payment
darkModebooleanNoEnable dark mode for the checkout page
metadataobjectNoCustom key-value pairs attached to the session
Store Slug authentication does not support priceSnapshot or expiresInSeconds to prevent price tampering and session manipulation from the client side.

Billing Detail Object

FieldTypeRequiredDescription
countrystringYesISO 3166-1 alpha-2 country code (e.g. US, JP, DE)
isBusinessbooleanYesWhether this is a business purchase
postcodestringNoPostal or ZIP code
statestringConditionalRequired for US and CA (e.g. CA, NY, ON)
businessNamestringConditionalRequired when isBusiness is true
taxIdstringConditionalRequired for EU countries when isBusiness is true (VAT number)

Session Locks

When a checkout session is created, the following values are locked and cannot change during the session lifetime: productVersionId, productName, priceInfo, storeName, billingPeriod, withTrial, theme, buyerEmail, billingDetail

Example Request

import { WaffoPancake, CheckoutSessionProductType } from "@waffo/pancake-ts";

const client = new WaffoPancake({
  merchantId: process.env.WAFFO_MERCHANT_ID!,
  privateKey: process.env.WAFFO_PRIVATE_KEY!,
});

const session = await client.checkout.createSession({
  storeId: "STO_2D5F8G3H1K4M6N9P",
  productId: "PROD_7J3K5L8M2N4P6Q9R",
  productType: CheckoutSessionProductType.Onetime,
  currency: "USD",
  buyerEmail: "customer@example.com",
  successUrl: "https://example.com/thank-you",
});

console.log(session.sessionId);   // "cs_550e8400-e29b-41d4-a716-446655440000"
console.log(session.checkoutUrl); // "https://checkout.waffo.ai/..."
console.log(session.expiresAt);   // "2026-01-22T10:30:00.000Z"

Success Response

{
  "data": {
    "sessionId": "cs_550e8400-e29b-41d4-a716-446655440000",
    "checkoutUrl": "https://checkout.waffo.ai/my-store-abc123/checkout/cs_550e8400-e29b-41d4-a716-446655440000",
    "expiresAt": "2026-01-22T10:30:00.000Z"
  }
}

Response Fields

FieldTypeDescription
sessionIdstringCheckout session ID (cs_ + UUID format, not a Short ID)
checkoutUrlstringFull URL to redirect the buyer to the hosted checkout page
expiresAtstringISO 8601 timestamp when the session expires

Errors

StatusMessageDescription
400Missing required fieldsproductId, productType, or currency is missing
400Invalid productTypeMust be onetime or subscription
400Invalid billingDetailBilling detail validation failed (e.g. missing state for US)
401UnauthorizedInvalid API Key signature or Store Slug
403Store not activeThe store is not in active status
403Store not production enabledStore cannot process live payments
403Product not in storeThe product does not belong to the specified store
404Store not foundNo store matches the given storeId or slug
404Product not foundNo product matches the given productId
The default session TTL is 45 minutes (2700 seconds). When using API Key auth, you can customize this with expiresInSeconds. Sessions lock the product version and pricing at creation time, so price changes will not affect existing sessions.