When to use it
- You want to get paid this week, not after building a checkout page.
- You’re selling one-time products or services and want a page that just works.
- You’re launching subscriptions and want signup and the first charge handled for you.
- You want card data and PCI scope nowhere near your servers.
How it works
Before you start
- Create a test-mode secret key (
sk_v1_test_...) in the Dashboard. - Have a success page and a cancel page on your site.
1. Create a Checkout Session
CallPOST /v1/checkout/sessions from your server, calculating the amount
from prices you trust, never from the browser.
amountis in cents:15000is $150.00. USD only for now.order_1001is your order’s ID; it threads throughIdempotency-Key,client_reference_id, andmetadataso the webhook can find the order.[email protected]pre-fills the buyer’s email (optional).success_urlandcancel_urlare pages on your site.IONIC_SECRET_KEYis an environment variable holding your test-mode secret key.
price_id instead and Ionic uses
the price you defined there:
cs_... ID on your order and use url unchanged; it carries its
own token (hcs_...), not the session ID.
If the call times out, retry it with the same Idempotency-Key and body to
get the original session back. See Idempotency.
Selling a subscription?
Same call withmode: "subscription", where every line item is a recurring
Catalog price sharing one billing cadence:
price_Monthly00000000000000000 stands in for one of your recurring prices.
Pass customer when the buyer already has an Ionic customer record;
otherwise the hosted page collects their details and creates one. Everything
downstream (redirect, webhook, fulfillment) is identical; see
Subscriptions for the recurring lifecycle:
renewals, dunning, cancellation.
2. Redirect the buyer
From your page, call your server route and follow the returned URL:{CHECKOUT_SESSION_ID} placeholder
in success_url with the real session ID and redirects. The back button
returns the buyer to cancel_url; that and a closed tab both leave the
session open and unpaid.
On your success page, verify before you show “paid”: send the session_id
query value to your backend, retrieve the session with your secret key, and
check both status fields.
open, show a short “Confirming payment” state and
poll your backend.
Don’t call
POST /v1/checkout/sessions/{id}/confirm here; that endpoint
is for Embedded Checkout.3. Fulfill from the webhook
Subscribe an endpoint tocheckout.session.completed and
checkout.session.expired (delivered when a session lapses unpaid, after 24
hours by default). The completed event carries the order references you set at
creation:
webhooks.unwrap() from the server SDK checks the signature
and replay window, then returns a typed event; this Next.js example uses it.
On another stack, Verify signatures has the manual
implementation in Node, Python, and Go.
app/api/webhooks/ionic/route.ts
fulfillOrderOnce stores the event ID under a unique constraint so each order
fulfills once, and hands slow work (shipping, provisioning, email) to a
queue. Ionic delivers events at least once and in no guaranteed order; see
Idempotency and retries. Ionic doesn’t
email the buyer a receipt; send your order confirmation from this fulfillment
path.
Developing locally? Webhooks need a URL Ionic can reach. Expose your dev
server with a tunnel (for example ngrok or cloudflared), register the tunnel
URL as a test-mode endpoint, and pay again. The
webhooks quickstart covers endpoint setup.
See it work
Pay with4111 1111 1111 1111, any future expiration date, and any
three-digit CVC. Then check:
- The buyer lands on your success page.
- Your endpoint receives
checkout.session.completed, and the retrieved session iscompleteandpaid. - The payment appears in your Dashboard.
open and the buyer can retry. More scenarios in
Test cards.
Advanced options
The Checkout Sessions reference has the complete request and response contract. Commonly used:- Known customers: pass
customerto link the session. See Customers. - Optional items and quantities:
optional_itemsoffers add-ons the buyer can select;adjustable_quantityon a line item lets the buyer change the count. Fulfill from the completed session’s line items, not the original cart. - Field collection:
collect_configrequires contact, billing, or shipping fields. - Button label:
submit_typeacceptsauto,pay,book, ordonate. - Expiration:
expires_at, 30 minutes to 24 hours from creation; the default is 24 hours. - Capture and reuse:
payment_intent_datafor supported capture and future-usage behavior. - Metadata: up to 50 keys per session and 20 per line item; non-sensitive values only.
- Apple Pay: offered on the hosted page without merchant domain registration. See Apple Pay.
- Save a card without a purchase: use a Setup Intent; Checkout Session
creation does not accept
mode: "setup". See Save cards.
Next steps
Webhooks
Verify signatures and manage endpoints.
Going live
Swap test keys for live keys and launch.
Refunds and captures
Refund, capture, or cancel a payment.
Embedded Checkout
Keep buyers on your own domain.

