# Billing

The organization's plan, usage, and limits. How sandbox time is counted is on [Sandbox time and plans](/docs/cloud/plans). `:id` and `organization_id` are the organization's ID.

## The account object

| Field                     | Meaning                                                                                      |
| ------------------------- | -------------------------------------------------------------------------------------------- |
| `organization_id`         |                                                                                              |
| `plan`                    | `id`, `version`, `name`, `monthly_usd`, `comped`.                                            |
| `subscription_status`     | The subscription's status, or null.                                                          |
| `cancel_at`               | When a cancellation at the period end takes effect, or null.                                 |
| `scheduled_change`        | `{ "plan_id", "at" }` for a switch held to the period end, or null.                          |
| `payment_method`          | Whether a payment method is on file.                                                         |
| `payment_method_required` | Whether cloud runs need one.                                                                 |
| `period`                  | `start`, `end` of the current allowance period.                                              |
| `hours`                   | `used`, `included` (a number or `"unlimited"`), `remaining` (or null).                       |
| `overage`                 | `rate_usd_per_hour` (or null), `hours`, `usd`, `projected_hours`, `projected_usd`.           |
| `spend_limit`             | `usd` (a number or `"unlimited"`) and `source`: `override`, `organization`, or `plan`.       |
| `members`                 | `used`, `limit` (a number or `"unlimited"`).                                                 |
| `private_workbenches`     | `used`, `limit`.                                                                             |
| `override`                | Limits set by workbenches.dev for the organization, with `reason` and `expires_at`, or null. |

## Get the account

`GET /v1/billing/accounts/:id`

Key `catalog:read`, or session: member. Response `200`: the account.

## Set the spend limit

`PATCH /v1/billing/accounts/:id` with `{ "spend_limit_usd": 100 }`

An owner or admin, by session or key. The monthly overage spend limit in dollars, at least 0. Response `200`: the account.

## Checkout

`POST /v1/billing/checkouts`

An owner or admin, by session or key. Starts Stripe Checkout:

| Body                                                       | Purpose                        |
| ---------------------------------------------------------- | ------------------------------ |
| `{ "mode": "subscription", "organization_id", "plan_id" }` | Upgrade to a public paid plan. |
| `{ "mode": "setup", "organization_id" }`                   | Add a card.                    |

Response `201` `{ "url" }`: send the customer there. Checkout is refused while a subscription is live; use the portal or a plan switch instead.

### Return from checkout

`POST /v1/billing/checkouts/returns` with `{ "organization_id", "session_id": "cs_..." }`

An owner or admin. Applies the Checkout session's subscription now and returns the account, so a paid organization never sees Free.

## Customer portal

`POST /v1/billing/portals` with `{ "organization_id" }`

An owner or admin. Response `201` `{ "url" }` to the Stripe customer portal: cards, invoices, and cancellation at the period end. The portal does not switch plans.

## Switch plans

### Preview a switch

`POST /v1/billing/plans/previews` with `{ "organization_id", "plan_id" }`

An owner or admin. Changes and charges nothing. Response `200`:

| Field                                    | Meaning                                             |
| ---------------------------------------- | --------------------------------------------------- |
| `effect`                                 | `now` for an increase, `period_end` for a decrease. |
| `due_now_usd`                            | What is charged now.                                |
| `current_monthly_usd`, `new_monthly_usd` | Both monthly prices.                                |
| `takes_effect_at`                        | When the switch applies.                            |
| `next_invoice_at`                        |                                                     |
| `proration_date`                         | Pass it to the switch, or null.                     |

### Switch

`POST /v1/billing/plans` with `{ "organization_id", "plan_id", "proration_date" }`

An owner or admin, for a paying organization. An increase applies at once and invoices the prorated difference shown by the preview; a `proration_date` older than 15 minutes is refused with a request to review again. A decrease is held until the period ends. Response `200`: the account plus `effect` (`now` or `period_end`).

## Plan limits

Enforcement refuses with 402 `plan_limit` and a message naming the limit and the upgrade path:

- `POST /v1/runs` without a payment method, with no sandbox time left, past the spend limit, or with a `max_minutes` longer than the time available.
- `POST /v1/invitations` and `POST /v1/acceptances` at the member cap.
- `POST /v1/versions` for a new Workbench at the private Workbench cap.
