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

# Subscriptions

> The binding between a tenant and a plan.

A **Subscription** is the record that links a tenant to a plan. It tracks billing periods, payment status, trial dates, and seat counts. Every status change is recorded to an immutable event log.

## Subscription Statuses

| Status           | Description                                                                                                                                |
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| `pending`        | Created but not yet activated (awaiting payment confirmation)                                                                              |
| `trial`          | In a free trial period                                                                                                                     |
| `active`         | Paid and active                                                                                                                            |
| `past_due`       | Payment failed — grace period                                                                                                              |
| `pending_cancel` | Cancellation requested; access continues until `currentPeriodEnd`                                                                          |
| `canceled`       | Canceled. For manual billing subscriptions, this is set immediately on cancellation; for recurring subscriptions, it is set at period end. |
| `expired`        | Trial or subscription ended without renewal                                                                                                |

## Status Transitions

```mermaid theme={null}
flowchart LR
    pending --> trial --> active --> past_due --> canceled
    pending --> active
    past_due --> expired
    active --> pending_cancel --> canceled
```

Transitions are triggered by Stripe webhook events or explicit API calls:

| Event / Action                                     | Transition                                         |
| -------------------------------------------------- | -------------------------------------------------- |
| `checkout.session.completed`                       | `pending` → `active` or `trial`                    |
| `customer.subscription.updated`                    | `trial` → `active`                                 |
| `invoice.payment_failed`                           | `active` → `past_due`                              |
| `customer.subscription.deleted`                    | any → `canceled`                                   |
| `POST /subscriptions/{id}/cancel` (recurring)      | `active` / `trial` / `past_due` → `pending_cancel` |
| `POST /subscriptions/{id}/cancel` (manual billing) | `active` / `trial` / `past_due` → `canceled`       |

## Subscription Fields

```json theme={null}
{
  "id": "sub_crovver_abc123",
  "status": "active",
  "tenantId": "ten_xyz",
  "planId": "plan_pro",
  "trialEndsAt": null,
  "currentPeriodStart": "2025-01-01T00:00:00Z",
  "currentPeriodEnd": "2025-02-01T00:00:00Z",
  "canceledAt": null,
  "capacityUnits": 15,
  "usedCapacity": 12,
  "providerSubscriptionId": "sub_stripe_...",
  "providerCustomerId": "cus_stripe_..."
}
```

## Event Sourcing

Every subscription status change is written to `subscription_events`. This gives you a complete audit trail:

```json theme={null}
{
  "event_type": "subscription.activated",
  "previous_status": "trial",
  "new_status": "active",
  "occurred_at": "2025-02-01T00:00:00Z",
  "metadata": {
    "stripe_event_id": "evt_...",
    "invoice_id": "in_..."
  }
}
```

## Checking Subscription Status

Use the React SDK hook on the frontend:

```tsx theme={null}
import { useSubscription } from 'crovver-react';

function Dashboard() {
  const { isActive, plan, subscription } = useSubscription();

  if (!isActive) return <UpgradePrompt />;

  return <App trialEndsAt={subscription?.trialEndsAt} />;
}
```

Or query the API from your backend:

```bash theme={null}
GET /api/public/subscriptions/status?publicKey=pk_live_...&tenantId=workspace_123
```
