Skip to content

Better Auth

Install the Better Auth integration:

Terminal window
npm install @guapocado/better-auth

Add the plugin to Better Auth:

import { guapocado } from "@guapocado/better-auth";
import { betterAuth } from "better-auth";
import { organization } from "better-auth/plugins";
export const auth = betterAuth({
plugins: [
organization({
teams: {
enabled: true,
},
}),
guapocado({
apiKey: process.env.GUAPOCADO_API_KEY!,
customerId: "organization",
webhook: {
path: "/guap",
},
}),
],
});

The plugin adds authenticated billing endpoints to auth.api:

export async function GET(request: Request) {
const result = await auth.api.guapocadoHas({
headers: request.headers,
body: { key: "advanced-analytics" },
});
return Response.json(result);
}

For browser code, add the Guapocado client plugin:

import { guapocadoClient } from "@guapocado/better-auth/client";
import { createAuthClient } from "better-auth/react";
export const authClient = createAuthClient({
plugins: [guapocadoClient()],
});
const usage = await authClient.guapocado.usage.consume("api-calls", 1);

Use customer.sync() to create or update the Guapocado customer for the current Better Auth session:

const customer = await authClient.guapocado.customer.sync();

Usage endpoints return { customerId, balance, resets }:

await auth.api.guapocadoUsageBalance({
headers: request.headers,
body: { key: "api-calls" },
});
await auth.api.guapocadoUsageConsume({
headers: request.headers,
body: { key: "api-calls", amount: 1 },
});
await auth.api.guapocadoUsageRefund({
headers: request.headers,
body: { key: "api-calls", amount: 1 },
});

customerId: "organization" maps the active Better Auth organization to Guapocado. You can also use "user" or "team".

"organization" requires Better Auth’s organization() plugin. "team" requires organization({ teams: { enabled: true } }). "user" only needs core Better Auth sessions.

The server plugin exposes GET/POST /api/auth/guap by default. Calling GET registers the current app URL with Guapocado using the server API key. Guapocado creates the endpoint disabled, so a dashboard user must approve it before events are forwarded.

Signal the integration in billing.config.ts:

export default defineBilling({
// entitlements and products...
webhooks: {
forwarding: [
{
key: "better-auth",
path: "/api/auth/guap",
events: "*",
integration: "better-auth",
},
],
},
});

For custom identity models, resolve the customer ID yourself:

guapocado({
apiKey: process.env.GUAPOCADO_API_KEY!,
resolveCustomerId: async (session) => String(session.session?.workspaceId),
});