Billing
Set up and manage billing for your NNO platform with Stripe and usage metering.
Set Up Billing
NNO billing uses a hybrid model: a flat monthly base tier covers platform access and a baseline resource allocation, with usage-based overage charges for anything above the included limits. This guide explains how subscriptions work, what gets metered, and how to configure Stripe for your platform.
Plan tiers
| Tier | Monthly price | Platforms | Tenants | Features |
|---|---|---|---|---|
| Starter | $49/mo | 1 | Up to 3 | Up to 5 |
| Growth | $199/mo | Up to 3 | Up to 20 | Unlimited |
| Scale | $799/mo | Unlimited | Unlimited | Unlimited |
Each tier includes baseline Cloudflare resource allocations (Worker invocations, D1 rows, R2 storage, KV operations). Usage above those limits incurs overage charges billed at the end of the month.
How subscriptions work
When a platform operator signs up on the NNO Portal, the Billing service:
- Creates a Stripe Customer for the operator
- Creates a Stripe Subscription on the selected tier
- Records the subscription in the billing D1 database (
subscriptionstable)
Subscription status (active, trialing, past_due, canceled) is kept in sync via Stripe webhooks. Check your current subscription status:
curl https://gateway.svc.nno.app/api/billing/subscription \
-H "Authorization: Bearer <your-api-key>"To change tiers, call POST /api/billing/subscription with the new tier, or use the Upgrade flow in the NNO Portal under Billing > Plan.
Usage metering
Usage is collected daily at 02:00 UTC. Each platform Worker emits data points to Cloudflare Analytics Engine (CFAE) on every request. The Billing service queries CFAE and the Cloudflare GraphQL Analytics API to aggregate:
- Worker invocations — via CFAE SQL API
- D1 read/write rows — via Cloudflare GraphQL Analytics API
- R2 storage and operations — via Cloudflare GraphQL Analytics API
- KV reads and writes — via Cloudflare GraphQL Analytics API
Daily snapshots are stored in usage_snapshots and summarised into month-to-date totals for quota enforcement and invoicing.
Check your current month-to-date usage:
curl https://gateway.svc.nno.app/api/billing/usage/current \
-H "Authorization: Bearer <your-api-key>"The response includes used, limit, pct, and on_track per resource so you can build usage dashboards or set alerts.
Invoice generation
Invoices are generated on the 1st of each month at 06:00 UTC for the previous month's usage. The calculation is:
invoice total = flat tier base price + sum of overage chargesOverage charges are calculated per resource and added as Stripe Invoice Items before the invoice is finalised. List invoices via:
curl "https://gateway.svc.nno.app/api/billing/invoices" \
-H "Authorization: Bearer <your-api-key>"Each invoice includes a line_items array with per-resource usage, the included limit, excess, rate description, and amount in cents.
Threshold alerts
The Billing service sends email alerts when usage crosses 50%, 75%, 90%, and 100% of your tier limits. Each threshold fires only once per billing period per resource. Alerts are also surfaced as banners in the NNO Portal.
To handle alerts programmatically, subscribe to usage webhook events from the NNO Portal under Billing > Webhooks.
Configure the Stripe webhook
The Billing service listens for Stripe events at /webhooks. Configure the endpoint in your Stripe dashboard:
- Go to Stripe Dashboard > Developers > Webhooks > Add endpoint
- Set the endpoint URL to
https://billing.svc.nno.app/webhooks - Select these events:
invoice.paid,invoice.payment_failed,customer.subscription.deleted - Copy the signing secret, then add it as a Worker secret:
wrangler secret put STRIPE_WEBHOOK_SECRETStripe signatures are verified using the stripe-signature header on every incoming request. Events are processed idempotently — duplicate deliveries are safe.
Payment method management
Operators manage payment methods via the Stripe Customer Portal. Generate a portal session:
curl -X POST https://gateway.svc.nno.app/api/billing/portal \
-H "Authorization: Bearer <your-api-key>"
# Returns: { "url": "https://billing.stripe.com/session/..." }Redirect the user to the returned URL. The portal handles card updates, billing address, and invoice history.
Required secrets
Set these secrets on the Billing service before deploying:
| Secret | Description |
|---|---|
STRIPE_SECRET_KEY | Stripe live or test secret key |
STRIPE_WEBHOOK_SECRET | Stripe webhook signing secret |
CF_API_TOKEN | Cloudflare API token (Analytics Engine + resource stats read scope) |
CF_ACCOUNT_ID | Cloudflare account ID |
wrangler secret put STRIPE_SECRET_KEY
wrangler secret put STRIPE_WEBHOOK_SECRET
wrangler secret put CF_API_TOKEN
wrangler secret put CF_ACCOUNT_IDNext steps
- Managing Environments — use separate Stripe test keys in staging
- Authentication — protect billing routes with the platform-admin role
- API reference — full Billing service endpoint reference