Integrations
API keys
Keys for people's scripts, bots and integrations, with permissions.


Better Auth's API Key plugin.
Turning it on
Install the plugin's package
Terminal
pnpm add @better-auth/api-key
Enable it
nuxt.config.ts
export default defineNuxtConfig({
betterAuthUi: {
apiKey: {
enabled: true,
prefix: 'myapp_',
// The permissions people can give a key.
scopes: { projects: ['read', 'write'] }
}
}
})
Run Better Auth's migrations
The plugin adds an apikey table.
What people get
An API keys tab on the account page:
- Create a key with a name, an expiry (30, 90 or 365 days, or never) and permissions, ticked from your
scopes. - Copy it from the dialog: it's shown once.
- See their keys, with each key's first characters, permissions, last use and expiry, and revoke one.
Checking a key
On your server, verify the key and its permissions with Better Auth:
server/api/projects.post.ts
export default defineEventHandler(async (event) => {
const key = getHeader(event, 'x-api-key')
const { valid } = await serverAuth(event).api.verifyApiKey({
body: { key, permissions: { projects: ['write'] } }
})
if (!valid) throw createError({ statusCode: 401 })
})
With enableSessions, a key in the x-api-key header signs its owner in, like a session, so your usual session checks
work for it too.
In the admin
Staff see a user's keys on their page and revoke one that leaked (user: update). Creating, deleting and revoking keys
are recorded in the audit log, and a user's data download lists their keys, never the key itself.
Options
enabled
booleandefault: false
prefix
string
Put in front of every key, for example
myapp_. Better Auth recommends ending it with an underscore.scopes
Record<string, string[]>
Permissions people may give a key, as resources and actions. Without it, keys have no permissions.
enableSessions
booleandefault: false
A key in the
x-api-key header signs its owner in, like a session.Better Auth only takes a key's permissions from server calls, so the module creates keys through its own route. It
checks them against
scopes, then calls Better Auth's createApiKey for the signed-in user. Listing and revoking use
Better Auth's endpoints.