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. amount and currency are required. Completes with a checkout_session.paid webhook, 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. Omit amount; a customer is required, and the saved method is bound to it permanently. Completes with a checkout_session.setup_succeeded webhook.
📘

Charging now and keeping the card is PAYMENT mode. The SETUP page tells the customer "you won't be charged now", and that promise isn't configurable — so don't reach for SETUP when you intend to charge immediately. Set a customer on a PAYMENT-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 a customer on 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

  1. Create a checkout session — a hosted page URL is generated
  2. Redirect (or email) the customer to the URL
  3. The customer completes the page — paying in PAYMENT mode, entering payment details in SETUP mode
  4. The session transitions to COMPLETE and a webhook is sent: checkout_session.paid in PAYMENT mode, checkout_session.setup_succeeded in SETUP mode

Sessions expire after 24 hours if not completed.

Creating a checkout session

API reference

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

FieldDescription
modePAYMENT (default) charges the customer; SETUP saves a payment method without charging
amountAmount in smallest currency unit (e.g. 10000 = 100.00 GBP). Required in PAYMENT mode, must be omitted in SETUP mode
currencyThree-letter ISO currency code. Required in PAYMENT mode; optional in SETUP mode, where it restricts the rails offered
customerThe customer to attach. Required in SETUP mode; in PAYMENT mode it enables the save-card option on the page
payment_method_typesRestricts which payment rails the customer may pick. Empty means every eligible rail on your account is offered
client_reference_idYour own reference (e.g. order ID) for cross-referencing
success_urlURL to redirect the customer to after they complete the page. If not set, a Synapto hosted success page is shown
cancel_urlWhen set, a "Back" link is shown on the checkout page that redirects here
urlThe hosted page URL. Only present when state is OPEN
payment_intentThe payment intent created automatically for this session. PAYMENT mode only
setup_intentThe setup intent created automatically for this session. SETUP mode only
paidtrue once payment has succeeded. Always false in SETUP mode
payment_intent_dataConfigures 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
metadataKey-value pairs for your own use (max 50 keys, key max 40 chars, value max 500 chars)

Checkout session states

StateDescription
OPENCustomer can visit the URL and complete the page
COMPLETEThe payment succeeded, or in SETUP mode the payment method was saved
EXPIREDSession expired before the customer completed it (after 24 hours by default)

Expiring a session

API reference

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.


Did this page help you?