Skip to main content
Docs

useSubscription()

Warning

Billing is currently in Beta and its APIs are experimental and may undergo breaking changes. 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
    enabled?
    Type
    boolean
    Description

    If true, a request will be triggered when the hook is mounted. Defaults to true.

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

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

  • Name
    keepPreviousData?
    Type
    boolean
    Description

    If true, the previous data will be kept in the cache until new data is fetched. Defaults to false.

Returns

useSubscription() returns an object with the following properties:

  • Name
    data
    Type
    undefined | null | BillingSubscriptionResourceJavaScript Icon
    Description

    The subscription object, undefined before the first fetch, or null if no subscription exists.

  • Name
    error
    Type
    undefined | Error
    Description

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

  • Name
    isFetching
    Type
    boolean
    Description

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

  • Name
    isLoading
    Type
    boolean
    Description

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

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

    Function to manually revalidate or refresh the subscription data.

Examples

Basic usage

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

app/pricing/subscription-details/page.tsx
'use client'

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

export default 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.

app/pricing/organization-subscription-details/page.tsx
'use client'

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

export default 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'

export 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