Integrations

API keys

Keys for people's scripts, bots and integrations, with permissions.
The account page's API keys tab: each key with its first characters, permissions, last use and expiry

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:

  1. Create a key with a name, an expiry (30, 90 or 365 days, or never) and permissions, ticked from your scopes.
  2. Copy it from the dialog: it's shown once.
  3. 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.