docs/content/docs/plugins/api-key/index.mdx
The API Key plugin allows you to create and manage API keys for your application. It provides a way to authenticate and authorize API requests by verifying API keys.
```package-install
@better-auth/api-key
```
```ts title="auth.ts"
import { betterAuth } from "better-auth"
import { apiKey } from "@better-auth/api-key" // [!code highlight]
export const auth = betterAuth({
plugins: [
apiKey() // [!code highlight]
]
})
```
Run the migration or generate the schema to add the necessary fields and tables to the database.
<Tabs items={["migrate", "generate"]}>
<Tab value="migrate">
```package-install
npx auth migrate
```
</Tab>
<Tab value="generate">
```package-install
npx auth generate
```
</Tab>
</Tabs>
See the [Schema](/docs/plugins/api-key/reference#schema) section to add the fields manually.
```ts title="auth-client.ts"
import { createAuthClient } from "better-auth/client"
import { apiKeyClient } from "@better-auth/api-key/client" // [!code highlight]
export const authClient = createAuthClient({
plugins: [
apiKeyClient() // [!code highlight]
]
})
```
You can view the API Key plugin options.
<Callout>API keys can be owned by either a user or an organization, depending on the configuration's references setting.</Callout>
It'll return the ApiKey object which includes the key value for you to use.
Otherwise if it throws, it will throw an APIError.
type verifyApiKey = { /** * Configuration ID to scope verification to. When omitted, the key is validated against its own configuration. / configId?: string /* * The key to verify. / key: string = "your_api_key_here" /* * The permissions to verify. Optional. */ permissions?: Record<string, string[]> }
</APIMethod>
#### Result
```ts
type Result = {
valid: boolean;
error: { message: string; code: string } | null;
key: Omit<ApiKey, "key"> | null;
};
You'll receive everything about the API key details, except for the key value itself.
If it fails, it will throw an APIError.
type Result = Omit<ApiKey, "key">;
If fails, throws APIError.
Otherwise, you'll receive the API Key details, except for the key value itself.
If fails, throws APIError.
Otherwise, you'll receive:
type Result = {
success: boolean;
};
If fails, throws APIError.
Otherwise, you'll receive a paginated response:
type Result = {
apiKeys: Omit<ApiKey, "key">[];
total: number;
limit?: number;
offset?: number;
};
// Get first 10 API keys for the current user
const result = await authClient.apiKey.list({
query: { limit: 10 }
});
// Get second page (10 items per page)
const page2 = await authClient.apiKey.list({
query: { limit: 10, offset: 10 }
});
// Sort by creation date (newest first)
const sorted = await authClient.apiKey.list({
query: { sortBy: "createdAt", sortDirection: "desc" }
});
// Combined pagination and sorting
const combined = await authClient.apiKey.list({
query: {
limit: 20,
offset: 0,
sortBy: "name",
sortDirection: "asc"
}
});
// List organization-owned keys
const orgKeys = await authClient.apiKey.list({
query: { organizationId: "org_123" }
});
// List organization keys with specific config
const orgPublicKeys = await authClient.apiKey.list({
query: {
organizationId: "org_123",
configId: "public"
}
});
This function will delete all API keys that have an expired expiration date.
<APIMethod path="/api-key/delete-all-expired-api-keys" method="POST" isServerOnly> ```ts type deleteAllExpiredApiKeys = { } ``` </APIMethod> <Callout> We automatically delete expired API keys every time any apiKey plugin endpoints were called, however they are rate-limited to a 10 second cool down each call to prevent multiple calls to the database. </Callout>