Checkout Sessions
Checkout Sessions
Checkout sessions let you create a hosted page with a shareable URL. You create a session, then redirect your customer to the generated URL — or email it to them — to collect a payment or save a payment method.
Choosing a mode
Set mode when you create the session. It decides what the page collects and what it promises the customer:
PAYMENT— collects a one-time payment.amountandcurrencyare required. Completes with acheckout_session.paidwebhook, sent once the underlying payment intent succeeds — immediately for a card, after the collection clears for a Bacs Direct Debit rail. This is the default, and the right choice whenever money is due.SETUP— saves a payment method for later and charges nothing. Omitamount; acustomeris required, and the saved method is bound to it permanently. Completes with acheckout_session.setup_succeededwebhook.
Charging now and keeping the card isPAYMENTmode. TheSETUPpage tells the customer "you won't be charged now", and that promise isn't configurable — so don't reach forSETUPwhen you intend to charge immediately. Set acustomeron aPAYMENT-mode session and the page offers to save the card for future use; when the customer opts in, the method is stored against that customer and you can charge it later server-side. Without acustomeron the session, no save option is shown.
Use SETUP when nothing is due yet — a free trial, a Direct Debit mandate ahead of the first billing date, or storing a card before the first order.
Offering Apple Pay and Google Pay
A PAYMENT-mode page can offer Apple Pay and Google Pay alongside the card form. Both need enabling on your account first. See Digital Wallets for more information.
Checkout session lifecycle
- Create a checkout session — a hosted page URL is generated
- Redirect (or email) the customer to the URL
- The customer completes the page — paying in
PAYMENTmode, entering payment details inSETUPmode - The session transitions to
COMPLETEand a webhook is sent:checkout_session.paidinPAYMENTmode,checkout_session.setup_succeededinSETUPmode
Sessions expire after 24 hours if not completed.
Creating a checkout session
The Idempotency-Key header lets you safely retry the request if it fails — see Idempotency.
mode is omitted below, so this session is PAYMENT mode.
curl -X POST https://api.synaptopay.com/v1/accounts/acct_YOUR_ACCOUNT/checkout-sessions \
-H "Authorization: Api-Key $API_KEY" \
-H "Idempotency-Key: YOUR_UNIQUE_KEY" \
-H "Content-Type: application/json" \
-d '{
"amount": "10000",
"currency": "GBP",
"client_reference_id": "order_12345",
"success_url": "https://example.com/success",
"cancel_url": "https://example.com/cancel"
}'Response
{
"name": "accounts/acct_YOUR_ACCOUNT/checkout-sessions/cs_SESSION_ID",
"state": "OPEN",
"amount": "10000",
"currency": "GBP",
"client_reference_id": "order_12345",
"url": "https://pay.synaptopay.com/checkout?s_checkout_session=cs_SESSION_ID",
"payment_intent": "accounts/acct_YOUR_ACCOUNT/payment-intents/pi_PAYMENT_INTENT_ID",
"paid": false,
"success_url": "https://example.com/success",
"cancel_url": "https://example.com/cancel",
"expire_time": "2025-11-18T16:00:00Z",
"create_time": "2025-11-17T16:00:00Z",
"update_time": "2025-11-17T16:00:00Z"
}Redirect your customer to the url to complete payment.
Saving a payment method without charging
Pass mode: SETUP and a customer, and omit amount. currency is optional here — when set it restricts the page to rails supporting it; when omitted, every setup-capable rail on your account is offered.
curl -X POST https://api.synaptopay.com/v1/accounts/acct_YOUR_ACCOUNT/checkout-sessions \
-H "Authorization: Api-Key $API_KEY" \
-H "Idempotency-Key: YOUR_UNIQUE_KEY" \
-H "Content-Type: application/json" \
-d '{
"mode": "SETUP",
"customer": "accounts/acct_YOUR_ACCOUNT/customers/cus_CUSTOMER_ID",
"metadata": { "plan_id": "plan_monthly" },
"success_url": "https://example.com/details-saved"
}'{
"name": "accounts/acct_YOUR_ACCOUNT/checkout-sessions/cs_SESSION_ID",
"mode": "SETUP",
"state": "OPEN",
"customer": "accounts/acct_YOUR_ACCOUNT/customers/cus_CUSTOMER_ID",
"setup_intent": "accounts/acct_YOUR_ACCOUNT/setup-intents/seti_SETUP_INTENT_ID",
"url": "https://pay.synaptopay.com/checkout?s_checkout_session=cs_SESSION_ID",
"paid": false,
"metadata": { "plan_id": "plan_monthly" },
"success_url": "https://example.com/details-saved",
"expire_time": "2025-11-18T16:00:00Z",
"create_time": "2025-11-17T16:00:00Z"
}paid stays false for the whole life of a SETUP session — nothing was charged. The saved method is attached to customer and cannot later be used for a different one.
Reconciling a completed setup
Listen for checkout_session.setup_succeeded, not setup_intent.succeeded. Only the session event carries the metadata you set at create time, so it's the one you can match back to the order, plan or booking that prompted the setup:
{
"name": "accounts/acct_YOUR_ACCOUNT/events/evt_EVENT_ID",
"type": "checkout_session.setup_succeeded",
"checkout_session": {
"name": "accounts/acct_YOUR_ACCOUNT/checkout-sessions/cs_SESSION_ID",
"mode": "SETUP",
"state": "COMPLETE",
"customer": "accounts/acct_YOUR_ACCOUNT/customers/cus_CUSTOMER_ID",
"setup_intent": "accounts/acct_YOUR_ACCOUNT/setup-intents/seti_SETUP_INTENT_ID",
"paid": false,
"metadata": { "plan_id": "plan_monthly" }
},
"event_time": "2025-11-17T16:04:00Z"
}Read the setup_intent from the event to get the payment_method it saved, then use that method to charge the customer or to create a subscription.
For a card, the event means the card is saved and chargeable. For a Bacs Direct Debit mandate it means the customer finished the form and the mandate was submitted — Bacs confirms it a few working days later, so key off dd_mandate.active / dd_mandate.failed for the outcome. You can still start collecting immediately; see Direct Debit.
Key fields
| Field | Description |
|---|---|
mode | PAYMENT (default) charges the customer; SETUP saves a payment method without charging |
amount | Amount in smallest currency unit (e.g. 10000 = 100.00 GBP). Required in PAYMENT mode, must be omitted in SETUP mode |
currency | Three-letter ISO currency code. Required in PAYMENT mode; optional in SETUP mode, where it restricts the rails offered |
customer | The customer to attach. Required in SETUP mode; in PAYMENT mode it enables the save-card option on the page |
payment_method_types | Restricts which payment rails the customer may pick. Empty means every eligible rail on your account is offered |
client_reference_id | Your own reference (e.g. order ID) for cross-referencing |
success_url | URL to redirect the customer to after they complete the page. If not set, a Synapto hosted success page is shown |
cancel_url | When set, a "Back" link is shown on the checkout page that redirects here |
url | The hosted page URL. Only present when state is OPEN |
payment_intent | The payment intent created automatically for this session. PAYMENT mode only |
setup_intent | The setup intent created automatically for this session. SETUP mode only |
paid | true once payment has succeeded. Always false in SETUP mode |
payment_intent_data | Configures the payment intent the session creates: description (max 1000 chars, shown on the receipt) and disable_payment_receipt (see Receipts). PAYMENT mode only — rejected in SETUP mode |
metadata | Key-value pairs for your own use (max 50 keys, key max 40 chars, value max 500 chars) |
Checkout session states
| State | Description |
|---|---|
OPEN | Customer can visit the URL and complete the page |
COMPLETE | The payment succeeded, or in SETUP mode the payment method was saved |
EXPIRED | Session expired before the customer completed it (after 24 hours by default) |
Expiring a session
If an order is canceled or changes before the customer completes the page, expire the session to invalidate the link:
curl -X POST https://api.synaptopay.com/v1/accounts/acct_YOUR_ACCOUNT/checkout-sessions/cs_SESSION_ID:expire \
-H "Authorization: Api-Key $API_KEY"This cancels the session's managed intent — the payment intent, or the setup intent in SETUP mode — and sets the session state to EXPIRED. If the customer completed the page in the meantime, the session is completed instead of expired.
Webhooks
When a checkout session is completed, an event is sent to your webhook endpoints — checkout_session.paid in PAYMENT mode, checkout_session.setup_succeeded in SETUP mode. Both carry the session, including its metadata. See Webhooks for setup instructions.
Updated 29 days ago