Skip to main content

Create a Checkout Session

Create a session on your server, then redirect the buyer to the checkout URL.

Endpoint

POST /v1/sessions
Authorization: Bearer vp_sk_live_xxx
Content-Type: application/json
Idempotency-Key: <unique-key> (optional, recommended)

Headers

HeaderRequiredDescription
AuthorizationYesBearer token (vp_sk_live_xxx or vp_sk_test_xxx)
Content-TypeYesapplication/json
Idempotency-KeyNoUnique key to prevent duplicate session creation. If you retry a request with the same key, the original session is returned instead of creating a new one. Recommended for all production integrations.

Request Body

FieldTypeRequiredDescription
amountintegerYesAmount in minor units (cents). 1499 = $14.99
currencystringYesISO 4217 currency code (USD, EUR, GBP)
countrystringNoISO 3166-1 alpha-2 country code (US, CA, GB)
successUrlstringNoHTTPS URL to redirect buyer after payment
cancelUrlstringNoHTTPS URL to redirect buyer on cancel
modestringNoPayment mode (default "payment")
descriptionstringNoPayment description for bank statements
localestringNoCheckout page language (e.g. "en", "fr")
expiresInintegerNoSession TTL in seconds (300–3600, default 1800)
buyerIdstringNoYour external customer ID (enables saved payment methods)
buyerNamestringNoBuyer's name (pre-fills billing form, encrypted at rest)
buyerEmailstringNoBuyer's email (encrypted at rest)
lineItemsarrayNoOrder items to display on checkout page
metadataobjectNoKey-value pairs passed through to webhooks

Line Item Object

FieldTypeRequiredDescription
namestringYesItem name
quantityintegerYesQuantity (1-9999)
unitAmountintegerYesUnit price in minor units
imageUrlstringNoProduct image URL

Response

{
"id": "vp_cs_live_k7x9m2n4p3",
"checkoutUrl": "https://checkout.vonpay.com/checkout?session=vp_cs_live_k7x9m2n4p3",
"expiresAt": "2026-03-31T15:30:00.000Z"
}

The POST /v1/sessions response is deliberately minimal — just the session ID, the checkout URL to redirect the buyer to, and the session expiry. Processor selection (Stripe, Adyen, etc.) happens server-side inside Von Payments and is not exposed on the merchant API. See Vora — Payment Routing for why.

Session Expiry

Sessions expire 30 minutes after creation. If the buyer hasn't completed payment by then, the session status becomes expired and the checkout page shows an error.

Amount Format

Amounts are always in minor units (the smallest currency unit):

AmountCurrencyValue
1499USD$14.99
1000EUR10.00 EUR
999GBP9.99 GBP
100000JPY100,000 JPY (JPY has no minor unit)

Example: With Line Items

curl -X POST https://checkout.vonpay.com/v1/sessions \
-H "Authorization: Bearer vp_sk_live_xxx" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order_456_attempt_1" \
-d '{
"amount": 3298,
"currency": "USD",
"country": "US",
"successUrl": "https://mystore.com/order/456/confirm",
"cancelUrl": "https://mystore.com/cart",
"description": "Order #456",
"locale": "en",
"buyerId": "cust_789",
"buyerName": "Jane Doe",
"buyerEmail": "jane@example.com",
"lineItems": [
{ "name": "Wireless Headphones", "quantity": 1, "unitAmount": 2499 },
{ "name": "USB-C Cable", "quantity": 1, "unitAmount": 799 }
],
"metadata": { "orderId": "order_456" }
}'

Example: Simple Payment (No Items)

curl -X POST https://checkout.vonpay.com/v1/sessions \
-H "Authorization: Bearer vp_sk_live_xxx" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: simple_pay_001" \
-d '{
"amount": 5000,
"currency": "USD",
"country": "US",
"successUrl": "https://mystore.com/thank-you"
}'

If no lineItems are provided, the checkout page shows the total amount without an itemized breakdown.

Validation Rules

  • amount must be a positive integer (1 to 99,999,999)
  • currency must be exactly 3 characters
  • country must be exactly 2 characters
  • successUrl and cancelUrl must be HTTPS (localhost exempt in sandbox)
  • expiresIn must be between 300 and 3600 (seconds)
  • lineItems max 100 items
  • metadata values must be strings, max 500 characters each

Errors

StatusErrorCause
400Validation error messageInvalid request body
401Invalid API keyWrong or missing Bearer token
429Too many requestsRate limited (10/min)
500Error messageServer error