Checkout Session API
Overview
Section titled “Overview”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_idandtransaction_idonce payment is complete.
Use Checkout Sessions when selling digital goods, subscriptions, or any one-time purchase with a known price.
How It Works
Section titled “How It Works”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_KEYStep 1: Create Session
Section titled “Step 1: Create Session”Creates a new checkout session and returns a checkout_url for the customer to complete payment.
Request
Section titled “Request”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" } }'Request Fields
Section titled “Request Fields”| Field | Type | Required | Description |
|---|---|---|---|
wallet_set_id | string | Yes | Wallet set ID from dashboard Settings → Wallet Sets |
currency | string (3–10 chars) | Yes | ISO 4217 currency code (e.g. "USD", "EUR", "GBP"). All amounts are normalized to USD. See Non-USD Currencies |
external_order_id | string (1–255 chars) | Yes | Your internal order reference |
line_items | array (1–100) | Yes | Items being purchased (see line item fields below) |
expires_at | string (ISO 8601) | No | Absolute expiry datetime. 30m–24h from now. Defaults to 24h |
metadata | object | No | Custom key-value pairs. Reserved keys: success_url, cancel_url |
Line Item Fields
Section titled “Line Item Fields”| Field | Type | Required | Description |
|---|---|---|---|
name | string (1–255 chars) | Yes | Display name |
description | string (up to 1000 chars) | No | Optional details |
unit_amount | string (decimal) | Yes | Price per unit (e.g. "10.00") |
quantity | integer (≥1) | Yes | Quantity |
metadata | object | No | Custom key-value pairs |
Response (200)
Section titled “Response (200)”{ "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" }}Idempotency
Section titled “Idempotency”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.
Step 2: Get Session
Section titled “Step 2: Get Session”Retrieve the current state of a session. Returns the same session object, including order_id and transaction_id once payment is complete.
Request
Section titled “Request”curl -X GET https://api.unuspay.com/api/v1/checkout_session/chs_abc123xyz \ -H "Authorization: Bearer YOUR_API_KEY"Response (200)
Section titled “Response (200)”{ "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 }}Status Values
Section titled “Status Values”open— Session is active and can accept paymentcomplete— Customer completed payment successfullyexpired— Session was manually expired or reached its expiry timefailed— Payment attempt failed
Step 3: Expire Session
Section titled “Step 3: Expire Session”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.
Request
Section titled “Request”curl -X POST https://api.unuspay.com/api/v1/checkout_session/chs_abc123xyz/expire \ -H "Authorization: Bearer YOUR_API_KEY"Response (200)
Section titled “Response (200)”{ "status": "success", "data": { "session_id": "chs_abc123xyz", "status": "expired", "expired_at": "2026-04-29T12:00:00.000Z", "expiry_reason": "manual" }}Metadata
Section titled “Metadata”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.
What Happens Next
Section titled “What Happens Next”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.
Non-USD Currencies
Section titled “Non-USD Currencies”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:
presentmentis only included when the input currency is not"USD". If the currency code is not recognized by the exchange rate provider, the API returnsINVALID_CURRENCY(CONV-002). Use standard ISO 4217 fiat codes only (e.g."EUR","GBP","JPY").
Error Handling
Section titled “Error Handling”| Error Code | Trigger | Recovery |
|---|---|---|
CHECKOUT_SESSION_INVALID_WALLET_SET | wallet_set_id doesn’t exist or doesn’t belong to your org | Verify the ID from dashboard Settings → Wallet Sets |
CHECKOUT_SESSION_INVALID_EXPIRY | expires_at outside 30m–24h from now | Adjust to a valid datetime |
CHECKOUT_SESSION_INVALID_AMOUNT | Line item total or session total is zero/invalid | Check unit_amount and quantity values |
INVALID_CURRENCY (CONV-002) | Currency code not found in exchange rate provider | Use a valid ISO 4217 fiat code (e.g. "EUR", "GBP", "JPY") |
CHECKOUT_SESSION_NOT_FOUND | session_id doesn’t exist or belongs to another org | Double-check the session ID |
CHECKOUT_SESSION_ALREADY_COMPLETE | Attempted to expire a completed session | Session is terminal; no action needed |
CHECKOUT_SESSION_ALREADY_FAILED | Attempted to expire a failed session | Session is terminal; no action needed |
CHECKOUT_SESSION_EXPIRED | Attempted to expire an already-expired session | Session is terminal; no action needed |
Error Response Envelope
Section titled “Error Response Envelope”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" }}