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

# vetta plan & vetta credits

> The monthly plan, the prepaid balance, top-ups, and the usage ledger.

Two different things, and the order matters. The **plan** is the right to use the organization at all — without an active one every command outside billing is refused. **Credits** are the prepaid USD balance those commands then spend: every session debits the ledger as it runs, and a top-up credits it.

<Note>
  Organizations, members, API keys, and the audit trail moved to their own pages: [`vetta org`](/docs/cli/org), [`vetta keys`](/docs/cli/keys), and [`vetta audit`](/docs/cli/audit). There is **no `vetta billing` group** — the plan is `vetta plan`, the balance is `vetta credits`, and the card, the invoices and cancellation all live behind `vetta plan portal`.
</Note>

## Commands

| Command                | Description                                                            |
| ---------------------- | ---------------------------------------------------------------------- |
| `vetta plan show`      | Show the plan: status, period end, pending cancellation.               |
| `vetta plan subscribe` | Get the hosted checkout link for the monthly plan.                     |
| `vetta plan portal`    | Get the link to the hosted account page: card, invoices, cancellation. |
| `vetta credits show`   | Show the balance.                                                      |
| `vetta credits topup`  | Get a hosted checkout link.                                            |
| `vetta credits ledger` | List grants and charges.                                               |

## The plan

An organization starts with no plan, and a plan is what makes it usable: `GET /v1/agents`, `POST /v1/sessions` and everything else outside billing answer `402 subscription_required` until one is active. Creating an organization does not start one, and neither does a credit balance — a full balance with no plan is still refused.

The plan is **\$20 per month**, and each paid period also grants 20 USD of credit. So the plan buys the right to run; the credit it grants is what the running costs.

### plan show

```bash theme={"system"}
vetta plan show
```

```json theme={"system"}
{
  "object": "subscription",
  "status": "active",
  "current_period_end": "2026-09-22T17:30:00Z",
  "grace_until": null,
  "cancel_at_period_end": false,
  "action_url": null
}
```

| `status`   | Meaning                                                                              |
| ---------- | ------------------------------------------------------------------------------------ |
| `none`     | No plan has ever started. Every gated command is refused.                            |
| `active`   | The organization can be used until `current_period_end`.                             |
| `past_due` | The last payment did not go through. Still usable until `grace_until`, then refused. |
| `canceled` | The plan ended. Every gated command is refused.                                      |

`cancel_at_period_end` is `true` once a cancellation has been asked for: the organization stays usable until `current_period_end` and is refused after it. This command answers whether or not a plan exists, so it is always safe to run — it is the one thing a lapsed organization can still ask.

### plan subscribe

```bash theme={"system"}
vetta plan subscribe
```

```json theme={"system"}
{
  "object": "subscription",
  "status": "none",
  "current_period_end": null,
  "grace_until": null,
  "cancel_at_period_end": false,
  "action_url": "https://checkout.example/c/pay/cs_test_a1b2c3..."
}
```

`action_url` is a hosted checkout page. **Open it in a browser and pay it there** — a card cannot be typed into a terminal, so this is the one step the CLI hands back to you. Copy the URL whole; it is printed on one line and unwrapped for exactly that reason.

```bash theme={"system"}
vetta plan subscribe | jq -r .action_url     # just the URL, for `open`/`xdg-open`
```

<Warning>
  `subscribe` opens a checkout and changes **nothing** by itself. The plan becomes `active` only when the payment provider's signed callback lands — normally a second or two after you finish the page. The command does not wait for that: it cannot see whether you opened the URL, and blocking on a payment it does not control would be a lie about what it is doing. Run `vetta plan show` when you have paid.
</Warning>

Re-running `subscribe` while a plan is already active is harmless; it opens another checkout page you can simply not use. To cancel, use `vetta plan portal` below — `vetta plan` has no `cancel` command, and a cancellation takes effect at the end of the period already paid for either way.

### plan portal

```bash theme={"system"}
vetta plan portal
```

```json theme={"system"}
{
  "object": "billing_portal_session",
  "action_url": "https://billing.example/session/live_YWNjdF8..."
}
```

The one place the card on file, the past invoices and cancellation all live. Like `subscribe`, it hands back a URL for a browser: none of those three is a thing a terminal can do.

