Skip to main content
Docs

useCheckout()

Warning

This API is experimental and subject to change while Clerk Billing is under Beta. To mitigate potential disruptions, we recommend pinning your SDK and clerk-js package versions.

The useCheckout() hook is used to create, manage, and confirm a checkout session for a user or an organization's subscription plan. The hook provides the state of the current checkout process, such as its status and any errors, along with methods to initiate and complete the checkout.

There are two ways to use useCheckout():

  1. In conjunction with <CheckoutProvider /> to create a shared checkout context. All child components inside the provider can then use useCheckout() to access or update the same checkout state.
  2. Using useCheckout() on its own by passing configuration options directly to it. This is ideal for self-contained components that handle their own checkout flow without needing a shared context.

Important

For the best user experience and to prevent potential errors, always wrap components using useCheckout() with both <ClerkLoaded> and <SignedIn> components. This ensures that the user is properly authenticated and Clerk is fully initialized before accessing checkout functionality.

import { ClerkLoaded, SignedIn } from '@clerk/nextjs'

function CheckoutPage() {
  return (
    <ClerkLoaded>
      <SignedIn>
        <YourCheckoutComponent />
      </SignedIn>
    </ClerkLoaded>
  )
}
  • Name
    options?
    Type
    UseCheckoutOptions
    Description

    An object containing the configuration for the checkout flow. This is required if the hook is used without a <CheckoutProvider /> wrapping the component tree.

  • Name
    for?
    Type
    'organization'
    Description

    Specifies if the checkout is for an organization. If omitted, the checkout defaults to the current user.

  • Name
    planId
    Type
    string
    Description

    The ID of the subscription plan to check out (e.g., cplan_xxxx).

  • Name
    planPeriod
    Type
    'monthly' | 'yearly'
    Description

    The billing period for the plan.

  • Name
    checkout
    Type
    object
    Description

    Specify the checkout resource properties, state helpers, and methods.

The checkout object contains the following:

Resource properties

These properties describe the checkout resource itself. They are null until the checkout process is started by calling the start() method.

  • Name
    id
    Type
    string | null
    Description

    The unique identifier for the checkout resource.

  • Name
    paymentSource
    Type
    object | null
    Description

    The payment source being used for the checkout.

  • Name
    plan
    Type
    object | null
    Description

    The subscription plan details for the checkout.

  • Name
    externalClientSecret
    Type
    string | null
    Description

    The client secret from an external payment provider, like Stripe, used to complete the payment on the client-side.

  • Name
    planPeriod
    Type
    'monthly' | 'yearly' | null
    Description

    The billing period for the plan.

  • Name
    planPeriodStart
    Type
    Date | null
    Description

    The start date of the plan period.

  • Name
    totals
    Type
    object | null
    Description

    The total costs, taxes, and other pricing details.

  • Name
    isImmediatePlanChange
    Type
    boolean | null
    Description

    Indicates if the plan change will take effect immediately.

State helpers

These properties provide information about the current state of the hook's operations.

  • Name
    status
    Type
    'idle' | 'starting' | 'confirming' | 'complete' | 'error'
    Description

    The current status of the checkout flow.

  • Name
    isStarting
    Type
    boolean
    Description

    Returns true when the start() method is in progress.

  • Name
    isConfirming
    Type
    boolean
    Description

    Returns true when the confirm() method is in progress.

  • Name
    error
    Type
    ClerkAPIResponseError | null
    Description

    Returns an error object if any part of the checkout process fails.

  • Name
    fetchStatus
    Type
    'idle' | 'fetching' | 'error'
    Description

    The data fetching status for the checkout resource.

Methods

