---
title: "What changing plan would do, and cost today"
description: "Admins only."
canonical: "https://grid82.com/docs/builder-api/billing/preview"
updated: "2026-11-13"
---

# What changing plan would do, and cost today

`POST https://studio.grid82.app/v1/organizations/{organizationId}/billing/preview`

Admins only.

Changes nothing. Says whether the change is immediate (an upgrade, charged now and prorated, with Stripe's own figure for today), scheduled for the end of the paid period (a downgrade), or needs a checkout (no subscription yet). Refused with 501 while billing is not connected.

Requires the `account:read` scope. Operation `billing.preview`. MCP tool `billing_preview`. CLI: `grid82 billing preview` (`npx grid82`).

## Path parameters

| Name             | Type   | Required | Description |
| ---------------- | ------ | -------- | ----------- |
| `organizationId` | string | yes      |             |

## Headers

| Name              | Type   | Required | Description                                                                                                                                                                                                                                                        |
| ----------------- | ------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `Idempotency-Key` | string | no       | Any unique string. Sending the same key with the same request again returns the first response (marked `Idempotency-Replayed: true`) instead of running it twice. Reusing it for a different request is refused with 409. Kept for 24 hours. Up to 255 characters. |

## Request body

| Field      | Type                                     | Required | Description          |
| ---------- | ---------------------------------------- | -------- | -------------------- |
| `plan`     | "free" or "starter" or "pro" or "custom" | yes      |                      |
| `interval` | "monthly" or "yearly"                    | no       | Default `"monthly"`. |

**Authorizations**

- `Authorization` (bearer, in header, required)

## Response

**200**: Success

- `data` (`object`, required)
- `data.kind` (`enum<string>`, required, one of: `first_subscription, upgrade_immediate, downgrade_scheduled`)
- `data.plan` (`enum<string>`, required, one of: `free, starter, pro, custom`)
- `data.interval` (`enum<string>`, required, one of: `monthly, yearly`)
- `data.effectiveImmediately` (`boolean`, required)
- `data.effectiveAt` (`string,null`, required)
- `data.amountDueToday` (`number,null`, required)
- `data.currency` (`string,null`, required)
- `data.breakdown` (`object | null`, required)
- `data.breakdown.unusedCredit` (`number`, required)
- `data.breakdown.newCharge` (`number`, required)
- `data.breakdown.tax` (`number`, required)

```json
{
  "data": {
    "kind": "first_subscription",
    "plan": "free",
    "interval": "monthly",
    "effectiveImmediately": true,
    "effectiveAt": null,
    "amountDueToday": null,
    "currency": null,
    "breakdown": {
      "unusedCredit": 123.45,
      "newCharge": 123.45,
      "tax": 123.45
    }
  }
}
```

**4XX**: Refused

- `error` (`object`, required)
- `error.code` (`enum<string>`, required, one of: `not_found, forbidden, unauthenticated, validation_failed, conflict, rate_limited, payment_required, not_implemented, internal`)
- `error.message` (`string`, required)
- `error.details` (`Record<string, unknown>`)

```json
{
  "error": {
    "code": "not_found",
    "message": "<string>",
    "details": {}
  }
}
```

**Example request**

```bash
curl --request POST \
  --url 'https://studio.grid82.app/v1/organizations/<organizationId>/billing/preview' \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '{
  "plan": "free"
}'
```
