Browse documentation
Deploy and Operate
Billing
Plans, seats, usage allowances, add-ons, budgets, and invoices for a Vex organization.
On this page
Billing is per organization. Open Settings → Organizations → your organization → Billing at /settings/organizations/<org-id>/billing, or pick Billing from the user menu in the bottom-left corner, which goes to the active organization's page. The strip at the top gives the four numbers at a glance: seats, usage spend so far this period, the next invoice, and when the trial or period ends. Any member can read the page; only an organization owner can subscribe, change add-ons, set a budget, or cancel. The public price list is at /pricing.
Plan and seats
An organization without a subscription sees the Team plan priced at its current member count and one Subscribe action. Subscribing opens Stripe Checkout to collect a card; nothing is charged until the trial ends. The subscription and its Metronome contract are created when Stripe confirms the session, so the page may take a moment to show the plan after you return.
Once subscribed, the plan card shows:
- the package and its status (
trialing,active,past_due), - billable seats against the package's seat limit,
- the trial end or the current period end,
- the next invoice total and remaining credits, read from the rating provider's draft invoice,
- Manage in Stripe, which opens the Stripe customer portal for invoices, the payment method, and the billing address.
Seats are counted from organization members. Inviting a member past the seat limit is refused with a billing notice (see When a limit is reached).
Usage and allowances
Every seat brings a monthly allowance on each meter. The usage table lists one row per meter for the current period: what is included, what has been used, the overage and its cost at the rate card price, and a straight-line projection of the overage at period end. A sparkline shows the last 24 hours in 5-minute buckets.
CI minutes are one group with a row per runner class. The included pool covers the standard classes; larger runners are always billed at their rate. Classes with no usage this period are folded until you ask for them.
Pick a meter to open its breakdown: the live 24-hour series, totals for the last 24 hours, 7 days, or the period, and the subjects (apps, runs, repositories) that produced the usage. The panel says how fresh the data is. Totals from ledger means the live pipes were unavailable and the numbers come from the hourly ledger instead, which lags by up to an hour and carries no per-subject detail.
Add-ons
An add-on is a fixed monthly block that raises one allowance, for example 100 GiB of repository storage. Owners change the quantity from the Add-ons card; each step takes effect on the current period and is prorated on the next invoice.
Budget
A monthly budget caps usage spend. Set a dollar figure on the Budget card; the organization is emailed at 50%, 80%, and 100% of it. Leave the field empty and save to remove the cap. The budget applies to usage charges only, never to the seat charge.
Invoices and payment
Seat charges are billed in advance each month and usage in arrears, on one invoice. The Invoices section on the billing page lists the upcoming invoice (what usage so far would be charged, its period, and any credit that applies) followed by past invoices with their date, number, status, and total; View opens the invoice in Stripe and PDF downloads it, each in a new tab. The list is refreshed about once a minute. Receipts and the payment method live in the Stripe customer portal, reached from Manage in Stripe. A failed payment keeps the plan for a 14-day grace period; the plan card shows Payment failed until the invoice is paid.
Cancelling from the Danger zone keeps the plan until the end of the current period, then the organization drops to the free limits. Resume before that date to keep it.
When a limit is reached
A request that would pass a limit is refused with HTTP 402 and a body of the form:
{
"error": {
"code": "billing_limit_exceeded",
"reason": "seat_limit",
"meter_key": null,
"limit": 5,
"requested": 6,
"upgrade_path": "/settings/organizations/<org-id>/billing",
"message": "The Team plan allows 5 seats."
}
}
The web app shows this as a billing notice with a link to the billing page. Raise the limit by adding seats, an add-on, or a budget, or by moving to a custom package.
API
All billing endpoints use the cookie session or a bearer token and are scoped to the organization:
| Method | Path | Who |
|---|---|---|
GET | /api/v1/organizations/:organization_id/billing | members |
GET | /api/v1/organizations/:organization_id/billing/usage | members |
GET | /api/v1/organizations/:organization_id/billing/usage/breakdown?meter=&window= | members |
GET | /api/v1/organizations/:organization_id/billing/invoices | members |
POST | /api/v1/organizations/:organization_id/billing/checkout_sessions | owners |
POST | /api/v1/organizations/:organization_id/billing/portal_sessions | owners |
PATCH | /api/v1/organizations/:organization_id/billing/subscription | owners |
PUT | /api/v1/organizations/:organization_id/billing/addons/:addon_key | owners |
PUT | /api/v1/organizations/:organization_id/billing/budget | owners |
GET | /api/v1/billing/packages | public |
The full schemas are in the OpenAPI document.