These methods are used to control the checkout flow.

  • Name
    start()
    Type
    () => Promise<CommerceCheckoutResource>
    Description

    Initializes the checkout process by creating a checkout resource on the server.

  • Name
    confirm()
    Type
    (params: ConfirmCheckoutParams) => Promise<CommerceCheckoutResource>
    Description

    Confirms the checkout, typically after the user has entered payment details.

  • Name
    complete()
    Type
    (params?: { redirectUrl: string }) => void
    Description

    Finalizes the checkout process. Can optionally accept a redirectUrl to navigate the user to upon completion.

  • Name
    clear()
    Type
    () => void
    Description

    Clears the current checkout state from the cache.

Examples

The useCheckout() hook can be used with a context provider for managing state across multiple components or as a standalone hook for more isolated use cases.

Using the <CheckoutProvider /> is the recommended approach when checkout state needs to be shared across multiple components. The provider is configured once, and any child component can access the checkout context by calling useCheckout().

The following example shows a <SubscriptionPage /> that sets up the provider and a <CheckoutFlow /> component that consumes the context to manage the checkout UI.

src/components/SubscriptionPage.tsx
import { CheckoutProvider } from '@clerk/clerk-react' // Fictional import path
import { CheckoutFlow } from './CheckoutFlow'

export function SubscriptionPage() {
  // The provider sets the context for the checkout flow.
  // Any child component can now call `useCheckout()` to access this context.
  return (
    <CheckoutProvider for="user" planId="cplan_123abc" planPeriod="monthly">
      <div>
        <h1>Upgrade Your Plan</h1>
        <p>You are about to subscribe to our monthly plan.</p>
        <CheckoutFlow />
      </div>
    </CheckoutProvider>
  )
}
src/components/CheckoutFlow.tsx
import { useCheckout } from '@clerk/clerk-react' // Fictional import path

export function CheckoutFlow() {
  // `useCheckout` reads context from the nearest `<CheckoutProvider />`
  const { checkout } = useCheckout()
  const { start, status, isStarting, error } = checkout

  const handleStartCheckout = async () => {
    try {
      // This will create the checkout session on the backend
      await start()
      // Next steps would involve using a payment element (e.g., Stripe)
      // and then calling `checkout.confirm()` and `checkout.complete()`.
    } catch (e) {
      console.error('Error starting checkout:', e)
    }
  }

  return (
    <div>
      <p>Current status: {status}</p>
      <button onClick={handleStartCheckout} disabled={isStarting}>
        {isStarting ? 'Starting...' : 'Proceed to Payment'}
      </button>
      {error && <p style={{ color: 'red' }}>Error: {error.errors[0].message}</p>}
      {status === 'starting' && <p>Redirecting to payment...</p>}
    </div>
  )
}

For simple, self-contained components, you can use useCheckout() by passing the configuration options directly to the hook. This avoids the need to wrap the component in a provider.

The following example shows an <UpgradeButton /> component that manages its own checkout flow.

src/components/UpgradeButton.tsx
import { useCheckout } from '@clerk/clerk-react' // Fictional import path

export function UpgradeButton({ planId, planPeriod }) {
  // Pass options directly to the hook when not using a provider.
  const { checkout } = useCheckout({
    planId,
    planPeriod,
    for: 'user',
  })

  const { start, status, isStarting, error } = checkout

  const handleStartCheckout = async () => {
    try {
      await start()
      // In a real app, you would now use the `externalClientSecret`
      // from the checkout object to render a payment form.
      console.log('Checkout started! Status:', checkout.status)
    } catch (e) {
      console.error('Error starting checkout:', e)
    }
  }

  return (
    <div>
      <button onClick={handleStartCheckout} disabled={isStarting}>
        {isStarting ? 'Initializing...' : `Upgrade to ${planPeriod} plan`}
      </button>
      {error && <p style={{ color: 'red' }}>Error: {error.errors[0].message}</p>}
    </div>
  )
}

Checkout flow with a new payment method

Prompt users to add a new payment method during checkout

Checkout flow for returning users

Prompt users to select an existing payment method during checkout

Feedback

What did you think of this content?

Last updated on