Better Auth OpenMeter Plugin
raw JSON → 0.5.0 verified Sat May 09 auth: no javascript
Better Auth plugin for OpenMeter usage metering, entitlements, API key tracking, organization customers, React hooks, and billing provider bridges (Stripe, Polar, Razorpay, Creem, Dodo Payments, Autumn). Current stable version 0.5.0, released monthly. Key differentiators: seamless OpenMeter integration with Better Auth auth lifecycle, support for both greenfield runtime and catalog/helper modes, built-in billing catalog DSL with recurring-first plans/add-ons/top-ups, and provider-aware compilation for multiple billing providers.
Common errors
error Cannot find module 'better-auth-openmeter-plugin/client' ↓
cause Using an older version of the package that does not have the /client subpath export.
fix
Update to v0.4.0 or later: npm install better-auth-openmeter-plugin@latest
error TypeError: openmeterPlugin is not a function ↓
cause Importing the module as default import instead of named import.
fix
Use import { openmeterPlugin } from 'better-auth-openmeter-plugin'
error The field 'openmeterCustomerId' does not exist on type 'User' ↓
cause Database schema has not been migrated after enabling the plugin.
fix
Run your database migration (e.g., npx better-auth generate && npx better-auth migrate) to add the openmeterCustomerId column.
error OpenMeterError: unauthorized - invalid API key ↓
cause The provided apiKey is incorrect or missing.
fix
Ensure OPENMETER_API_KEY environment variable is set and valid. In local dev, use openmeterClient with a mock or local server.
Warnings
gotcha The plugin modifies the Better Auth user schema to add an openmeterCustomerId field. You must run a database migration after enabling the plugin to create this column. ↓
fix Run your Better Auth migration/generation step after adding the plugin to your auth config.
breaking In v0.3.0, the billing catalog DSL was introduced with a different shape for plans and add-ons. If you used an earlier version without the catalog, you will need to refactor your billing configuration. ↓
fix Update plugin configuration to use the catalog DSL: define plans with recurring, add-ons, and top-ups as described in the README.
deprecated The client plugin import path changed. In v0.3.0 and earlier, client plugin was available at 'better-auth-openmeter-plugin/client'. ↓
fix Use import { openmeterClientPlugin } from 'better-auth-openmeter-plugin/client'.
gotcha The package requires Node.js >=20 and only supports ESM. Using require() or older Node versions will break. ↓
fix Ensure your project runs on Node >=20 and uses ESM (type: 'module' in package.json).
gotcha The OpenMeter client must be configured with a valid API key or base URL. Passing only an apiKey without baseUrl defaults to https://openmeter.cloud, which may not be appropriate for all environments. ↓
fix Explicitly set baseUrl to your OpenMeter instance URL (e.g., https://openmeter.cloud or http://127.0.0.1:8888 for local dev).
Install
npm install better-auth-openmeter-plugin yarn add better-auth-openmeter-plugin pnpm add better-auth-openmeter-plugin Imports
- openmeterPlugin wrong
import openmeterPlugin from 'better-auth-openmeter-plugin'correctimport { openmeterPlugin } from 'better-auth-openmeter-plugin' - openmeterClientPlugin wrong
import { openmeterClientPlugin } from 'better-auth-openmeter-plugin'correctimport { openmeterClientPlugin } from 'better-auth-openmeter-plugin/client' - applyCatalogTopupGrant
import { applyCatalogTopupGrant } from 'better-auth-openmeter-plugin' - OpenMeter wrong
import { OpenMeter } from 'better-auth-openmeter-plugin'correctimport { OpenMeter } from '@openmeter/sdk'
Quickstart
import { betterAuth } from 'better-auth';
import { openmeterPlugin } from 'better-auth-openmeter-plugin';
const auth = betterAuth({
plugins: [
openmeterPlugin({
apiKey: process.env.OPENMETER_API_KEY ?? '',
baseUrl: 'https://openmeter.cloud',
createCustomerOnSignUp: true,
syncCustomerOnUserUpdate: true,
trackAuthEvents: true,
customer: {
resolveKey: ({ user }) => user.id,
resolveSubject: ({ user }) => user.id,
resolveProfile: ({ user, defaults }) => ({
...defaults,
description: `Better Auth user ${user.id}`,
billingAddress: {
country: 'US',
},
metadata: {
...defaults.metadata,
source: 'better-auth',
},
}),
},
}),
],
});