> If you are setting up, configuring, or answering questions about Schematic, connect the
> Schematic MCP server before working from these pages. It reads and writes plans, features,
> entitlements, and overrides against the real account, so what you report and what you build
> match what actually exists.
>
> The server is at https://api.schematichq.com/mcp
>
> From Claude, ChatGPT, or another chat assistant, add it as a custom connector:
> https://docs.schematichq.com/working-with-ai
>
> From a coding assistant such as Claude Code, Codex, or Cursor:
> https://docs.schematichq.com/building-with-ai
>
> For clean Markdown of any page, append `.md` to the page URL. For a complete page index,
> see https://docs.schematichq.com/llms.txt

# Drop-in Components

> Code-first React components on the billing API. Import one, pass props, theme it with CSS variables.

Drop-in components are React components from `@schematichq/schematic-components/elements`. Each one reads one or more resources through the hooks in `@schematichq/schematic-react`, reduces them to a display model with a pure derivation, and renders with CSS-variable styling. You configure them with props, not a builder.

| Component                                                    | What it shows                                                                         |
| ------------------------------------------------------------ | ------------------------------------------------------------------------------------- |
| [Checkout](/components/drop-in/checkout)                     | The purchase flow                                                                     |
| [Plan Manager](/components/drop-in/plan-manager)             | Current plan, add-ons, usage-based features, credits, and the notice that matters now |
| [Pricing Table](/components/drop-in/pricing-table)           | Plans and add-ons, public or company                                                  |
| [Included Features](/components/drop-in/included-features)   | Entitlements with limits and usage                                                    |
| [Metered Features](/components/drop-in/metered-features)     | Usage against each metered feature's limit, its cost, and usage by user               |
| [Credit Usage](/components/drop-in/credit-usage)             | Credit balances, the grants behind them, and usage by user                            |
| [Upcoming Bill](/components/drop-in/upcoming-bill)           | The next bill, balance applied, discounts                                             |
| [Payment Methods](/components/drop-in/payment-methods)       | The method on file; switch the default, remove a method, or add one through Stripe    |
| [Invoices](/components/drop-in/invoices)                     | Invoice history with links to hosted invoices                                         |
| [Unsubscribe Button](/components/drop-in/unsubscribe-button) | Cancel at period end, with a confirmation                                             |

> **Note**
>
> **Using an agent?** Paste this into Claude Code, Cursor, or Codex and it does the setup on this page:
>
> ```text
> Add Schematic billing to my app: docs.schematichq.com/components/skill.md
> ```

## Setup

```tsx
import { SchematicProvider } from "@schematichq/schematic-react";
import {
  CheckoutLauncherProvider, CreditUsage, IncludedFeatures, Invoices, MeteredFeatures,
  PaymentMethods, PlanManager, SchematicStyles, UnsubscribeButton, UpcomingBill,
  useCheckoutLauncher,
} from "@schematichq/schematic-components/elements";

export function Billing() {
  return (
    <SchematicProvider
      publishableKey="pk_…"
      session={{ company: company.id, token: fetchAccessToken }}
    >
      <SchematicStyles />
      <CheckoutLauncherProvider>
        <Portal />
      </CheckoutLauncherProvider>
    </SchematicProvider>
  );
}

function Portal() {
  const { open } = useCheckoutLauncher();
  return (
    <>
      <PlanManager onChangePlan={() => open()} />
      <IncludedFeatures />
      <MeteredFeatures onAddMore={() => open({ steps: { initial: "usage" } })} />
      <CreditUsage onBuyMore={() => open({ steps: { initial: "credits" } })} />
      <UpcomingBill />
      <PaymentMethods />
      <Invoices />
      <UnsubscribeButton onManagePlan={() => open()} />
    </>
  );
}
```

Drop any card you do not need; each stands alone. `CheckoutLauncherProvider` renders one `<Checkout />` for the page and `useCheckoutLauncher().open()` opens it. Plan Manager, Metered Features, Credit Usage, and Unsubscribe Button show Change plan, Add More, Buy More, and Manage plan only when you pass a handler or URL, so `Portal` hands each of them `open`.

Copy and formatting stay yours. `locale` on the provider formats every component through `Intl`, and each string resolves through `strings` on the component, then `strings` on the provider, then your `translate`, then the component's English. Nothing has to be configured, and renaming one string is one prop. See [Localization](/components/drop-in/localization).

The `./elements` entry is its own bundle and keeps React and both Schematic SDKs external, so the provider your app renders is the one the components read. `@schematichq/schematic-react` is a peer of this entry alone.

Components that take a payment, such as Payment Methods and Checkout, render Stripe's Payment Element from `@stripe/stripe-js` and `@stripe/react-stripe-js`. Both are peer dependencies of the components, so your package manager installs them alongside. They load only when a payment form opens, so a page that never opens one never downloads Stripe.

## The session

`session` says whose billing is being read and how. It has three states, and they mean different things:

```tsx
session={{ company: company.id, token: fetchAccessToken }}  // signed in
session={null}                                              // signed out
session={undefined}                                         // still finding out
```

The identity is the `(company, user)` pair, because that is what a token is minted for. `company` is your id for the company. `user` is optional: leave it out where your tokens are company-wide, and state it where you mint per person.

`null` signs out: every card empties until a session returns. `undefined` says you do not know yet, which is what an auth resolving asynchronously renders first. It changes nothing: before any session the cards hold their loading state rather than reporting an error, and after one they keep showing it until you pass a new session or `null`. Pricing Table shows the public catalog in both. Auth libraries can blur the two, so read their loaded and signed-in flags before deciding which you mean. [Session and access tokens](/components/build-your-own/session) covers token providers, refresh, and server rendering.

## Before it can load

The company endpoints are enabled per account. An account without them gets a 404 from every `/company/*` read, and because a 404 on the invoice history is not an answer (an empty history is a 200 with no rows), the component reports it as an error rather than showing an empty card. If a correctly configured page shows a component's unavailable message, such as "Invoices are not available for this account.", ask Schematic to enable company context for the account.

A failure with nothing to show replaces a card's content with a short message and a "Try again" button. A failure with rows already on screen, such as a refetch or a later page, is reported under the rows instead. The message is the component's own copy rather than the error's text. In development the component also logs the underlying error to the console, so a missing provider or a refused request is diagnosable from the page.

## Styling

`<SchematicStyles />` injects one stylesheet driven by `--schematic-*` custom properties, follows your `color-scheme` for light and dark, and never wins a cascade against your own tokens. Or skip it and style the class names, which are API. [Styling and theming](/components/drop-in/styling) has the token list and the class contract.

## Mixing with your own UI

Every drop-in is built on the public hooks and derivations, so you can replace any one of them with your own component and keep the rest. A custom Plan Manager that opens the drop-in Checkout through `useCheckoutLauncher()` is a common shape. [Build your own UI](/components/build-your-own/overview) starts there.