# Plans, add-ons, and upgrades

> How a coding agent drives a Tarout plan upgrade end to end, including the Moyasar checkout and polling loop

# Plans, add-ons, and upgrades

> **Preflight - check auth first.** Run `tarout whoami --json`. If it does not
> return `success: true`, authenticate with the table in
> [start.md](https://tarout.sa/docs/for-ai/start.md)
> before running anything on this page - every command below fails without a
> credential, and the failure reads like a broken deploy rather than a missing
> login.

For a brand-new customer this *is* the onboarding journey: pick plan → confirm →
pay → activate. The CLI is built so you can drive it without a human at the
keyboard, except for the card-entry step itself.

**The checkout page IS the user's approval.** Completing payment is consent;
closing the page is refusal. Do not pre-ask in chat, and do not stall the deploy
waiting for a decision - tell the user you are opening checkout, then run it.

The **free plan needs no credit card**: one app, one database, one bucket. Most
first deploys never reach this page.

## When you land here

Either `tarout up` returned:

```json
{ "success": false, "error": { "code": "NEEDS_UPGRADE", "message": "...", "details": { "suggestedPlan": "shared" } } }
```

or another command returned `FORBIDDEN` with a "Plan limit reached" message.
**Do not silently retry.**

## Run the upgrade

Pass the plan and extras as flags so no `needs_input` event fires:

```sh
tarout billing upgrade --json --yes \
  --plan <planKey> \
  --billing-period monthly \
  --addon db.standard:1 \
  --addon storage.gb:10
```

- `--plan` is an alias for the positional argument - use either.
- `--billing-period` is `monthly` or `yearly` (yearly = 10× monthly, two months free).
- `--addon <key>[:qty]` is repeatable; quantity defaults to `1`.
- Object storage capacity is the `storage.gb` add-on, where the quantity is the
  number of GB for the whole project (0.12 SAR per GB per month). The older
  `storage.starter`, `storage.standard`, and `storage.pro` add-ons are retired;
  do not pass them.
- `--yes` skips the "Switch to plan X?" confirm. Drop it if you want the CLI to
  emit a `needs_input` event and confirm with the user first.

`billing upgrade` **waits by default** - it opens the payment page and polls to
completion. Pass `--no-wait` for the early-return flow below, or `--no-open` to
stop the CLI launching the browser itself (when you open it instead).

## Result envelopes

| Envelope | Meaning |
|---|---|
| `{ applied: true, status: "applied" }` | Free upgrade, or a stored card on file. Nothing further to do. |
| `{ status: "paid", paidAt: "..." }` | Default path: page opened, user paid, change applied. Retry the blocked command. |
| `{ status: "deferred" }` | Downgrade staged for the end of the period. |
| `{ status: "payment_required", paymentUrl, orderId }` | Only with `--no-wait`. Open `paymentUrl` for the user, keep `orderId`, then poll. |

## Polling an open order

```sh
tarout billing wait <orderId> --json --timeout 600
```

Streams newline-delimited events:

```json
{ "type": "event", "event": "checkout_status", "orderId": "...", "status": "PENDING" }
{ "type": "event", "event": "checkout_status", "orderId": "...", "status": "PAID" }
```

The final envelope is `{ success: true, data: { status: "paid", paidAt: "..." } }`
on success, or `{ success: false, error: { code: "CHECKOUT_FAILED" |
"CHECKOUT_EXPIRED" | "CHECKOUT_TIMEOUT" } }` on failure. Once paid, **retry the
original blocked command.**

## Headless escape hatch

For test runs and CI with mock payments:

```sh
ORDER_ID=$(tarout --json billing upgrade --plan <plan> --yes --no-open | jq -r '.data.orderId')
tarout --json billing confirm "$ORDER_ID"
```

If you are fully unattended and never want the CLI to try its own browser launch
or TTY fallback, layer `--non-interactive` on top of `--json`:

```sh
tarout --json --non-interactive billing upgrade --plan <plan> --yes --billing-period monthly
```

## AI Gateway usage

The AI Gateway is not a plan or an add-on. It is billed per token in SAR from
the organization's prepaid wallet. One gateway key calls every model in the
catalog, and each request picks its model with the `model` field, so there is
no need to create a key per model. To cap what a key can spend, give it a
monthly credit limit in SAR:

```sh
tarout wallet balance
tarout ai models
tarout ai keys create --name production --monthly-cap 50
```

## Other commands

```sh
tarout billing status
tarout billing plans
tarout billing confirm <orderId>
tarout billing wait <orderId> [--timeout 600]
tarout wallet balance                    # AI Gateway wallet, separate from plans
```

---

## Every Tarout agent guide

- [Start Here (Agents)](https://tarout.sa/docs/for-ai/start.md)
- [Overview](https://tarout.sa/docs/for-ai.md)
- [Deploying an app](https://tarout.sa/docs/for-ai/deploy.md)
- [Databases](https://tarout.sa/docs/for-ai/database.md)
- [Object storage](https://tarout.sa/docs/for-ai/storage.md)
- [Custom domains](https://tarout.sa/docs/for-ai/domains.md)
- [Troubleshooting](https://tarout.sa/docs/for-ai/troubleshoot.md)
- [Agent Onboarding](https://tarout.sa/docs/for-ai/onboarding.md)
- [CLI Reference](https://tarout.sa/docs/for-ai/cli-reference.md)
- [CLI JSON Schema](https://tarout.sa/docs/for-ai/cli-json-schema.md)

Whole corpus in one file: https://tarout.sa/llms-full.txt · index: https://tarout.sa/llms.txt
Any docs page is raw markdown at the same URL + `.md`. Short link to the entry point: https://tarout.sa/deploy.md