```bash theme={"system"}
vetta plan portal | jq -r .action_url        # just the URL, for `open`/`xdg-open`
```

The link is single-use and expires — run the command again rather than keeping one around. And like `subscribe` it changes nothing by itself: whatever you do on that page arrives back as a confirmed event a moment later, so run `vetta plan show` to see the result.

An organization that has never held a plan has no account to manage, and the command says so rather than opening an empty page:

```
$ vetta plan portal
error: not_found: this organization has no billing account to manage; start the plan with `POST /v1/credits/subscription` first (req_9k2m4p7q1w8x3v6z0b5n2c4t8r)
```

### When a command is refused

Any command on an organization with no plan fails like this, and names the command that fixes it:

```
$ vetta agent list
error: subscription_required: this organization has no active plan. Start or renew it with `POST /v1/credits/subscription` and follow `action_url`; the organization can be used again as soon as the payment is confirmed. (req_9k2m4p7q1w8x3v6z0b5n2c4t8r)
fix it with: vetta plan subscribe
```

The first line is unchanged and still leads with the `code`, so `case` statements that branch on it keep working; the remedy is a second line on stderr. Exit code is `1` — see [exit codes](/docs/cli/sessions#run-exit-codes).

## The balance

What the plan does *not* cover: every token an agent spends is debited from the prepaid balance below. `insufficient_credits` (402) means top up; `subscription_required` (402) means the plan above.

### show

```bash theme={"system"}
vetta credits show
```

```json theme={"system"}
{
  "object": "credit_balance",
  "balance_micro_usd": 79416537,
  "mode": "test"
}
```

`mode` is `test` for an `sk_test_…` credential and `live` for `sk_live_…`. A test-mode balance is not real money.

### topup

```bash theme={"system"}
vetta credits topup --usd 50
```

| Flag    | Description                                   |
| ------- | --------------------------------------------- |
| `--usd` | Amount as a decimal-dollar string (required). |

<Warning>
  `topup` opens a hosted checkout and credits **nothing** by itself. Only the verified payment callback moves money, so the balance does not change the moment this command returns. Poll `vetta credits show` if you need to wait for it to land.
</Warning>

### ledger

```bash theme={"system"}
vetta credits ledger --limit 2
```

```json theme={"system"}
{
  "data": [
    {
      "id": "led_35cwx4557pj3sr9wrsgbfnx7f3",
      "type": "debit",
      "amount_micro_usd": -124,
      "balance_after_micro_usd": 79416537,
      "actor": { "type": "key", "id": "key_5d50bxwbje7b5n4a8gpkpfak38" },
      "session_id": "ses_xq5542edbac2dssv3gm6atdcr8",
      "agent_id": "agt_kt88353jaw132sjakt4sytz4a6",
      "deployment_id": null,
      "line_items": [
        { "tier": "input", "amount_micro_usd": -114 },
        { "tier": "cache_write", "amount_micro_usd": 0 },
        { "tier": "cache_read", "amount_micro_usd": 0 }
      ]
    }
  ],
  "has_more": true,
  "next_cursor": "led_..."
}
```

| Flag                  | Description                  |
| --------------------- | ---------------------------- |
| `--type`              | `debit` \| `credit`.         |
| `--session`           | Attribute to one session.    |
| `--agent`             | Attribute to one agent.      |
| `--deployment`        | Attribute to one deployment. |
| `--from` / `--to`     | ISO-8601 date bounds.        |
| `--limit` / `--after` | Pagination.                  |

Each entry carries full attribution and a `line_items` breakdown by pricing tier, so a charge can always be traced to the run that caused it.

```bash theme={"system"}
vetta credits ledger --agent agt_kt88353jaw132sjakt4sytz4a6 --from 2026-08-01 --human
```

<Note>
  **Money is exact.** `--usd` takes a decimal-dollar string and is converted client-side to integer micro-USD. JSON output amounts are integer `*_micro_usd` (`1 USD = 1_000_000` micro-USD) so a script's arithmetic never rounds; `--human` renders dollars for reading.
</Note>

<Warning>
  A misspelled filter cannot silently widen a money query. `vetta credits ledger --sesion ses_…` exits `2` and lists the flags the command does take, rather than answering with the whole org's ledger.
</Warning>
