All tutorials

Wire Ringside spend into Stripe metered billing

20 min

By the end you'll have a working pipeline: Ringside charges land in your webhook, get signed-checked, translate into Stripe meter events, and your customers can open their own billing portal from a Next.js route.

Prerequisites
  • • A Ringside API key (do the quickstart first if you don't have one)
  • • A Stripe account with billing enabled + the Stripe CLI installed
  • • Node 20+ with a tunnel (ngrok, Cloudflare Tunnel, or deployed app)
  • • Your end-users already mapped to Stripe Customer IDs
  • • 20 minutes
01
Step 1

Register a webhook endpoint

// subscribe to chat.completion.finished

Ringside emits an event every time a chargeable API call completes. Register the URL of your receiver and pick the events you care about.

The signing secret comes back in the response once. Store it in an env var. You'll use it to HMAC-verify every delivery.

What just happened

Ringside retries deliveries with exponential backoff on any non-2xx, and stamps X-FC-Signature on every attempt. Re-emits on the same attempt share an event id, so your handler can be idempotent.

~/billing
02
Step 2

Create a Stripe meter + metered Price

// define the billable unit

A Stripe meter is the server-side aggregator. A metered Price attaches a rate to it. You can run both from the Stripe CLI or the dashboard.

Use ringside_spend as the event name so every meter event points at the same bucket. Units are up to you; this tutorial uses micro-cents so fractional usage doesn't round down.

~/billing
03
Step 3

Receive the webhook

// verify the HMAC signature

A minimal Express handler. The critical line is the HMAC comparison; you never trust the body until the signature matches the secret from Step 1.

Log the event type + customer id first so you can see the wiring work end-to-end before you layer Stripe on top.

What just happened

Use express.raw() (not express.json()) or Node's built-in raw-body read. HMAC is computed over the exact bytes on the wire - JSON re-serialization will silently break verification.

~/billing/server.js
04
Step 4

Post a Stripe meter event from the handler

// stripe.billing.meterEvents.create

Pull the Stripe customer id off your own mapping (usually stored on the Ringside Customer's metadata) and post a meter event equal to the call cost.

Ringside events carry cost_usd already converted to dollars. Multiply by 100,000 for micro-cents. Stripe accepts any integer unit, and you pick the rate on the Price.

What just happened

Ringside bills you in fractional dollars. Stripe meters store integers. Pick a unit once (micro-cents is our recommended default) and stay consistent - you can always change the Price markup later without touching the meter math.

~/billing/server.js
05
Step 5

Self-serve billing portal

// stripe.billingPortal.sessions.create

Drop a Next.js route handler that mints a billing-portal session for the signed-in user's Stripe customer id.

Redirect the user to the returned URL and Stripe handles invoice downloads, card updates, and cancellation. No custom UI to build.

app/api/portal/route.ts

You built it.

Ringside usage flows to your webhook, gets HMAC-verified, translates to Stripe meter events, and your customers self-serve invoices through the portal. Your margin is the difference between the Ringside cost and the Stripe Price you set.