Browse SDK

plandalf.present()

Open an offer and get an awaitable flow handle.

Implemented by the browser object; parameter and return types follow the delegated class declaration.

Call this after plandalf.ready(). The browser wrapper can return undefined before initialization.

Signature

plandalf.present(
  slug: string,
  opts?: Partial<FlowOpenOptions>,
): FlowHandle<FlowResult>

Arguments

NameTypeMeaning
slugstringPublished offer slug.
opts?Partial<FlowOpenOptions>Flow options passed through to the class. The browser wrapper declares this argument as any and passes it to the typed class method.

Example

present.js
plandalf.ready(async () => {
  const handle = plandalf.present('upgrade', {
    frame: 'modal',
    size: 'standard',
  })
  const result = await handle
  if (result.status === 'complete') {
    // Confirm access on your server.
    console.log(result.session?.uuid)
  }
})

Present options

The opts object accepts these FlowOpenOptions fields.

FieldTypeMeaning
confirmClose?() => boolean | Promise<boolean>Merchant-supplied "are you sure?" gate. Resolved true allows the close to proceed, false keeps the frame open. Replaces the previous boolean + label/title strings combo. Off when omitted.
context?Record<string, unknown>Initial values for the flow context.
continuity?ContinuityScopePer-call continuity override.
frame?FrameModeFrame modality. Was previously mode — renamed because mode now means the test/live/preview environment (see below).
metadata?Record<string, string>Per-call Stripe-customer metadata. Eager string values only — for window-global lookups use the page-global PlandalfConfig.metadata thunk form. Wins over PlandalfConfig.metadata on overlap.
mode?"test" | "live" | "preview"Environment override: 'test' | 'live' | 'preview'. Was previously environment. The server uses this to route the session through the org's test or live integration; super-admin only.
promo?PromoContextResolved promotion context. The current present() implementation also resolves a promo slug string at runtime.
properties?Record<string, unknown>Per-call form-field prefill defaults. Wins over PlandalfConfig.properties on overlap. See specs/sdk-checkout-config.md.
session?string | nullSession continuity token (cks_…). Pass explicitly to resume a specific session server-side — cross-device handoff, email "continue your checkout" links, anywhere the merchant has a token in hand. Pass null to force a fresh session and skip any stored token. Omit entirely to let the SDK auto-detect.
sessionId?stringReuse an existing session UUID instead of creating a fresh one. Used by the auto-resume path to finalize against the ORIGINAL session after a redirect-based auth bounce — creating a new session would lose the draft upsell invoice that needs settling.
size?FlowSize | { h: string; w: string; }Size of the modal panel. Either a named preset OR an explicit { w, h } object for one-off cases. Defaults to 'standard'.
templateId?stringLower-level template selector. The method supplies templateSlug from its slug argument, so this does not select the offer here.
templateSlug?stringCan override the slug argument in the current implementation. Pass the desired slug as the method argument instead.
user?stringCustomer JWT for THIS call only — overrides the SDK-wide identity from plandalf.setUser() or the user init option. Useful for "buy as customer" admin tooling, impersonation flows, or offers that need a different identity than the global one. The value is the raw JWT string.

Supported compatibility options

The current runtime still reads these older fields.

FieldTypeMeaning
animation?"slide" | "fade" | "none"Frame entrance animation.
backdrop?booleanWhether to render a backdrop behind the frame.
closeButton?booleanWhether to show the frame close button.
closeOnBackdrop?booleanWhether a backdrop click closes the frame.
confirmLeaveLabel?stringLeave button text in the built-in close confirmation.
confirmMessage?stringMessage in the built-in close confirmation.
confirmStayLabel?stringStay button text in the built-in close confirmation.
confirmTitle?stringTitle in the built-in close confirmation.
duration?numberFrame animation duration in milliseconds.
environment?"test" | "live"Test or live session routing. The newer per-call name is mode.
height?stringExplicit frame height.
onClose?(reason) => voidCallback when the presented flow closes. Await the handle for the final result.
onComplete?(result) => voidCallback on flow completion. Await the handle for the final result.
onError?(error) => voidCallback on flow failure. A rejected handle can also be caught.
position?"left" | "right"Frame position, left or right.
width?stringExplicit frame width. This takes precedence over a size preset.

Declared without current effect

FieldTypeMeaning
dragToClose?booleanCollected into frame config, but not passed to the rendered frame.
headless?booleanDeclared in the type, but the checkout implementation does not read it.

Awaited result

Await the handle for a FlowResult. The result fields are:

FieldTypeMeaning
customer?CustomerConvenience — same as result.session.customer.
reason?"complete" | "cancel" | "escape"When dismissed, why — backdrop / close button / escape.
redirectUrl?stringWhere to redirect the customer after complete (if the offer configures one).
session?CheckoutSessionPayloadThe full CheckoutSession at the moment of completion (populated on status='complete' only). Invoice + everything else lives in here — inspect via result.session.uuid, result.session.total, result.session.invoice, etc.
statusFlowResultStatus'complete' = user finished the flow. 'dismissed' = closed early.

Returns

FlowHandle<FlowResult>

Behaviour

The returned handle is awaitable. It also has an events async iterable and close() method. A completed browser flow still needs server-side entitlement verification.

All plandalf methods

Feature detail