Skip to content

Session extensions (booking metadata)

Pass arbitrary partner-defined JSON through the entire checkout lifecycle by setting extensions on the cart payload when you create a session. Swft treats the contents as opaque and surfaces them verbatim in every webhook that fires off the session.

import { Swft } from '@swft-checkout/js'
const swft = new Swft({ apiKey: merchant.api_key })
const session = await swft.sessions.create({
cart: {
items: [{ id: 'class:reformer-100', name: '60-min Reformer', quantity: 1, price: 2500 }],
extensions: {
booking: {
class_schedule_id: 'cs_8f...',
user_id: 'usr_31...',
studio_id: 'stu_4d...',
reformer_id: null,
payment_type: 'single',
},
},
},
})
window.location.href = session.sessionUrl

extensions ends up in two places:

  1. The order.completed (and order.failed, cart.abandoned, refund.issued) webhook as a top-level extensions field alongside data. Use this to identify the booking on confirmation and create the booking row server-side.

  2. The pre-confirmation hook request body as extensions. Use this to look up the class/inventory and decide { available: true | false }.

If the session creates a Stripe Subscription (memberships), Swft copies the extensions into stripe.subscription.metadata.swft_extensions (JSON-stringified) so every renewal/cancellation event also carries the same booking context.

There is no schema on Swft’s side — extensions is Record<string, unknown>. Define yours on the partner side; we recommend versioning your extension keys (booking_v1, booking_v2, …) so you can evolve the shape without ambiguity in the webhook handler.