Skip to main content
Two hooks bracket a checkout: useCheckoutPreview shows what the customer owes today and what changes before anything is charged, and useCheckoutSession polls a hosted-form session until the PSP confirms. Both are scoped to the portal customer. Every hook returns isLoading: boolean and error: Error | null (see Introduction); the sections below list each hook’s specific returns.

useCheckoutPreview

Returns a server-computed preview of a checkout action — amount due today, the upcoming schedule, credit impact, line items, and warnings — before anything is charged. It calls POST /v1/checkout/sessions/preview with a discriminated input. Pass null to disable (e.g. while inputs are still being assembled). customerId is filled from context — callers omit it.
For plan-change previews, use useSubscription(id).previewChange() instead — it returns a richer shape (proration, entitlement diffs, direction/timing).
Parameters
CheckoutPreviewInput | null
required
The action to preview, a discriminated union on purpose. Pass null to hold the query inert.
Returns
  • preview — the CheckoutPreviewResult, or null while loading / when disabled. It extends the shared base shape with the per-purpose details payload:
DueToday
Discriminated by kind: charge_now (cents, currency), invoice_later (cents, netDays, estimatedDate), or no_charge.
PreviewLineItem[]
{ description, unitAmount, quantity, subtotal, muted? } rows.
number
Money breakdown in minor units.
PreviewSchedule
Optional { date, amountCents? } for the next charge.
CreditImpact
Optional wallet delta — { currencyName, denomination, minorUnitScale, currentBalance, delta, afterBalance, … }.
PreviewWarning[]
{ code, params? } — e.g. trial_requires_payment_method, customer_has_no_payment_method.
-
Echoes the purpose; details is the per-purpose payload (e.g. details.subscription, details.creditTopup).
  • refresh()() => Promise<void> — refetch the preview (e.g. after the customer edits the amount).

useCheckoutSession

Polls GET /v1/checkout/sessions/:id/status and reports when a hosted-form payment resolves. Use it to await the result of a requires_form SettleOutcome — after the Elements form submits, the webhook completer flips the session to completed once the PSP confirms. Polling is tiered: ~1s for the first 30s (hot phase), then ~5s, then it stops and synthesizes expired at maxWaitMs. Parameters
string | null
required
The session to poll. Pass null to leave the hook idle (e.g. before the form step is reached). Changing the id resets the timeout.
boolean
default:"true"
Gate polling without unmounting the hook. Set false to hold the query inert (e.g. before the modal advances to its confirming step).
number
default:"90000"
Wall-clock cap on the pending window. After this elapses the hook stops polling and surfaces status: 'expired' even if the server row is still pending.
Returns
  • status'idle' | 'pending' | 'completed' | 'expired':
    • 'idle' — no checkoutSessionId, or enabled is false.
    • 'pending' — polling; defaults to this until the first fetch resolves.
    • 'completed' — the PSP confirmed and the session row finalized.
    • 'expired' — terminal server status, or the client-side maxWaitMs timeout fired.
  • data — the CheckoutSessionStatus row, or null before the first response: { id, status, completedAt, subscriptionId, invoiceId }.
Pair this with a requires_form outcome: render the <PaymentForm> Elements step, then mount useCheckoutSession(session.id) to await provisioning.

See also

Catalog & pricing

The plans and packages a checkout starts from.

Settlement model

Every SettleOutcome kind and its callback, including requires_form.

Credits & wallets

Top-up and package purchases that feed the preview.