Skip to content

Checkout Session API

A Checkout Session represents a fixed-price payment intent with a pre-built hosted payment page. It is ideal for one-time purchases where you know the exact amount and line items upfront.

  • Hosted checkout page — Unuspay provides a customer-facing payment UI at the checkout_url. No need to build your own payment form.
  • Fixed-price — The amount and line items are set at creation time and cannot be modified afterward.
  • Auto-expiry — Sessions expire automatically after a configurable window (30 minutes–24 hours, defaults to 24 hours).
  • Pollable status — Retrieve the current session state at any time, including linked order_id and transaction_id once payment is complete.

Use Checkout Sessions when selling digital goods, subscriptions, or any one-time purchase with a known price.

flowchart TD
M1["Merchant create session"] --> U1["Unuspay return checkout_url"]
U1 --> M2["Merchant redirect customer"]
M2 --> C1["Customer visit checkout page"]
C1 --> U2["Unuspay process payment"]
U2 --> C2["Customer redirect to success_url"]
U2 -.-> U3["Unuspay send webhook"]
U3 -.-> M3["Merchant verify session"]

Solid arrows — synchronous flow | Dashed arrows — asynchronous

Base URL: https://api.unuspay.com/api/v1

Auth: Include your API key in the Authorization header:

Authorization: Bearer YOUR_API_KEY

Creates a new checkout session and returns a checkout_url for the customer to complete payment.

Terminal window
curl -X POST https://api.unuspay.com/api/v1/checkout_session \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-1234-unique-key" \
-d '{
"wallet_set_id": "wset_xxx",
"currency": "USD",
"external_order_id": "order-1234",
"line_items": [
{
"name": "Pro Plan",
"unit_amount": "99.00",
"quantity": 1
}
],
"expires_at": "2026-04-30T00:00:00Z",
"metadata": {
"success_url": "https://your-shop.com/thank-you",
"cancel_url": "https://your-shop.com/checkout"
}
}'
FieldTypeRequiredDescription
wallet_set_idstringYesWallet set ID from dashboard SettingsWallet Sets
currencystring (3–10 chars)YesISO 4217 currency code (e.g. "USD", "EUR", "GBP"). All amounts are normalized to USD. See Non-USD Currencies
external_order_idstring (1–255 chars)YesYour internal order reference
line_itemsarray (1–100)YesItems being purchased (see line item fields below)
expires_atstring (ISO 8601)NoAbsolute expiry datetime. 30m–24h from now. Defaults to 24h
metadataobjectNoCustom key-value pairs. Reserved keys: success_url, cancel_url
FieldTypeRequiredDescription
namestring (1–255 chars)YesDisplay name
descriptionstring (up to 1000 chars)NoOptional details
unit_amountstring (decimal)YesPrice per unit (e.g. "10.00")
quantityinteger (≥1)YesQuantity
metadataobjectNoCustom key-value pairs
{
"status": "success",
"data": {
"session_id": "chs_abc123xyz",
"public_token": "chk_def456uvw",
"payment_token": "pt_ghi789rst",
"checkout_url": "https://app.unuspay.com/checkout/chk_def456uvw",
"amount_total": "99.00000000",
"currency": "USD",
"status": "open",
"expires_at": "2026-04-30T00:00:00.000Z"
}
}

When the Idempotency-Key header is present, repeat calls with the same key return the previously created session (identical response, 200). Repeat calls with the same key but different body parameters are ignored — the cached session is returned as-is.

Retrieve the current state of a session. Returns the same session object, including order_id and transaction_id once payment is complete.

