Checkout sessions
A checkout session is a short-lived URL on `pay.cimplify.io` that hosts the full checkout for a specific cart. You create one server-side with your secret key, redirect the customer to the URL, and listen for the resulting webhook.
Endpoints
| Method | Path | Auth |
|---|---|---|
POST | /v1/checkout/sessions | Secret key (Bearer) |
GET | /v1/checkout/sessions/{session_id} | Public; used by the hosted page itself |
Creating a session
curl https://api.cimplify.io/v1/checkout/sessions \
-H "Authorization: Bearer $CIMPLIFY_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{
"cart_id": "crt_01J5BGM…",
"public_key": "pk_live_…",
"order_types": ["delivery", "pickup"],
"default_order_type": "delivery",
"currency": "GHS",
"submit_label": "Pay GH₵29.99",
"success_url": "https://store.example.com/orders/thanks",
"cancel_url": "https://store.example.com/cart",
"appearance": {
"theme": "light",
"variables": { "primaryColor": "#0a2540" }
},
"metadata": { "shipping_zone": "GH-AC" }
}'Request body: CreateCheckoutSessionRequest
| Field | Type | Required | Notes |
|---|---|---|---|
cart_id | string | yes | Existing cart on the same business. |
public_key | string | no | pk_… embedded into the hosted page. Defaults to the business's primary public key. |
order_types | string[] | no | Subset of delivery | pickup | dine_in. |
default_order_type | string | no | Pre-selected order type. |
currency | string | no | ISO 4217 override. |
success_url | string | no | Cimplify redirects here on success with ?order_id=…&session_id=…. |
cancel_url | string | no | Renders a "Return to store" button. |
appearance | object | no | ElementAppearance. |
submit_label | string | no | Override Pay button copy. |
metadata | object | no | Free-form JSON, echoed on the resulting order. |
Response: CreateCheckoutSessionResponse
{
"id": "cs_01J5BGM…",
"url": "https://pay.cimplify.io/s/cs_01J5BGM…",
"status": "open",
"expires_at": "2026-05-07T17:00:00Z"
}SDK helper
From a server context with a secret key:
const r = await fetch("https://api.cimplify.io/v1/checkout/sessions", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.CIMPLIFY_SECRET_KEY!}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
cart_id: cart.id,
success_url: `${origin}/orders/thanks`,
cancel_url: `${origin}/cart`,
}),
});
if (!r.ok) throw new Error(await r.text());
const session = await r.json();
return Response.redirect(session.url, 303);Reading a session
GET /v1/checkout/sessions/:id returns the public-safe view of the session used by the hosted page. You generally don't call this directly, but it's useful for debugging or for building a custom-host alternative to pay.cimplify.io.
{
"id": "cs_…",
"status": "open",
"business_id": "biz_…",
"cart_id": "crt_…",
"public_key": "pk_live_…",
"business": { "name": "…", "logo_url": "https://…" },
"cart": { "items": [...], "subtotal": "29.99", "tax_amount": "0.00", "total": "29.99", "currency": "GHS" },
"order_types": ["delivery", "pickup"],
"default_order_type": "delivery",
"appearance": { "theme": "light", "variables": { "primaryColor": "#0a2540" } },
"submit_label": "Pay GH₵29.99",
"success_url": "https://store.example.com/orders/thanks",
"cancel_url": "https://store.example.com/cart",
"expires_at": "2026-05-07T17:00:00Z"
}Lifecycle
| Status | Meaning |
|---|---|
open | Created and within expires_at. URL is usable. |
completed | Customer paid. An order exists; webhook fired. |
expired | Past expires_at. Returns HTTP 410 Gone on subsequent reads. Issue a new session. |
After completion
- Cimplify redirects the customer to
success_urlwith?order_idand?session_id. order.completedwebhook fires. Treat the webhook as the source of truth; never fulfill on the redirect alone.- If
cancel_urlis set and the customer hits the "Return to store" button instead of paying, they bounce there with no params.
Errors
| Status | Code | Meaning |
|---|---|---|
| 401 | UNAUTHORIZED | Missing or invalid API key. |
| 403 | FORBIDDEN | API key doesn't belong to the cart's business. |
| 404 | CART_NOT_FOUND | cart_id doesn't exist. |
| 410 | SESSION_GONE | Session expired. Create a new one. |
| 422 | VALIDATION_ERROR | Bad input (e.g. malformed appearance JSON). |
Next
- Payment links: For paying an existing order
- Webhooks: Source of truth for completion
Link dashboard
The shopper-facing UX at `link.cimplify.io`. Customers visit it directly to manage their saved details across every Cimplify-powered storefront. This page is a tour of what shoppers see; these screens are _not_ embeddable on their own (use [AccountElement](/docs/link/account-element) for that).
Payment links
A payment link is a short URL on `pay.cimplify.io/:token` that takes payment for an _already-existing_ order. Use these for invoicing flows: you bill someone offline, generate a token, drop the link into a WhatsApp / email / SMS, and the customer clicks through to settle.