Skip to main content
Create a one-time purchase order from an existing checkout session and return a hosted PSP payment URL.
POST /v1/actions/onetime-order/create-order
Authentication: Session Token — see Customer Endpoints (customer or shopper role)

Checkout Flow

  1. The merchant first calls Create Checkout Session to lock product version, pricing, and currency, and receives a sessionId
  2. The buyer is sent to the hosted checkout page (or your own page if you handle the UI), where they confirm billing details
  3. This endpoint is called to finalize the order — the server snapshots the price, calculates tax against billingDetail, writes the order, and creates the PSP checkout
  4. The buyer is redirected to the returned checkoutUrl to complete payment
  • Price snapshot: the price is frozen at order creation time; later product price changes do not affect this order
  • Tax calculation: tax is computed from billingDetail (country, state for US/CA, business + VAT for EU)
  • PSP fault tolerance: if the PSP call fails, the order is rolled back so you can safely retry
  • Email normalization: buyerEmail is server-normalized with trim().toLowerCase() before tax calculation, order storage, session writeback, and PSP calls — Foo@Bar.COM and foo@bar.com are treated as the same buyer

Request Body

FieldTypeRequiredDescription
checkoutSessionIdstringYesCheckout session ID returned by Create Checkout Session
billingDetailobjectConditionalBuyer billing detail (see below). Required unless already pre-filled on the session
buyerEmailstringConditionalBuyer email. Required unless already pre-filled on the session; ignored when the session token carries a buyer identity
buyerIpstringNoBuyer IP address (used to refine tax calculation)
successUrlstringNoOverride the success redirect URL configured on the session
storeId, productId, and currency are already locked on the checkout session — passing them in the body is ignored.

Billing Detail Object

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

Example Request

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

const client = new WaffoPancake({
  sessionToken: window.WAFFO_SESSION_TOKEN, // injected by the merchant's portal
  environment: "prod",
});

const result = await client.orders.createOnetime({
  checkoutSessionId: "cs_550e8400-e29b-41d4-a716-446655440000",
  buyerEmail: "customer@example.com",
  billingDetail: {
    country: "US",
    isBusiness: false,
    state: "CA",
  },
  successUrl: "https://example.com/thank-you",
});

console.log(result.checkoutUrl); // "https://checkout.stripe.com/c/pay/cs_xxx"

Success Response (200)

{
  "data": {
    "checkoutUrl": "https://checkout.stripe.com/c/pay/cs_xxx"
  }
}

Response Fields

FieldTypeDescription
checkoutUrlstringHosted PSP payment URL — redirect the buyer here to complete payment

Errors

Retry policy: Never retry 4xx — fix the request and resubmit. Retry 5xx with exponential backoff (start 5s, max 3 attempts).
Statuserrors[0].messageWhat it meansRecommended handling
400Invalid JSON bodyRequest body is not valid JSONFix the body, resubmit
400Missing required field: checkoutSessionIdcheckoutSessionId was not providedFix the body, resubmit
400Session product type mismatch: expected onetimeThe session was created for a subscription productCreate a new one-time session and retry
400Environment mismatch between request and sessionX-Environment differs from the session’s environmentUse the matching environment, resubmit
400Missing billingDetail: provide in request body or pre-fill in checkout sessionNeither the request nor the session carries billingDetailProvide billingDetail, resubmit
400State is required for US/CAbillingDetail validation failedFix billingDetail, resubmit
400Missing buyerEmail: provide in request body or pre-fill in checkout sessionNeither the request nor the session carries a buyer emailProvide buyerEmail, resubmit
401Authentication failedSession token invalid, expired, or malformedRe-mint the session token via Issue Session Token
403Session does not belong to this storeThe session was created for a different storeUse a session belonging to the caller’s store
409Checkout session invalid, please re-enter checkoutSession does not exist or has expiredCreate a new checkout session and restart the flow
500Internal server errorUnexpected server-side failureRetry with exponential backoff (start 5s, max 3 attempts)