Checkout sessions
A checkout session is the one-shot payment object: a buyer wants to pay amount for description, here's a hosted URL, redirect them to it, listen for the webhook. It's the cleanest way to take money for a single thing in Storlaunch and the underlying engine the public buy-now/cart-checkout endpoints sit on top of.
Storlaunch's checkout-sessions resource has two operating modes:
- Legacy mode — workspaces without the Plugipay module run on Storlaunch's own
CheckoutSessiontable, with adapters for Xendit and PayPal wired up locally. - Plugipay mode — workspaces with the module enabled proxy create/retrieve through to Plugipay, and the buyer is hosted at
pay.plugipay.com.
Both modes return identical wire shapes; the only visible diff is hostedUrl.
All authenticated endpoints require an sk_* key. The :id/public, :id/pay, and :id/pixel-cookies routes are unauthenticated — they're hit by the buyer's browser on the hosted checkout page.
Endpoints
Merchant (authenticated)
| Method | Path | Purpose |
|---|---|---|
POST |
/v1/payment/checkout-sessions |
Create a session |
GET |
/v1/payment/checkout-sessions |
List sessions |
GET |
/v1/payment/checkout-sessions/:id |
Retrieve a session |
POST |
/v1/payment/checkout-sessions/:id/refund |
Refund a completed session |
POST |
/v1/payment/checkout-sessions/:id/confirm |
Confirm a manual-payment session |
Buyer (unauthenticated)
| Method | Path | Purpose |
|---|---|---|
GET |
/v1/payment/checkout-sessions/:id/public |
Buyer-side read for the hosted checkout page |
POST |
/v1/payment/checkout-sessions/:id/pay |
Submit payment-method choice from the hosted page |
POST |
/v1/payment/checkout-sessions/:id/pixel-cookies |
Persist Meta _fbp / _fbc cookies onto the session |
Create
POST /v1/payment/checkout-sessions
Idempotency-Key supported but optional. Same key with a different body returns 409 IDEMPOTENCY_KEY_REUSED.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
amount |
integer | yes | Smallest-unit total. |
currency |
string (3) | yes | ISO 4217. |
description |
string | yes | Shown to the buyer on the hosted page and in their receipt. |
customerEmail |
string | yes | Used for the receipt and (for digital products) the delivery URL. |
paymentMethods |
array of strings | no | Whitelist the methods shown. Subset of qris, va, card, ewallet, paypal. Empty means "all available". |
paymentMethod |
string | no | Force one method. Skips the picker. |
productId |
string | conditional | Required if this session is fulfilling a product purchase. Drives the post-pay delivery flow. |
variantId / quantity |
string / integer | no | If a variant/quantity applies. |
successUrl / cancelUrl |
string | no | Buyer redirects after pay-or-cancel. |
expiresAt |
ISO 8601 string | no | Auto-expire time. Defaults to +24 hours. |
metadata |
object | no | Free-form. Surfaced in webhooks. |
Response — 201 Created
{
"data": {
"id": "cs_01HX...",
"accountId": "acc_01HX...",
"status": "open",
"amount": 75000,
"currency": "IDR",
"description": "Field Notes Notebook",
"customerEmail": "alice@example.com",
"paymentMethods": ["qris","va","card"],
"paymentMethod": null,
"hostedUrl": "https://storlaunch.forjio.com/checkout/cs_01HX...",
"expiresAt": "2026-05-14T10:42:00Z",
"createdAt": "2026-05-13T10:42:00Z",
"metadata": { "productId": "prod_01HX..." }
},
"error": null,
"meta": { "requestId": "req_01HX...", "timestamp": "2026-05-13T10:42:00Z" }
}
In Plugipay mode, hostedUrl points at pay.plugipay.com/c/cs_….
Retrieve
GET /v1/payment/checkout-sessions/:id
Returns the session. Use this to poll status, but prefer webhooks — you'll spend less and pay less attention.
List
GET /v1/payment/checkout-sessions?limit=50&cursor=…&status=…
Cursor-paginated. Status filter: open, pending_review, completed, expired, failed.
Refund
POST /v1/payment/checkout-sessions/:id/refund
Fully or partially refund a completed session. The actual refund mechanics depend on the rail (QRIS refunds can take days; card auths refund instantly to the issuer). Refunds emit refund.created and (when the rail settles) refund.succeeded on the Plugipay side — subscribe there if you need that lifecycle, not here.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
amount |
integer | no | Smallest-unit. Defaults to the full session amount. |
reason |
string | no | Free text. Surfaced on the receipt. |
Confirm (manual session)
POST /v1/payment/checkout-sessions/:id/confirm
For sessions paid by manual bank transfer that are sitting in pending_review. The merchant has seen the transfer land; this call flips the session to completed, runs fulfilment, fires checkout.completed with metadata.source = "manual_confirm".
Buyer endpoints
These power the buyer-facing hosted checkout page:
GET /:id/public— lightweight read with only buyer-safe fields (no account secrets, no full metadata).POST /:id/pay— called when the buyer picks a payment method on the hosted page. Server-side creates the underlying provider invoice (Xendit or PayPal in legacy mode; Plugipay handles it transparently in Plugipay mode) and returns the redirect URL.POST /:id/pixel-cookies— buyer's browser stashes_fbp/_fbccookies so server-side Meta CAPI can fire the post-payPurchaseevent with deduplication intact.
These are called by Storlaunch's own checkout UI; you usually don't call them directly.
The session object
| Field | Type | Nullable | Description |
|---|---|---|---|
id |
string | no | cs_ + 26-char ULID. |
accountId |
string | no | Workspace. |
status |
enum | no | open / pending_review / completed / expired / failed. |
amount |
integer | no | Smallest-unit total. |
currency |
string | no | ISO 4217. |
description |
string | no | Buyer-visible. |
customerEmail |
string | no | For receipt + delivery. |
customerId |
string | yes | Linked customer (if known at create or upgraded later). |
paymentMethods |
array | no | Allowed methods. |
paymentMethod |
string | yes | Actual method used. null until paid. |
hostedUrl |
string | no | Where to redirect the buyer. |
successUrl / cancelUrl |
string | yes | Post-pay redirects. |
expiresAt |
string (ISO 8601 UTC) | no | When open transitions to expired. |
completedAt |
string (ISO 8601 UTC) | yes | When the session settled. |
metadata |
object | no | Free-form. |
createdAt |
string (ISO 8601 UTC) | no | Creation time. |
Events
| Event type | Fires on | Notes |
|---|---|---|
checkout.completed |
Session transitions to completed. |
The canonical "money's in, fulfil this" event. See checkout.completed. |
product.purchased |
Per delivery created post-checkout. | Storlaunch-specific event with productId, deliveryId, licenseKey. See product.purchased. |
checkout.expired, checkout.refunded, and payment.succeeded exist as concepts but are not emitted from Storlaunch's outbox — in Plugipay mode you can subscribe to the corresponding Plugipay events directly.
Next
checkout.completed— the event you actually wait for.product.purchased— the fulfilment-side event.- Deliveries — what gets created post-payment.
- Webhook endpoints — where you wire the listener.