Plan reference
| Plan | Monthly | Monthly FCU | Annual price | Features |
|---|---|---|---|---|
| Free | $0 | 10K | — | No credit card, evaluate WAVIS |
| PAYG | $0 base | Unlimited | — | $2.00/1M FCU overage |
| Starter | $9 | 1M | $7.47/mo | SDK GPU acceleration (BYO GPU) |
| Pro | $49 | 20M | $40.67/mo | Priority compute queue, webhook alerts, batch discount |
| Scale | $199 | 100M | $165.17/mo | Dedicated compute allocation, 99.9% SLA |
| Enterprise | Custom | Unlimited | Custom | SLA, audit logs, self-hosted GPU option, on-prem |
FCU weights
| Operation | FCU |
|---|---|
add, negate, rescale, add-plain | 1 |
multiply-plain | 2 |
multiply, rotate, key_switch | 5 |
poly-eval | 10 |
matmul | 20 |
bootstrap | 50 |
infer_7b | 100 |
infer_70b | 1000 |
POST /api/v1/billing/subscribe
Subscribe to a plan or change plans.
Auth: BILLING+ (account_admin)
Request
| Field | Type | Required | Notes |
|---|---|---|---|
plan | string | Yes | "starter", "pro", "scale", "enterprise" |
email | string | Yes | Billing contact (Stripe customer email) |
billing_cycle | string | No | "monthly" (default) or "annual" (17% off) |
Response — 200 OK
checkout_url (Stripe Checkout) instead of status: "active".
GET /api/v1/billing/subscription
Get the current subscription.
Auth: BILLING+
Response — 200 OK
status values:
"active"— paid, in good standing"trial"— trial period, no charge yet"cancelled"— cancelled but still in paid period"past_due"— payment failed, grace period"unpaid"— past grace, account suspended
DELETE /api/v1/billing/subscription
Cancel the subscription. Service continues until the end of the current
billing period.
Auth: BILLING+
Response — 200 OK
/billing/subscribe again with
the same plan.
GET /api/v1/billing/invoices
List past invoices.
Auth: BILLING+
Response — 200 OK
status: "paid", "open", "void", "uncollectible".
POST /api/v1/billing/budget
Set a monthly budget cap. Operations exceeding the cap are either rejected
(hard cap) or alerted on (soft cap).
Auth: BILLING+
Request
| Field | Type | Required | Notes |
|---|---|---|---|
monthly_cap_usd | float | Yes | >0 |
alert_email | string | No | Where to send 80%/100% alerts |
hard_cap | bool | No | If true, block ops once cap reached. Default false |
allow_soft_overage | bool | No | If false, also block when soft cap is reached. Default true |
Response — 200 OK
GET /api/v1/billing/budget
Get current budget settings and spend.
Auth: BILLING+
Response — 200 OK
Same shape as POST response.GET /api/v1/billing/usage
Current cycle usage breakdown. Requires Clerk JWT (dashboard session
token), not a WAVIS API key — used by the dashboard’s billing page.
Auth: Clerk JWT
Response — 200 OK
POST /api/v1/billing/portal
Get a one-time URL to the Stripe Customer Portal (manage payment method,
update billing details, download receipts).
Auth: Clerk JWT
Request
return_url must match an allow-list configured server-side (currently
*.wavis.xyz and localhost).
Response — 200 OK
POST /api/v1/billing/checkout
Create a Stripe Checkout Session — the easiest way to onboard a new
subscriber, supports all payment methods Stripe enables for your account.
Auth: Clerk JWT
Request
Response — 200 OK
client_secret with Stripe’s embedded checkout in the browser.
POST /api/v1/billing/stripe_webhook
Stripe → WAVIS event ingestion. Not for direct customer use.
Stripe POSTs subscription/payment events here, signed with the Stripe
webhook secret. WAVIS verifies the Stripe-Signature header before
processing. Returns 200 OK on success.
You don’t call this endpoint — Stripe does, when you configure
api.wavis.xyz/api/v1/billing/stripe_webhook in your Stripe Dashboard
(automatic for managed Enterprise tenants).
Common errors
| Code | Status | Meaning |
|---|---|---|
INVALID_PLAN | 400 | plan not recognized |
BUDGET_HARD_CAP_HIT | 402 | Operation rejected, monthly cap reached |
NO_PAYMENT_METHOD | 402 | Subscribe attempted without saved card; use /checkout |
STRIPE_UNAVAILABLE | 502 | Upstream Stripe API error; retry idempotent |
RETURN_URL_NOT_ALLOWED | 400 | return_url not in allow-list |
BILLING_PORTAL_DISABLED | 403 | Portal disabled for this tenant (Enterprise managed) |
Lifecycle examples
Upgrade plan mid-month
Set a hard budget cap of $1000/month
402 BUDGET_HARD_CAP_HIT once spend hits $1000
that month. Resets at UTC midnight on the month boundary.
Subscribe to billing webhooks
Best practices
- Always set a budget cap. Even with metered PAYG, cap your monthly exposure. A leaked key cannot exceed the cap.
- Use
wvs_test_*keys in CI. Test keys don’t trigger Stripe charges, but they consume quota — keep an eye on it. - Subscribe to
invoice_failed. Don’t let a card decline silently suspend your account. - Use annual billing for predictable workloads. 17% discount.
- Negotiate Enterprise early. Custom SLA, dedicated allocation, and on-prem deployment options are negotiable for >$5K/month commitments.
Next Steps
Webhooks
Async events for billing notifications
Authentication
API key roles and rotation