CheckoutButton starts checkout for one plan through BillingProvider and opens Razorpay, redirects, hands you a Stripe client secret, or reports a completed or scheduled change.
When to use
- A plan card or marketing section that sells one plan.
- An onboarding step that subscribes the new customer.
- Anywhere you need checkout without the full
PricingTable.
- Light
- Dark
- Minimal
- Neobrutal
- Nozle
- Nozle Dark

Importing CheckoutButton
Rendering CheckoutButton
CheckoutButton must be inside a BillingProvider with createCheckout. Your merchant route creates the checkout with your secret key; see Implement the merchant endpoint.
app/pricing/buy-pro.tsx
createCheckout, verifyCheckout and getCheckoutStatus from BillingProvider.
What a click does
- The button calls
createCheckout({ idempotencyKey, planCode, returnUrl, registerMandate? }). It keeps one idempotency key per plan and reuses it when the customer clicks again, so a retry reopens the same pending checkout. A second click while the first is running does nothing. - For a
razorpayresult it loads Razorpay and opens it. A captured payment is checked withverifyCheckout, then polled withgetCheckoutStatusup to 30 times, one second apart. A failed payment shows “Payment failed. You can retry checkout.” - For a
processingresult it polls the same way and continues with the checkout it returns. - For a
hostedresult, or a result with aurl, it redirects the page. - For a
striperesult it passes the client secret toonStripeClientSecret. - For a
completedorscheduledresult it callsonCompleteoronScheduled.
useBillingRefresh() from the hooks. See checkout result types.
Examples
Embedded Stripe checkout and results
PassonStripeClientSecret and render Checkout with the secret. onComplete and onScheduled report changes that need no payment step.
Razorpay
For Razorpay, give the providerverifyCheckout and getCheckoutStatus. Each calls your backend, which scopes the request to the signed-in customer.
API reference
string
required
The plan to check out, sent to
createCheckout.string
default:"Get Started"
Button text. While checkout starts, the button reads “Loading…” and is disabled.
string
Sent to
createCheckout, where the provider returns the customer after payment. Defaults to the current URL.boolean
Sent to
createCheckout when set, to ask for a recurring payment mandate. Not sent when left out.(clientSecret: string) => void
Fires for an embedded Stripe checkout and receives its client secret; render
Checkout with it. Without it, a Stripe result fails with “onStripeClientSecret is required for embedded Stripe checkout”.(result: CompletedCheckoutResult) => void
Fires for a
completed result and receives it: the change took effect without a payment step, or a resumed checkout succeeded.(result: ScheduledCheckoutResult) => void
Fires for a
scheduled result, such as a downgrade at renewal, and receives it.(paymentId: string) => void
Razorpay only. Fires when the payment is captured and the plan is fulfilled, and receives the Razorpay payment ID.
(status: CheckoutStatus) => void
Fires with each status while the button waits for a payment to be confirmed, and receives that status.
() => void
Razorpay only. Fires when the customer closes the Razorpay window without paying.
(error: Error) => void
Fires when checkout fails and receives the error. The message also shows next to the button in a
role="alert" element.string
Deprecated and not used. The Razorpay key comes from the checkout result.
string
Class name on the button.
CSSProperties
Inline styles on the button, on top of the theme’s.
Appearance
Theme, variables and element overrides. Defaults to the provider’s. See Appearance.
States
Appearance
Element keys
Element keys
checkoutButton (the button).Style them with appearance.elements. See Elements.Related
Checkout
Renders the Stripe payment step for the client secret.
PricingTable
Plan cards that start checkout the same way.
UpgradeButton
Confirms a plan change before checkout.
Checkout result types
Every result
createCheckout can return.



