# Subscription status

Where the subscription stands: plan, seats paid against seats used, the card on file, and when it renews or ends. A failed payment says what failed and what happens next; a cancellation says when access ends and how to keep the plan. Billing changes happen in Stripe's portal, linked here.

- Registry name: `subscription-status` (`@candor/subscription-status`)
- Tier: Pro. Installing it needs a Pro, Premium or Team licence key: the person runs `npx candor-ui key <key>` themselves; never ask for the key in chat or write it to a file.
- Docs: https://candor.themethodic.com/docs/subscription-status

## Install

```bash
npx candor-ui add subscription-status
```

Run `npx candor-ui@latest init` once first (https://candor.themethodic.com/get-started.md). Without the CLI: `npx shadcn@latest add @candor/subscription-status`.
It brings in: badge, button, locale, ops, utils.
npm packages: lucide-react@^1.67.0.

## Example

```tsx
"use client"

import { SubscriptionStatus } from "@/components/subscription-status"
import type { PlanTier, Subscription } from "@/lib/ops"

const plan: PlanTier = { id: "enterprise", name: "Enterprise", perSeat: 499, tagline: "Everything in Team, plus people behind it", includes: [] }

const sub: Subscription = { plan: "enterprise", seats: 8, seatsUsed: 6, status: "active", periodEnd: "2026-11-24", card: { brand: "Visa", last4: "4242", expires: "08/28" } }

export default function Example() {
  return <SubscriptionStatus className="max-w-xl" sub={sub} plan={plan} onManage={() => {}} />
}
```

## <SubscriptionStatus>

Props:

- `sub: Subscription`: The subscription: status, seats, period end, card and any billing issue.
- `plan: PlanTier`: The subscribed plan, for its name and per-seat price.
- `onManage?: (() => void) | undefined`: Opens Stripe's customer portal.
- `onKeep?: (() => void) | undefined`: Undo a pending cancellation.
- `retention?: string | undefined`: What's kept after access ends, from the service's retention policy. Omitted when unknown.
- `label?: string | undefined`: The section's accessible name; set it when two are on one page.
- `className?: string | undefined`

## Strings (`subscriptionStatus`)

The fixed words, English by default. Override any of them under `subscriptionStatus` in `<LocaleProvider strings={{ subscriptionStatus: { … } }}>`; the table is exported as `subscriptionStatusStrings`.

- `label`: Subscription
- `statusActive`: Active
- `statusPastDue`: Payment failed
- `statusCanceling`: Ends soon
- `statusCanceled`: Ended
- `lastPaymentFailed`: The last payment failed.
- `price`: ${perSeat} / seat / month · ${total} a month
- `accessEnds`: Access ends on {date}.
- `endedOn`: Ended on {date}.
- `renewsOn`: Renews on {date}.
- `keep`: Keep {plan}
- `updatePayment`: Update payment
- `manageBilling`: Manage billing
- `seats`: Seats
- `seatsUsed`: {used} used of {total}
- `overSeats`: {count} more members than seats; the next invoice trues up.
- `cardEnding`: {brand} ending {last4}
- `cardExpires`: · expires {expires}
- `noCard`: No card on file

## Rules for using Candor UI

- Components take plain typed data. Never pass model output as HTML or render it as a link; messages are typed blocks.
- A control that can't be used says why: wrap it in `<Locked reason="…">`, don't just disable it.
- Don't show a value you don't have: leave it out (it renders as —) rather than guess. An estimate is labelled as one.
- Nothing is pre-selected in a decision a person makes, and the agent is named from your app's data, never from model output.
- Your app's words go in `LocaleProvider` (fixed strings) and `TermsProvider` (nouns); entity kinds and agent roles in `EntityKindsProvider` and `AgentRolesProvider`.
