> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nozle.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# UpgradeButton

> A button that opens a confirmation dialog for a plan change and then starts it through your BillingProvider.

`UpgradeButton` opens an [`UpgradeModal`](/sdks/react/components/upgrade-modal) for one target plan and, when the customer confirms, starts the change through `createCheckout` on `BillingProvider`.

**When to use**

* Next to the current plan in billing settings ("Upgrade to Scale").
* In an [`UpgradePrompt`](/sdks/react/components/upgrade-prompt) or usage notice that names the next plan.
* A plan change that needs a confirmation step with the price difference.

For a full plan picker with exact quotes, use [`PlanChangeControl`](/sdks/react/components/plan-change-control).

**Light**

![UpgradeButton labelled Upgrade to Scale, light theme](https://mintcdn.com/nozle-d78f01d8/8jEvxrWAvqijYzbo/images/react/components/upgrade-button/light.png?fit=max\&auto=format\&n=8jEvxrWAvqijYzbo\&q=85\&s=6f07c8050d551188b9dd9382c90a13fe)

**Dark**

![UpgradeButton labelled Upgrade to Scale, dark theme](https://mintcdn.com/nozle-d78f01d8/8jEvxrWAvqijYzbo/images/react/components/upgrade-button/dark.png?fit=max\&auto=format\&n=8jEvxrWAvqijYzbo\&q=85\&s=ec919c12e6943d248138251422023865)

**Minimal**

![UpgradeButton labelled Upgrade to Scale, minimal theme](https://mintcdn.com/nozle-d78f01d8/8jEvxrWAvqijYzbo/images/react/components/upgrade-button/minimal.png?fit=max\&auto=format\&n=8jEvxrWAvqijYzbo\&q=85\&s=f32cf1c95aeaae5deac36b5977a32adb)

**Neobrutal**

![UpgradeButton labelled Upgrade to Scale, neobrutal theme](https://mintcdn.com/nozle-d78f01d8/8jEvxrWAvqijYzbo/images/react/components/upgrade-button/neobrutal.png?fit=max\&auto=format\&n=8jEvxrWAvqijYzbo\&q=85\&s=72cda4e961fb9a7db5fd53322edb3fca)

**Nozle**

![UpgradeButton labelled Upgrade to Scale, nozle theme](https://mintcdn.com/nozle-d78f01d8/8jEvxrWAvqijYzbo/images/react/components/upgrade-button/nozle.png?fit=max\&auto=format\&n=8jEvxrWAvqijYzbo\&q=85\&s=ca6472f69f21029e5a00212ee5e0047b)

**Nozle Dark**

![UpgradeButton labelled Upgrade to Scale, nozleDark theme](https://mintcdn.com/nozle-d78f01d8/8jEvxrWAvqijYzbo/images/react/components/upgrade-button/nozle-dark.png?fit=max\&auto=format\&n=8jEvxrWAvqijYzbo\&q=85\&s=0b7c7d625bcdb0a3d6a0fc367ebd4a0c)

## Importing UpgradeButton

```tsx theme={null}
import { UpgradeButton, type ProrationPreview } from '@nozle-js/react'
```

## Rendering UpgradeButton

Render it inside a `BillingProvider` with `createCheckout` (see [Configure BillingProvider](/sdks/react/installation#configure-billingprovider)) and reload billing data when the change is done:

```tsx components/upgrade-to-scale.tsx theme={null}
import { useBillingRefresh } from '@nozle-js/react'

export function UpgradeToScale({ onClientSecret }: { onClientSecret: (secret: string) => void }) {
  const refresh = useBillingRefresh()
  return (
    <UpgradeButton
      planCode="scale"
      label="Upgrade to Scale"
      subscriptionId="sub_123"
      onStripeClientSecret={onClientSecret}
      onUpgraded={() => void refresh()}
      onDowngradeScheduled={() => void refresh()}
      onError={(error) => console.error(error.message)}
    />
  )
}
```

### What a confirm does

The button calls `createCheckout` with the plan code, return URL and the `subscriptionId`, `quoteId` and `idempotencyKey` you pass, then handles every checkout result: Stripe client secret, Razorpay, hosted, processing, completed and scheduled. The dialog closes and:

* calls `onCheckoutStarted` after a Stripe client secret was handed to `onStripeClientSecret`,
* calls `onUpgraded` when the change completed, or a Razorpay payment was captured,
* calls `onDowngradeScheduled` for a `scheduled` result.

When the change fails, the dialog stays open and shows the message. See [checkout result types](/sdks/react/hooks#checkout-result-types).

## Data

`preview` holds the amounts shown in the dialog, in major units (dollars, not cents):

```tsx theme={null}
const preview: ProrationPreview = {
  credit: 14.5,
  debit: 49.5,
  net: 35,
  currency: 'USD',
  nextBillingDate: '2026-11-01T00:00:00Z',
}

export function UpgradeToScale() {
  return <UpgradeButton planCode="scale" label="Upgrade to Scale" preview={preview} />
}
```

### Live data

[`useUpgradePreview(planCode)`](/sdks/react/hooks#the-hooks) reads the quote for a plan change from your `billingEndpoint`. Its amounts are minor units and it has no separate credit and debit, so it does not fit `ProrationPreview`. Pass its `quote_id` as `quoteId`, and show its amounts in an [`UpgradeModal`](/sdks/react/components/upgrade-modal#live-data) you control, or use [`PlanChangeControl`](/sdks/react/components/plan-change-control), which shows the exact quote.

```tsx theme={null}
import { useSubscription, useUpgradePreview } from '@nozle-js/react'

export function UpgradeWithQuote() {
  const subscription = useSubscription()
  const quote = useUpgradePreview('scale')
  const refresh = useBillingRefresh()
  return (
    <UpgradeButton
      planCode="scale"
      subscriptionId={subscription.data?.subscription?.external_id}
      quoteId={quote.data?.quote_id}
      onUpgraded={() => void refresh()}
      onDowngradeScheduled={() => void refresh()}
    />
  )
}
```

## Examples

### The confirmation dialog

A click opens the dialog with the amounts from `preview`: credits applied, the new plan charge, the amount due today and the next billing date.

![The confirmation dialog with credits applied, new plan charge, amount due today and next billing date, light theme](https://mintcdn.com/nozle-d78f01d8/8jEvxrWAvqijYzbo/images/react/components/upgrade-modal/light.png?fit=max\&auto=format\&n=8jEvxrWAvqijYzbo\&q=85\&s=934f43558f713d0651d28c2360b05196)

```tsx theme={null}
const preview: ProrationPreview = { credit: 14.5, debit: 49.5, net: 35, currency: 'USD', nextBillingDate: '2026-11-01T00:00:00Z' }

export function UpgradeToScale() {
  return <UpgradeButton planCode="scale" label="Upgrade to Scale" preview={preview} />
}
```

## API reference

**planCode** `string` *required*

The plan to change to, sent to `createCheckout`.

**label** `string` (default: Upgrade)

Button text.

**preview** `ProrationPreview`

Amounts shown in the dialog, in major units: `credit`, `debit`, `net`, `nextBillingDate` and optional `currency` (defaults to `USD`). See [`UpgradeModal`](/sdks/react/components/upgrade-modal#api-reference).

**subscriptionId** `string`

The customer's external subscription ID, sent to `createCheckout` to change that subscription. Not sent when left out. `subscriptionId`, `quoteId` and `idempotencyKey` need React `0.10.0` or later.

**quoteId** `string`

A server-issued quote the customer saw, sent to `createCheckout`. Not sent when left out.

**idempotencyKey** `string`

Sent to `createCheckout`. Reuse the same key when retrying the same change. Not sent when left out.

**returnUrl** `string`

Sent to `createCheckout`. Defaults to the current URL.

**onStripeClientSecret** `(clientSecret: string) =\> void`

Fires for an embedded Stripe checkout and receives its client secret; render [`Checkout`](/sdks/react/components/checkout) with it. Without it the dialog closes and the secret is not used.

**onCheckoutStarted** `() =\> void`

Fires after a Stripe client secret was handed over. The dialog closes.

**onUpgraded** `() =\> void`

Fires when the change completed, or a Razorpay payment was captured. The dialog closes.

**onDowngradeScheduled** `() =\> void`

Fires for a `scheduled` result. The dialog closes.

**onError** `(error: Error) =\> void`

Fires when the change fails and receives the error. The dialog stays open and shows the message.

**className** `string`

Class name on the button.

**style** `CSSProperties`

Inline styles on the button.

**appearance** `Appearance`

Used for the button and the dialog. Defaults to the provider's. See [Appearance](/sdks/react/styling).

### States

| State | What shows |
| - | - |
| Closed | The button. |
| Open | The confirmation dialog, with the `preview` amounts when set. |
| Confirming | "Checking subscription…" on the dialog's confirm button. |
| Change failed | The message in the dialog, which stays open. |
| No `createCheckout` on the provider | "BillingProvider createCheckout callback is required for checkout" in the dialog after confirm. |

### Appearance

> **Element keys**
>
> `upgradeButton` (the button), and the dialog's `upgradeModal`, `upgradeModal__dialog`, `upgradeModal__actions`.
>
> Style them with `appearance.elements`. See [Elements](/sdks/react/styling#elements).

## Related

> **[UpgradeModal](/sdks/react/components/upgrade-modal)**
>
> The dialog on its own, with your open state.

> **[PlanChangeControl](/sdks/react/components/plan-change-control)**
>
> Plan picker with exact quotes and payment recovery.

> **[CheckoutButton](/sdks/react/components/checkout-button)**
>
> Checkout without a confirmation step.

> **[Checkout](/sdks/react/components/checkout)**
>
> The Stripe payment step.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.