API Key
Install Solid/Zaidan API key management with create, copy, and revoke flows.
The API key plugin adds programmatic API key management to your Solid/Zaidan authentication settings. Users can create, reveal once, copy, list, and revoke API keys from security and organization settings. New keys can use a configurable expiration interval, and each listed key shows when it expires.
It contributes:
- An
<ApiKeys />card rendered by the copiedSecuritySettingscomponent when the API Key plugin is enabled - An
<OrganizationApiKeys />card for organization-owned keys whenapiKeyPlugin({ organization: true })is registered - Solid query and mutation wiring through
listApiKeysOptions,createApiKeyOptions, anddeleteApiKeyOptions - App-owned API key cards, empty state, loading placeholder, create dialog, new-key reveal dialog, and delete confirmation dialog
Setup
Install the Better Auth plugin
Install the @better-auth/api-key package and add it to your Better Auth server config:
import { apiKey } from "@better-auth/api-key"
import { betterAuth } from "better-auth"
export const auth = betterAuth({
// ...
plugins: [
apiKey()
]
})Install the matching client plugin
Add apiKeyClient() to your Solid auth client so authClient.apiKey.* methods are available:
import { apiKeyClient } from "@better-auth/api-key/client"
import { createAuthClient } from "better-auth/solid"
export const authClient = createAuthClient({
plugins: [
apiKeyClient()
]
})Install the Solid/Zaidan components
Run the shadcn CLI to install the Solid API key components and the apiKeyPlugin() factory into your project:
npx shadcn@latest add https://better-auth-ui.com/r/solid/api-key.jsonThis drops the following into your codebase:
src/lib/auth/api-key-plugin.ts: localapiKeyPlugin()factorysrc/components/auth/api-key/api-keys.tsx: the API keys security cardsrc/components/auth/api-key/api-key.tsx: individual API key row with delete controlsrc/components/auth/api-key/api-keys-empty.tsx: empty state shown when no keys existsrc/components/auth/api-key/api-key-skeleton.tsx: loading placeholder shown while keys are loadingsrc/components/auth/api-key/create-api-key-dialog.tsx: dialog for creating a new keysrc/components/auth/api-key/new-api-key-dialog.tsx: dialog showing the newly created key with copy buttonsrc/components/auth/api-key/delete-api-key-dialog.tsx: confirmation dialog for revoking a keysrc/components/auth/api-key/organization-api-keys.tsx: owner-gated wrapper that renders<ApiKeys />scoped to the active organization
Register the UI plugin
For user-owned keys, the copied SecuritySettings component renders <ApiKeys /> whenever the API Key plugin is enabled. For organization-owned keys, register the copied UI plugin with { organization: true }:
import { apiKeyPlugin } from "@/lib/auth/api-key-plugin"
<AuthProvider
authClient={authClient}
plugins={[
apiKeyPlugin({ organization: true })
]}
>
{children}
</AuthProvider>Configure expiration
The create dialog offers 30 days, 90 days, and Never by default. It initially selects 30 days. Configure the choices through the copied apiKeyPlugin():
apiKeyPlugin({
keyExpiration: {
intervals: [7, 30, 90],
defaultInterval: 30,
allowNever: true
}
})intervals and defaultInterval use days. Better Auth receives the selected lifetime as seconds.
Keep the UI choices within the limits in your Better Auth server configuration:
apiKey({
keyExpiration: {
minExpiresIn: 7,
maxExpiresIn: 90,
defaultExpiresIn: null
}
})When allowNever is enabled, selecting Never sends no custom interval. Better Auth will still apply defaultExpiresIn if the server defines one, so set allowNever: false in the UI when your server always requires expiration.
To remove the expiration field and rely entirely on the server default:
apiKeyPlugin({ keyExpiration: false })Components
<ApiKeys />
The security settings page shows <ApiKeys /> when its layout includes SecuritySettings and enables the API Key plugin.
The component uses the Solid runtime APIs to list, create, and revoke keys.
Usage
import { ApiKeys } from "@/components/auth/api-key/api-keys"
<ApiKeys />This component is normally mounted by SecuritySettings. Render it manually only if you are building a custom settings layout.
Props
Prop
Type
<OrganizationApiKeys />
This component wraps <ApiKeys />. It resolves the organization and checks the current user's membership.
It renders the API keys only for an organization owner.
To enable, opt in on the copied UI plugin and add a matching API key configuration to your Better Auth server config. The organization API key config uses a fixed configId of "organization", so the server entry must be { configId: "organization", references: "organization" }:
import { apiKeyPlugin } from "@/lib/auth/api-key-plugin"
<AuthProvider
authClient={authClient}
plugins={[
apiKeyPlugin({ organization: true })
]}
>
{children}
</AuthProvider>import { apiKey } from "@better-auth/api-key"
import { betterAuth } from "better-auth"
import { organization } from "better-auth/plugins"
export const auth = betterAuth({
// ...
plugins: [
organization(),
apiKey([
{ configId: "default", references: "user" },
{ configId: "organization", references: "organization" }
])
]
})See the Better Auth docs for role-based permissions on organization-owned keys.
Usage
import { OrganizationApiKeys } from "@/components/auth/api-key/organization-api-keys"
<OrganizationApiKeys />Props
Prop
Type
Options
Prop
Type
Runtime API references
List API keys
Prop
Type
Create API key
Prop
Type
Delete API key
Prop
Type
Localization
Prop
Type
Lifecycle controls
<ApiKeys /> lets users create, rename, and delete keys. The create form exposes the name, configuration, expiration, and organization. The list shows status, remaining requests, request usage, and the last request time as read-only values.
The built-in dialog does not show metadata because metadata belongs to the application. For metadata, build a custom form with useCreateApiKey. Map named fields or application state to the metadata object. Do not show a raw JSON editor. If metadata affects trusted behavior, validate it in a server route.
Better Auth reserves enablement, permissions, quotas, refill rules, and rate limits for server-side creation and updates. Configure those values in trusted server code instead of exposing them in the account UI.
apiKeyPlugin({
configurations: [
{ id: "default", label: "Personal", organization: false },
{ id: "organization", label: "Organization", organization: true }
],
pageSize: 20
})The server must define every listed configId. Use useUpdateApiKey for a custom Solid rename surface.
Last updated on