Build a Metered AI Voice Agent with Clerk Billing + Stripe (2026)
Clerk Billing wraps Stripe in 700ms of glue: PricingTable component, has() entitlement checks, and per-minute metered billing. Plug it into a voice agent in one afternoon.
TL;DR — Clerk Billing (0.7% + Stripe fees) gives you a drop-in
<PricingTable />, server-sidehas({ feature })entitlement, and Stripe Meters for per-minute voice billing — without writing a webhook handler.
What you'll build
Three voice plans (Starter / Pro / Scale), each gating minutes per month. The Realtime endpoint checks entitlement, increments a Stripe Meter on every minute, and shuts off cleanly on cap.
Prerequisites
- Next.js 15 + Clerk
@clerk/nextjs@^6. - Stripe account connected to Clerk Billing.
OPENAI_API_KEY,STRIPE_SECRET_KEY.
Architecture
flowchart TD
U[User] --> CL[Clerk Auth + Plan]
U --> RT[/api/realtime/]
RT --> EN{has voice_minutes?}
EN -->|yes| OA[OpenAI Realtime]
OA --> M[Stripe Meter increment]
EN -->|no| UP[Upgrade page]
Step 1 — Define plans in Clerk Dashboard
In Clerk Dashboard → Billing, create plans starter_149, pro_499, scale_1499 and a feature voice_minutes. Mark voice_minutes as a metered feature linked to a Stripe Meter voice_minutes_meter.
Step 2 — Drop the pricing table
```tsx
// app/pricing/page.tsx
import { PricingTable } from "@clerk/nextjs";
export default function Pricing() {
return
Step 3 — Entitlement gate
```ts // app/api/realtime/route.ts import { auth } from "@clerk/nextjs/server"; import { NextResponse } from "next/server";
Hear it before you finish reading
Talk to a live CallSphere AI voice agent in your browser — 60 seconds, no signup.
export async function POST() { const { userId, has } = await auth(); if (!userId) return new NextResponse("auth", { status: 401 }); if (!has({ feature: "voice_minutes" })) return NextResponse.json({ upgrade: true }, { status: 402 });
const r = await fetch("https://api.openai.com/v1/realtime/sessions", {
method: "POST",
headers: { Authorization: Bearer ${process.env.OPENAI_API_KEY},
"Content-Type": "application/json" },
body: JSON.stringify({ model: "gpt-realtime" }),
});
return NextResponse.json(await r.json());
}
```
Step 4 — Meter usage on call end
```ts import Stripe from "stripe"; import { auth, clerkClient } from "@clerk/nextjs/server";
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);
export async function POST(req: Request) { const { userId } = await auth(); const { minutes } = await req.json(); const u = await (await clerkClient()).users.getUser(userId!); const customerId = u.publicMetadata.stripeCustomerId as string;
await stripe.billing.meterEvents.create({ event_name: "voice_minutes_meter", payload: { stripe_customer_id: customerId, value: String(minutes) }, }); return Response.json({ ok: true }); } ```
Still reading? Stop comparing — try CallSphere live.
CallSphere ships complete AI voice agents per industry — 14 tools for healthcare, 10 agents for real estate, 4 specialists for salons. See how it actually handles a call before you book a demo.
Step 5 — Hook on call disconnect
In the browser, when the WebRTC peer goes disconnected, POST elapsed minutes to /api/meter.
Step 6 — Cap enforcement
Use has({ feature: "voice_minutes", quantity: { gte: capLeft } }) in middleware to block once the soft cap is hit.
Pitfalls
- Test mode: Clerk Billing dev sandbox uses Stripe test keys — switch both before launch.
- Meter granularity: Stripe Meters dedupe by
(customer, event_name, idempotency_key, time); always pass a uniqueidentifierper call. - Entitlement caching:
has()is cached for 30s — for hard caps, query Stripe usage directly.
How CallSphere does this in production
CallSphere prices at $149 Starter / $499 Pro / $1,499 Scale with metered overage, 14-day no-card trial, and 22% recurring Year-1 affiliate. The platform spans 37 agents, 90+ tools, 115+ DB tables, 6 verticals — Healthcare, OneRoof (Next.js 16 + React 19), Salon (NestJS 10 + Prisma), Sales (Node.js 20 + React 18 + Vite). Clerk + Stripe handles auth + billing across all six.
FAQ
Clerk Billing fee? 0.7% per transaction on top of Stripe fees.
Can I run B2B teams? Yes — Clerk has Organizations with seat-based plans and per-org features.
Can I avoid Clerk and use Stripe Customer Portal directly? Yes, but you give up the React components and has() helpers.
EU compliance? Clerk offers SCA-ready Stripe checkout out of the box.
Sources
- Clerk Billing for B2C - https://clerk.com/docs/nextjs/guides/billing/for-b2c
- Clerk Billing for B2B - https://clerk.com/docs/nextjs/guides/billing/for-b2b
- Stripe Sessions: Clerk + Stripe - https://stripe.com/sessions/2025/instant-zero-integration-saas-billing-with-clerk-stripe
- Stripe Billing Meters - https://docs.stripe.com/billing/subscriptions/usage-based/recording-usage
Try CallSphere AI Voice Agents
See how AI voice agents work for your industry. Live demo available -- no signup required.