What You’ll Build
This tutorial walks you through building a Next.js 14+ (App Router) full-stack application using a dual-client architecture:Profyclient — initialized with your platform API key (sk-pro-...). Used to call AI experts and chat completions. The cost is charged to your platform account.ProfyAppclient — initialized with your OAuth App credentials. Used to bill end users for usage viareportEvent, using each user’s OAuth token.
The
Profy client (API key) and ProfyApp client (OAuth) serve different purposes. You use the API key to call AI — the platform charges your account. You use OAuth tokens to bill your end users for the actions they take in your app.Prerequisites
Profy Developer Account
Register a Profy account, then create an App in the developer dashboard to get your Client ID, Client Secret, and API Key (
sk-pro-...)Development Environment
Node.js 18+, npm/pnpm/bun, basic Next.js and React experience
Step 1: Create a Next.js Project and Install Dependencies
Step 2: Configure Environment Variables
.env.local
Step 3: Initialize Both SDK Clients
Create a shared module that exports both theProfy client (for AI calls) and the ProfyApp client (for OAuth and billing):
lib/profy.ts
Both clients should be used as singletons on the server side. Never expose
apiKey or clientSecret to the browser.Step 4: Create the OAuth Login Page
UseprofyApp.authorizationUrl() to generate the OAuth URL. The events:write scope is required for billing event reporting.
app/page.tsx
Step 5: Handle the OAuth Callback
When the user authorizes your app, Profy redirects back with acode parameter. Exchange it for an OAuthToken and persist it.
app/api/callback/route.ts
Step 6: Token Persistence
You need to store OAuth tokens securely and refresh them when they expire. Here we show a manual DB store pattern using the SDK’sisTokenExpired() and app.refresh() helpers.
lib/token-store.ts
lib/token-store-production-example.ts
Step 7: Report Billing Events
UseprofyApp.reportEvent() with the user’s OAuth token to bill them. The onRefresh callback handles automatic token rotation during the API call.
app/api/report-event/route.ts
The
onRefresh callback on reportEvent is called if the SDK internally refreshes the token during the API call. This ensures your stored token stays up to date without a separate refresh step.app/dashboard/page.tsx
Step 8: Call AI (Expert or Chat)
Use theProfy client (API key) for all AI calls. This is completely separate from the OAuth billing flow — the AI cost is charged to your platform account.
Call an Expert
app/api/ai/expert/route.ts
Call an Expert (Streaming)
app/api/ai/expert-stream/route.ts
Chat Completions
app/api/ai/chat/route.ts
Combining AI Calls with Billing
In a real application, you typically call the AI and report a billing event together. Here’s how:lib/ai-with-billing.ts
Step 9: Error Handling
The SDK throws typed errors that you can catch precisely. All error classes extendProfyApiError.
lib/error-handler.ts
app/api/report-event/route.ts
Complete Project Structure
FAQ
Next Steps
Per-Use Billing SaaS
PER_USE mode: fixed-price per-use billing
AI Metered Billing
METERED mode: billing by token consumption for AI model calls
Webhook Event Handling
Receive real-time user event notifications from the Profy platform
Token Management Best Practices
Multi-user management, concurrent refresh, secure storage

