NNO Docs
Guides

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

TierMonthly pricePlatformsTenantsFeatures
Starter$49/mo1Up to 3Up to 5
Growth$199/moUp to 3Up to 20Unlimited
Scale$799/moUnlimitedUnlimitedUnlimited

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:

  1. Creates a Stripe Customer for the operator
  2. Creates a Stripe Subscription on the selected tier
  3. Records the subscription in the billing D1 database (subscriptions table)

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 charges

Overage 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:

  1. Go to Stripe Dashboard > Developers > Webhooks > Add endpoint
  2. Set the endpoint URL to https://billing.svc.nno.app/webhooks
  3. Select these events: invoice.paid, invoice.payment_failed, customer.subscription.deleted
  4. Copy the signing secret, then add it as a Worker secret:
wrangler secret put STRIPE_WEBHOOK_SECRET

Stripe 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:

SecretDescription
STRIPE_SECRET_KEYStripe live or test secret key
STRIPE_WEBHOOK_SECRETStripe webhook signing secret
CF_API_TOKENCloudflare API token (Analytics Engine + resource stats read scope)
CF_ACCOUNT_IDCloudflare 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_ID

Next steps

On this page