Terminal window
curl -X GET https://api.unuspay.com/api/v1/checkout_session/chs_abc123xyz \
-H "Authorization: Bearer YOUR_API_KEY"
{
"status": "success",
"data": {
"session_id": "chs_abc123xyz",
"public_token": "chk_def456uvw",
"status": "complete",
"currency": "USD",
"amount_total": "99.00000000",
"external_order_id": "order-1234",
"order_id": "ord_xxx",
"transaction_id": "txn_yyy",
"line_items": [
{
"name": "Pro Plan",
"unit_amount": "99.00",
"quantity": 1,
"amount_total": "99.00000000"
}
],
"metadata": {
"success_url": "https://your-shop.com/thank-you",
"cancel_url": "https://your-shop.com/checkout"
},
"created_at": "2026-04-29T10:00:00.000Z",
"expires_at": "2026-04-30T00:00:00.000Z",
"expired_at": null
}
}
  • open — Session is active and can accept payment
  • complete — Customer completed payment successfully
  • expired — Session was manually expired or reached its expiry time
  • failed — Payment attempt failed

Manually expire an active session. Only works on sessions with status: "open". Emits a checkout.session.expired webhook event. This action is terminal — an expired session cannot be revived.

Terminal window
curl -X POST https://api.unuspay.com/api/v1/checkout_session/chs_abc123xyz/expire \
-H "Authorization: Bearer YOUR_API_KEY"
{
"status": "success",
"data": {
"session_id": "chs_abc123xyz",
"status": "expired",
"expired_at": "2026-04-29T12:00:00.000Z",
"expiry_reason": "manual"
}
}

Use metadata.success_url and metadata.cancel_url to control customer redirects after the hosted checkout page:

  • success_url — The customer is redirected here after completing payment.
  • cancel_url — The customer is redirected here if they cancel or abandon the checkout page.

Both URLs are returned in the Get Session response and included in webhook payloads.

After creating a session, the customer visits the checkout_url (format: https://app.unuspay.com/checkout/{public_token}), completes payment on the hosted checkout page, and is redirected to your success_url. The session status advances from open to complete (or failed if the payment does not succeed).

To receive real-time updates on session lifecycle events, see the Webhook Guide.

When you pass a non-USD currency (e.g. "EUR"), the system converts line item amounts to USD using real-time exchange rates from the MoneyConvert and Frankfurter APIs. The session is always stored and returned with currency: "USD". The original currency and amounts are preserved in the presentment field:

{
"currency": "USD",
"amount_total": "108.90",
"presentment": {
"currency": "EUR",
"amount_total": "99.00",
"line_items": [
{
"name": "Pro Plan",
"unit_amount": "99.00",
"quantity": 1
}
],
"fx_rate": "0.90909090",
"fx_rate_source": "moneyconvert",
"fx_rate_timestamp": "2026-04-29T10:00:00.000Z"
}
}

Note: presentment is only included when the input currency is not "USD". If the currency code is not recognized by the exchange rate provider, the API returns INVALID_CURRENCY (CONV-002). Use standard ISO 4217 fiat codes only (e.g. "EUR", "GBP", "JPY").

Error CodeTriggerRecovery
CHECKOUT_SESSION_INVALID_WALLET_SETwallet_set_id doesn’t exist or doesn’t belong to your orgVerify the ID from dashboard SettingsWallet Sets
CHECKOUT_SESSION_INVALID_EXPIRYexpires_at outside 30m–24h from nowAdjust to a valid datetime
CHECKOUT_SESSION_INVALID_AMOUNTLine item total or session total is zero/invalidCheck unit_amount and quantity values
INVALID_CURRENCY (CONV-002)Currency code not found in exchange rate providerUse a valid ISO 4217 fiat code (e.g. "EUR", "GBP", "JPY")
CHECKOUT_SESSION_NOT_FOUNDsession_id doesn’t exist or belongs to another orgDouble-check the session ID
CHECKOUT_SESSION_ALREADY_COMPLETEAttempted to expire a completed sessionSession is terminal; no action needed
CHECKOUT_SESSION_ALREADY_FAILEDAttempted to expire a failed sessionSession is terminal; no action needed
CHECKOUT_SESSION_EXPIREDAttempted to expire an already-expired sessionSession is terminal; no action needed

All errors follow this structure:

{
"status": "error",
"error": {
"code": "CHECKOUT_SESSION_INVALID_WALLET_SET",
"message": "Wallet set not found or does not belong to this organization"
}
}