Create a Flowglad server factory function in a shared file, eg. lib/flowglad.ts:
Copy
Ask AI
import { FlowgladServer } from '@flowglad/nextjs/server'export const flowglad = (customerExternalId: string) => { // customerExternalId is the ID from YOUR app's database, NOT Flowglad's customer ID return new FlowgladServer({ customerExternalId, getCustomerDetails: async (customerExternalId) => { // Fetch customer details from YOUR database using YOUR app's ID const user = await db.users.findOne({ id: customerExternalId }) if (!user) { throw new Error('Customer not found') } return { email: user.email, name: user.name, } }, })}
Important:customerExternalId is the ID from your app’s database (e.g., user.id or organization.id), not Flowglad’s customer ID.B2C apps: Pass user.id as customerExternalId B2B apps: Pass organization.id or team.id as customerExternalId
Flowglad integrates seamlessly with your auth provider. Read more about auth options here.
Create a route handler to handle Flowglad API requests from your frontend. The Server SDK provides route handler constructors that enable your client to communicate with your server, allowing you to load billing and feature access data via the useBilling hook on your frontend. It should handle requests at /api/flowglad/...
Next.js App Router
Next.js Pages Router
Express
Other Frameworks
app/api/flowglad/[...path]/route.ts
Copy
Ask AI
import { nextRouteHandler } from '@flowglad/nextjs/server'import { flowglad } from '@/lib/flowglad'import { customerIdFromRequest } from '@/lib/auth'export const { GET, POST } = nextRouteHandler({ flowglad, getCustomerExternalId: async (req) => { const externalId = await customerIdFromRequest(req) if (!externalId) { throw new Error('Unable to determine customer external ID') } return externalId },})
pages/api/flowglad/[...path].ts
Copy
Ask AI
import { pagesRouteHandler } from '@flowglad/nextjs/server'import { flowglad } from '@/lib/flowglad'import { customerIdFromRequest } from '@/lib/auth'export default pagesRouteHandler({ flowglad, getCustomerExternalId: async (req) => { const externalId = await customerIdFromRequest(req) if (!externalId) { throw new Error('Unable to determine customer external ID') } return externalId },})
server.ts
Copy
Ask AI
import express from 'express'import { expressRouter } from '@flowglad/server/express'import { flowglad } from './lib/flowglad'import { customerIdFromRequest } from './lib/auth'const app = express()app.use( '/api/flowglad', expressRouter({ flowglad, getCustomerExternalId: async (req) => { const externalId = await customerIdFromRequest(req) if (!externalId) { throw new Error('Unable to determine customer external ID') } return externalId }, }))
server.ts
Copy
Ask AI
import { requestHandler } from '@flowglad/server'import { flowglad } from './lib/flowglad'import { customerIdFromRequest } from './lib/auth'import type { HTTPMethod } from '@flowglad/shared'const flowgladHandler = requestHandler({ flowglad, getCustomerExternalId: async (req) => { const externalId = await customerIdFromRequest(req) if (!externalId) { throw new Error('Unable to determine customer external ID') } return externalId },})// Example: Hono, Cloudflare Workers, Elysia, etc.// Adapt this pattern to your frameworkasync function handleFlowgladRequest(request: Request): Promise<Response> { const url = new URL(request.url) const path = url.pathname .replace('/api/flowglad/', '') .split('/') .filter((segment) => segment !== '') const result = await flowgladHandler( { path, method: request.method as HTTPMethod, query: request.method === 'GET' ? Object.fromEntries(url.searchParams) : undefined, body: request.method !== 'GET' ? await request.json().catch(() => ({})) : undefined, }, request ) return Response.json( { error: result.error, data: result.data, }, { status: result.status, } )}
import { nextRouteHandler} from '@flowglad/nextjs/server'import { flowglad } from '@/utils/flowglad'export const { GET, POST } = nextRouteHandler({ flowglad, // derive customer external id from the request getCustomerExternalId: async (req) => { // for B2B apps, provide organization or team id instead const user = await getUserForReq(req) return user.id }, // optional hooks for custom behavior beforeRequest: async () => { // side effect to run before the request is processed }, afterRequest: async () => { // side effect to run after the request is processed }, onError: (error) => { // handle errors }})
import { FlowgladServer } from '@flowglad/nextjs/server'export const flowglad = (customerExternalId: string) => { // customerExternalId is the ID from YOUR app's database, NOT Flowglad's customer ID return new FlowgladServer({ customerExternalId, getCustomerDetails: async (externalId) => { // Fetch customer details from YOUR database using YOUR app's ID const user = await db.users.findOne({ id: externalId }) if (!user) { throw new Error('Customer not found') } return { email: user.email, name: user.name, } }, })}
app/api/flowglad/[...path]/route.ts
Copy
Ask AI
import { nextRouteHandler } from '@flowglad/nextjs/server'import { flowglad } from '@/utils/flowglad'export const { GET, POST } = nextRouteHandler({ flowglad, getCustomerExternalId: async (req) => { // Extract customerExternalId from your auth/session // This should be YOUR app's user/organization ID, NOT Flowglad's customer ID // For B2C: return user.id (from your database) // For B2B: return organization.id (from your database) const userId = await getUserIdFromRequest(req) if (!userId) { throw new Error('User not authenticated') } return userId },})
Important:customerExternalId is the ID from your app’s database (e.g., user.id or organization.id), not Flowglad’s customer ID.B2C apps: Pass user.id as customerExternalId B2B apps: Pass organization.id or team.id as customerExternalIdFlowglad doesn’t need to know how you authenticate—just provide the ID from your system that represents the customer entity which will be billed.