# Billing & quotas

> **For agents:** `get_usage(org="acme")` (exact daily accepted events, plan, overage flag, credit balance), `get_billing_plans(org="acme")` (catalog + whether checkout is configured), `set_overage(org="acme", enabled=true)` (`org:admin`, audited). Upgrades happen in the dashboard — there is no checkout tool.

## One meter

1 error = 1 event, 1 transaction = 1 event. Spans, sessions, breadcrumbs, and client reports are free. There is no per-seat pricing for viewers.

| Plan | Price / month | Events included | Retention | Billable members | Overage (per 100k events) |
|---|---|---|---|---|---|
| Free | $0 | 100,000 | 30 days | 3 (5 projects) | not available |
| Starter | $29 | 1,000,000 | 90 days | 15 | $5.00 |
| Team | $79 | 5,000,000 | 90 days | 40 | $5.00 |
| Business | $249 | 20,000,000 | 90 days | 100 | $3.00 |
| Scale | $499 | 50,000,000 | 90 days | 250 | $2.00 |

Paid plans have unlimited projects. Viewers are unlimited everywhere.

## Exact metering

Accepted events are counted by a per-organization Durable Object (`OrgQuota`) and flushed to the control database as `usage_daily` rows by category — this is the number on the usage page and the invoice. The sampled analytics index is never used for billing. Filtered events, SDK-side drops (client reports), and rate-limited events are recorded as outcomes for transparency but are not billed.

`GET /v1/orgs/{org}/usage` returns the plan, `overageEnabled`, `daily[]` (`date`, `category`, `accepted`) for the last 31 days, and `credits` (balance, entries with expiry, last invoice application, and `appliesToInvoices` / `notAppliedReason`: whether anything can deduct them).

## Hard cap versus overage

- **Default: hard cap.** When the period's accepted events reach the plan allowance plus a 10% grace, the quota object writes a flag that ingest reads; further envelopes get `429` with `X-Sentry-Rate-Limits` and `Retry-After`, and SDKs back off. Nothing is billed beyond the plan.
- **Overage opt-in** (`POST /v1/orgs/{org}/billing/overage {"enabled": true}`, `org:admin`): the flag is never written; events above the allowance are billed at the plan's overage rate. Free has no overage.
- Counters reset on the organization's billing anchor day (nightly job).

## Credits

Credits (launch, migration, startup programs) live in a ledger and apply automatically on invoice creation:

- Cover at most **50% of any invoice**, across all credits combined; individual credits may carry a lower per-credit percentage.
- Never apply to tax — only the pre-tax subtotal.
- Active balance is capped at **$1,000** per organization; grants clamp to the room left.
- Drawn FIFO by nearest expiry. The balance and expiry dates are visible in `get_usage` and on the usage page.

Promotional credits are applied by discounting the invoice before it is finalized, which only works for Stripe-billed organizations. Polar issues its own invoices as the seller of record, so credits granted to a Polar-billed organization cannot come off its bill. **The balance says so rather than reading as money:** `credits.appliesToInvoices` is `false` with a `notAppliedReason` in `GET …/usage` and `get_usage`, and Settings → Billing labels it "not applied" and gives the reason. With no credits granted and none that could apply, the Credits panel is not shown at all. An organization not yet billed is judged by the provider it would be billed by. [Tell us](mailto:support@bugwatch.io) if you are holding a credit that does not apply. Fix-agent **credit packs**, which are purchases rather than discounts, work on both providers.

## Checkout and portal

### Who you are buying from

Bugwatch supports more than one payment provider, and **which one bills you changes who the seller is** — so it is stated, not hidden:

| Provider | Seller of record | Sales tax / VAT | Invoices and refunds come from |
|---|---|---|---|
| **Polar** (default) | Polar | Handled by Polar, worldwide | Polar |
| **Stripe** | Bugwatch | Charged by Bugwatch where we are registered | Bugwatch |

`GET /v1/orgs/{org}/billing/plans` reports the active one under `provider` (`id`, `name`, `merchantOfRecord`), and Settings → Billing shows it above the plan ladder. Your organization is assigned a provider the first time it pays and **stays on it**: if the default changes later, your existing subscription, portal, and invoices do not move.

### The endpoints

`GET /v1/orgs/{org}/billing/plans` returns every plan with `purchasable` set when a provider is configured and a product exists for it. Upgrading is `POST /v1/orgs/{org}/billing/checkout {"plan": "team", "returnPath": "/o/acme/settings"}` → `{"url", "provider"}` (a redirect to the provider's hosted checkout); managing cards, invoices, and cancellation is `POST …/billing/portal` → `{"url", "provider"}`. Both require `org:admin`, return `501` when no provider is configured, and are deliberately not exposed as MCP tools — purchases stay human-initiated. Plan changes come back through the provider's webhooks and update the allowance immediately.

Cancelling leaves the plan in place until the period you have paid for runs out; the drop to Free happens at expiry, not at the moment you cancel.

## What agents can do here

| Action | Tool | Scope |
|---|---|---|
| Read usage, plan, credits | `get_usage` | `org:read` |
| Read the catalog | `get_billing_plans` | `org:read` |
| Turn overage on/off | `set_overage` | `org:admin` (audited) |
| Upgrade, change card, cancel | none — dashboard | — |

## What the plan enforces

- **Project cap.** The Free plan includes 5 projects. Creating a sixth returns `402` with `{"error": "project limit reached …", "limit": 5, "plan": "free"}` from `POST /v1/orgs/{org}/projects` and from the `create_project` tool. Paid plans are unlimited.
- **Retention follows the plan.** New projects are created in the plan's tier (30 days on Free, 90 days on every paid plan). When a plan changes — Checkout, a subscription update, or a downgrade to Free — every project in the organization moves to the new tier within seconds, for events received from then on. Events already stored keep the retention they were written with; nothing is deleted early on a downgrade, and nothing is extended retroactively on an upgrade.
- **Period resets.** Exact usage counters reset on your billing anchor day (the 1st unless your subscription anchored elsewhere; 29–31 clamp to the last day of shorter months). Resets are idempotent per period, so a delayed nightly run never double-resets or skips a month.

## How overage is billed

With metered overage on, the nightly job computes each day's overage events — the part of that day's accepted errors and transactions that pushed the period's cumulative total past the allowance — from the exact per-day counts, and reports it to whichever provider bills your organization — a Stripe billing meter event, or a Polar usage event — under the identifier `org:date`. Each org-day is reported once; the last seven days are re-checked every night, so a missed run catches up and a retried run never double-bills. Days with no overage are recorded with zero and no call to the provider. So are days your organization was not billable for overage at all — overage off, or a plan without it — because **each day's decision is taken once, the night after it happens, and never revisited**: switching overage on does not bill the week before you switched it on, switching it off does not erase days you had already agreed to, and changing plan mid-period does not re-price days already recorded against your old allowance. Settings → Billing shows the events reported so far this period and the last reported day; the same numbers come back from `get_usage` under `overage`.
