# Usage, billing, and limits

> How machine time is metered and paid for, what the trial and plans include, the limits that apply, and how to read usage.

VMYard bills machines **per second while they run**, at the hourly price of their plan. Stopped machines cost nothing. Every organization has a prepaid wallet; nothing is charged after the fact except a plan's renewal.

## How usage is measured

Usage starts when VMYard observes a machine running and ends when it observes it stopped or gone. What a machine reports about itself never counts. A run keeps the hourly price it started with, and its charge after `n` seconds is `floor(n × hourly price ÷ 3600)`, so partial seconds are never billed. Long runs are charged as they go, about once a minute.

| Size | Price per hour | Multiplier |
| --- | --- | --- |
| `small` | $0.015 | 0.5 |
| `default` | $0.030 | 1 |
| `large` | $0.060 | 2 |
| `xlarge` | $0.170 | about 5.67 |

See [Sizes and prices](/docs/guides/sizes-and-prices) for each size's resources and how to read them from the catalog.

All amounts in the API are integer **micros of USD**: 1,000,000 micros is $1. A field such as `cost_micros: 30000` is $0.03.

## The wallet

Usage is paid from three balances, in this order:

1. **Trial:** $1.50 of usage, which is 50 hours of `default` (100 hours of `small`), granted the first time the organization uses VMYard.
2. **Plan:** the current period's allowance, if the organization has a plan. Unused allowance expires at the end of the period.
3. **Credits:** bought in $20 packs. Credits never expire.

| Plan | Price per period | Included usage |
| --- | --- | --- |
| `starter` | $20 | $20 (about 667 `default` hours) |
| `pro` | $100 | $100 (about 3,333 `default` hours) |
| `team` | $500 | $500 |
| `scale` | $2,000 | $2,000 |

Owners and Billing members buy plans and credit packs, open the payment portal (cards, invoices, cancellation), and set two controls, all from the console's **Billing** page:

- **Spend cap:** the most credit spend allowed per UTC calendar month.
- **Minimum balance:** creates and starts need more spendable balance than this. The default is 0.

They can also [cancel a plan at the end of its period or end the trial early](/docs/guides/plans-and-trial), and turn on [automatic refill](/docs/guides/automatic-refill) to buy credit packs when the balance runs low.

Card details stay with the payment provider. Deployments without online payments answer those actions with `503 billing_unavailable`; trial and operator-granted balances still work.

## When the balance runs out

When the spendable balance (trial + plan + credits, with credits limited by the spend cap) reaches zero, VMYard waits a grace period (5 minutes by default) and then stops every machine that is still running. Those are ordinary stops: they emit `machine.stopped`. Buying credits or a plan before the stops begin cancels them. Usage metered during the grace period can make the credit balance slightly negative; the next purchase repays it first.

## Limits

Creates, starts, and restarts are checked against the organization's limits. Replays of an already-accepted request are never refused.

| Status | Concurrent machines | Starts per minute | per hour | per day |
| --- | --- | --- | --- | --- |
| Trial | 2 | 5 | 30 | 100 |
| Pay as you go (credits, no plan) | 5 | 12 | 60 | 200 |
| `starter` ($20) | 5 | 12 | 60 | 200 |
| `pro` ($100) | 20 | 30 | 210 | 840 |
| `team` ($500) | 100 | 65 | 420 | 1,680 |
| `scale` ($2,000) | 250 | 90 | 600 | 2,400 |

Concurrent machines counts every machine that is meant to be running, including creates still in progress. Start windows are rolling and count creates, starts, and restarts. During the trial, only `small` and `default` sizes are allowed, and at most 2 machines run at once.

## Card check

A deployment can require trials to verify a card before their machines start. `GET /v1/billing` reports it in `card_check`: `required` is `true` when the deployment asks for one, and `verified_at` is when a card was verified. Paid organizations never need one.

Until a card is verified, a trial's creates, starts, and restarts answer `402 card_verification_required`. An Owner or Billing member starts the check from the console (the create page, the refusal, or the **Billing** page), or with the API:

