Skip to main content
Docs

useSubscription()

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 useSubscription() hook provides access to subscription information for users or organizations in your application. It returns the current subscription data and includes methods for managing it.

Warning

The useSubscription() hook should only be used for accessing and displaying subscription information. For authorization purposes (i.e., controlling access to features or content), use the has() helper or the <Protect> component instead.

Parameters

useSubscription() accepts a single optional object with the following properties:

  • Name
    for?
    Type
    'organization' | 'user'
    Description

    Specifies whether to fetch subscription for an organization or user. Defaults to 'user'.

  • Name
    keepPreviousData?
    Type
    boolean
    Description

    When true, the previous data will be kept in the cache until new data is fetched. This helps prevent layout shifts. Defaults to false.

Returns

useSubscription() returns an object with the following properties:

  • Name
    data
    Type
    | null
    Description

    The subscription object, or null if the data hasn't been loaded yet.

  • Name
    isLoading
    Type
    boolean
    Description

    A boolean that indicates whether the initial data is still being fetched.

  • Name
    isFetching
    Type
    boolean
    Description

    A boolean that indicates whether any request is still in flight, including background updates.

  • Name
    error
    Type
    Error | null
    Description

    Any error that occurred during the data fetch, or null if no error occurred.

  • Name
    revalidate
    Type
    () => Promise<void>
    Description

    Function to manually trigger a refresh of the subscription data.

Examples

Basic usage

The following example shows how to fetch and display subscription information.

'use client'
import { useSubscription } from '@clerk/nextjs/experimental'

function SubscriptionInfo() {
  const { data, isLoading, error } = useSubscription()

  if (isLoading) {
    return <div>Loading subscription...</div>
  }

  if (error) {
    return <div>Error loading subscription: {error.message}</div>
  }

  if (!data) {
    return <div>No subscription found</div>
  }

  return (
    <div>
      <h2>Your Subscription</h2>
      {/* Display subscription details */}
    </div>
  )
}

Organization subscription

The following example shows how to fetch an organization's subscription.

'use client'
import { useSubscription } from '@clerk/nextjs/experimental'

function OrganizationSubscription() {
  const { data, isLoading, revalidate } = useSubscription({
    for: 'organization',
    keepPreviousData: true,
  })

  const handleSubscriptionUpdate = async () => {
    // After making changes to the subscription
    await revalidate()
  }

  if (isLoading) {
    return <div>Loading organization subscription...</div>
  }

  return (
    <div>
      <h2>Organization Subscription</h2>
      {/* Display organization subscription details */}
      <button onClick={handleSubscriptionUpdate}>Refresh Subscription</button>
    </div>
  )
}

With error handling

The following example shows how to handle subscription data with proper error states.

app/pricing/subscription-details/page.tsx
'use client'
import { useSubscription } from '@clerk/nextjs/experimental'

function SubscriptionDetails() {
  const { data: subscription, isLoading } = useSubscription()

  if (isLoading) {
    return <div>Loading subscription...</div>
  }

  if (!subscription) {
    return <div>No subscription</div>
  }

  return (
    <div className="subscription-details">
      <h2>Subscription Details</h2>
      <div className="status">
        Status: <span className={`status-${subscription.status}`}>{subscription.status}</span>
      </div>

      <div className="dates">
        <p>Active since: {subscription.activeAt.toLocaleDateString()}</p>
        {subscription.pastDueAt && (
          <p className="warning">Past due since: {subscription.pastDueAt.toLocaleDateString()}</p>
        )}
      </div>

      {subscription.nextPayment && (
        <div className="next-payment">
          <h3>Next Payment</h3>
          <p>Amount: {subscription.nextPayment.amount.amountFormatted}</p>
          <p>Due: {subscription.nextPayment.date.toLocaleDateString()}</p>
        </div>
      )}

      <div className="subscription-items">
        <h3>Subscription Items</h3>
        <ul>
          {subscription.subscriptionItems.map((item) => (
            <li key={item.id}>{/* Display subscription item details */}</li>
          ))}
        </ul>
      </div>
    </div>
  )
}

export default function Page() {
  const { data, isLoading, error, isFetching, revalidate } = useSubscription()

  if (error) {
    return (
      <div className="error-state">
        <h3>Failed to load subscription</h3>
        <p>{error.message}</p>
        <button onClick={revalidate}>Try Again</button>
      </div>
    )
  }

  return (
    <div className="subscription-status">
      {isLoading ? (
        <div>Loading...</div>
      ) : (
        <>
          <div className="status-indicator">{isFetching && <span>Refreshing...</span>}</div>
          {data ? <SubscriptionDetails /> : <div>No active subscription</div>}
        </>
      )}
    </div>
  )
}

Feedback

What did you think of this content?

Last updated on