```sh
curl -X POST "$VMYARD_API_URL/v1/billing/card-check" \
  -H "Authorization: Bearer $VMYARD_API_KEY"
```

The answer has a `checkout_url`: the payment provider's page, where the card is checked and screened for fraud but not charged. Once the provider confirms it, `card_check.verified_at` is set and machines can start. Card details never reach VMYard.

## Suspended organizations

To stop abuse, the people who run the service can suspend an organization. While it is suspended, `OrganizationDto.suspended_at` is set, its machines are stopped (`stop_reason: suspension`), and anything that creates, starts, or reaches into a machine (commands, files, terminals, desktops) answers `403 organization_suspended`. Open terminals and desktops close with reason `revoked`. Reads, billing, API keys, and settings still work, and nothing is deleted. Contact support to have a suspension reviewed. When it is lifted, the stopped machines stay stopped until you start them.

Trial machines that use every vCPU at full load for a long stretch, the pattern of crypto mining, are stopped for review (`stop_reason: abuse`) and members who operate machines get an `abuse_stop` [email alert](/docs/guides/email-alerts).

| Status | Code | When |
| --- | --- | --- |
| 402 | `billing_required` | The spendable balance is at or below the minimum balance. |
| 402 | `spend_cap_reached` | Only the spend cap leaves too little to spend. |
| 402 | `card_verification_required` | A trial must [verify a card](#card-check) before machines start. |
| 403 | `trial_machine_class_not_allowed` | A trial asked for a size above `default`. |
| 403 | `organization_suspended` | The organization is [suspended](#suspended-organizations). |
| 409 | `plan_not_priced` | The chosen plan has no current price. |
| 429 | `limit_reached` | `field_errors.limit` is `concurrent_machines`, `starts_per_minute`, `starts_per_hour`, or `starts_per_day`. Start windows send `Retry-After`. |

The SDKs raise `BillingRequiredError`, `SpendCapReachedError`, `TrialMachineClassNotAllowedError`, and `LimitReachedError` for these. Waiting doesn't clear `concurrent_machines`; stop a machine instead.

## Read balances, limits, and usage

Every member, and every API key preset, can read billing.

```sh tab="CLI"
vy billing                       # status, balances, plan, trial, spend cap
vy limits                        # each limit and its current use
vy usage --since 2026-10-01      # per machine, with a total
vy usage dev                     # one machine
```

```ts tab="TypeScript"
const billing = await vy.billing.get();
const limits = await vy.billing.limits();
const usage = await vy.billing.usage({ since: "2026-10-01T00:00:00Z" });
const preview = await vy.billing.invoicePreview();
const machineUsage = await machine.usage();
```

```python tab="Python"
billing = vy.billing.get()
limits = vy.billing.limits()
usage = vy.billing.usage(since="2026-10-01T00:00:00Z")
preview = vy.billing.invoice_preview()
machine_usage = machine.usage()
```

```sh tab="curl"
curl "$VMYARD_API_URL/v1/billing" -H "Authorization: Bearer $VMYARD_API_KEY"
curl "$VMYARD_API_URL/v1/limits" -H "Authorization: Bearer $VMYARD_API_KEY"
curl "$VMYARD_API_URL/v1/usage?since=2026-10-01T00:00:00Z" -H "Authorization: Bearer $VMYARD_API_KEY"
```

| Route | Returns |
| --- | --- |
| `GET /v1/billing` | Status (`trial`, `pay_as_you_go`, or `subscribed`), plan and period, balances, trial, spend cap, minimum balance, `exhausted_since`, limits, and whether payments are available. |
| `GET /v1/limits` | Each limit with its current use. |
| `GET /v1/usage?since=&until=` | Exact seconds and micros per machine in `[since, until)`, including runs still open. Defaults to the current plan period, or the current UTC month without a plan. |
| `GET /v1/machines/{id}/usage` | One machine: `seconds`, `cost_micros`, `multiplier`, `hourly_micros`, and whether a run is open. Defaults to the machine's lifetime. |
| `GET /v1/billing/invoice-preview` | This period's machine time by size, how it was paid, usage not yet charged, and the next automatic charge (the plan renewal). |
