# API 密钥 (/docs/plugins/api-key)

Better Auth 的 API 密钥插件。



API 密钥插件允许您为应用程序创建和管理 API 密钥。它通过验证 API 密钥来认证和授权 API 请求。

## 功能 [#功能]

* 创建、管理和验证 API 密钥
* [内置的速率限制](/docs/plugins/api-key/advanced#速率限制)
* [自定义过期时间、剩余计数和补充系统](/docs/plugins/api-key/advanced#剩余额度补充与过期)
* [API 密钥的元数据](/docs/plugins/api-key/advanced#元数据)
* 自定义前缀
* [来自 API 密钥的会话](/docs/plugins/api-key/advanced#来自-api-密钥的会话)
* [二级存储支持](/docs/plugins/api-key/advanced#存储模式) 用于高性能的 API 密钥查找
* [多个配置](/docs/plugins/api-key/advanced#多配置支持) 用于不同类型的 API 密钥
* [组织拥有的 API 密钥](/docs/plugins/api-key/advanced#组织拥有的-api-密钥)，以及用户拥有的密钥

## 安装 [#安装]

<Steps>
  <Step>
    ### 安装插件 [#安装插件]

    <CodeBlockTabs defaultValue="npm" groupId="persist-install">
      <CodeBlockTabsList>
        <CodeBlockTabsTrigger value="npm">
          npm
        </CodeBlockTabsTrigger>

        <CodeBlockTabsTrigger value="pnpm">
          pnpm
        </CodeBlockTabsTrigger>

        <CodeBlockTabsTrigger value="yarn">
          yarn
        </CodeBlockTabsTrigger>

        <CodeBlockTabsTrigger value="bun">
          bun
        </CodeBlockTabsTrigger>
      </CodeBlockTabsList>

      <CodeBlockTab value="npm">
        ```bash
        npm install @better-auth/api-key
        ```
      </CodeBlockTab>

      <CodeBlockTab value="pnpm">
        ```bash
        pnpm add @better-auth/api-key
        ```
      </CodeBlockTab>

      <CodeBlockTab value="yarn">
        ```bash
        yarn add @better-auth/api-key
        ```
      </CodeBlockTab>

      <CodeBlockTab value="bun">
        ```bash
        bun add @better-auth/api-key
        ```
      </CodeBlockTab>
    </CodeBlockTabs>
  </Step>

  <Step>
    ### 将插件添加到服务器 [#将插件添加到服务器]

    ```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]
        ]
    })
    ```
  </Step>

  <Step>
    ### 迁移数据库 [#迁移数据库]

    运行迁移或生成架构以向数据库添加必要的字段和表。

    <Tabs items="[&#x22;migrate&#x22;, &#x22;generate&#x22;]">
      <Tab value="migrate">
        <CodeBlockTabs defaultValue="npm" groupId="persist-install">
          <CodeBlockTabsList>
            <CodeBlockTabsTrigger value="npm">
              npm
            </CodeBlockTabsTrigger>

            <CodeBlockTabsTrigger value="pnpm">
              pnpm
            </CodeBlockTabsTrigger>

            <CodeBlockTabsTrigger value="yarn">
              yarn
            </CodeBlockTabsTrigger>

            <CodeBlockTabsTrigger value="bun">
              bun
            </CodeBlockTabsTrigger>
          </CodeBlockTabsList>

          <CodeBlockTab value="npm">
            ```bash
            npx auth migrate
            ```
          </CodeBlockTab>

          <CodeBlockTab value="pnpm">
            ```bash
            pnpm dlx auth migrate
            ```
          </CodeBlockTab>

          <CodeBlockTab value="yarn">
            ```bash
            yarn dlx auth migrate
            ```
          </CodeBlockTab>

          <CodeBlockTab value="bun">
            ```bash
            bun x auth migrate
            ```
          </CodeBlockTab>
        </CodeBlockTabs>
      </Tab>

      <Tab value="generate">
        <CodeBlockTabs defaultValue="npm" groupId="persist-install">
          <CodeBlockTabsList>
            <CodeBlockTabsTrigger value="npm">
              npm
            </CodeBlockTabsTrigger>

            <CodeBlockTabsTrigger value="pnpm">
              pnpm
            </CodeBlockTabsTrigger>

            <CodeBlockTabsTrigger value="yarn">
              yarn
            </CodeBlockTabsTrigger>

            <CodeBlockTabsTrigger value="bun">
              bun
            </CodeBlockTabsTrigger>
          </CodeBlockTabsList>

          <CodeBlockTab value="npm">
            ```bash
            npx auth generate
            ```
          </CodeBlockTab>

          <CodeBlockTab value="pnpm">
            ```bash
            pnpm dlx auth generate
            ```
          </CodeBlockTab>

          <CodeBlockTab value="yarn">
            ```bash
            yarn dlx auth generate
            ```
          </CodeBlockTab>

          <CodeBlockTab value="bun">
            ```bash
            bun x auth generate
            ```
          </CodeBlockTab>
        </CodeBlockTabs>
      </Tab>
    </Tabs>

    请参阅 [架构](/docs/plugins/api-key/reference#模式) 部分以手动添加字段。
  </Step>

  <Step>
    ### 添加客户端插件 [#添加客户端插件]

    ```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]
        ]
    })
    ```
  </Step>
</Steps>

## 使用方法 [#使用方法]

您可以查看 [API 密钥插件选项](/docs/plugins/api-key/reference#api-密钥插件选项)。

### 创建 API 密钥 [#创建-api-密钥]

**Endpoint:** `POST /api-key/create`

### Client Side

> **Note:** 您可以改用服务器方法来调整更具体的 API 密钥配置。

```ts
const { data, error } = await authClient.apiKey.create({
    configId, // 要使用的配置 ID。如果未提供，则使用默认配置。
    name: 'project-api-key', // API 密钥的名称。
    expiresIn: 60 * 60 * 24 * 7, // API 密钥的过期时间（以秒为单位）。
    organizationId: "org-id", // 拥有该 API 密钥的组织 ID。 对于 `references: "organization"` 的配置是必需的。
    prefix: 'project-api-key', // API 密钥的前缀。
    metadata: { someKey: 'someValue' }, // API 密钥的元数据。
});
```

### Server Side

> **Note:** 如果您在服务器上创建 API 密钥，但无法访问标头，则必须传入 `userId` 属性（适用于用户拥有的密钥）。对于组织拥有的密钥，请传入 `organizationId`，并同时传入一个有权在该组织中创建密钥的 `userId`。

```ts
const data = await auth.api.createApiKey({
    body: {
        configId, // 要使用的配置 ID。如果未提供，则使用默认配置。
        name: 'project-api-key', // API 密钥的名称。
        expiresIn: 60 * 60 * 24 * 7, // API 密钥的过期时间（以秒为单位）。
        userId: "user-id", // server-only, 拥有该 API 密钥的用户 ID。server-only。 当不使用会话标头时，这是用户拥有的密钥所必需的。
        organizationId: "org-id", // 拥有该 API 密钥的组织 ID。 对于 `references: "organization"` 的配置是必需的。
        prefix: 'project-api-key', // API 密钥的前缀。
        remaining: 100, // server-only, 剩余的请求数量。server-only。
        metadata: { someKey: 'someValue' }, // API 密钥的元数据。
        refillAmount: 100, // server-only, 要补充的剩余计数。server-only。
        refillInterval: 1000, // server-only, 补充 API 密钥的间隔（以毫秒为单位）。server-only。
        rateLimitTimeWindow: 1000, // server-only, 每个请求计数的时间窗口（以毫秒为单位）。一旦达到 `maxRequests`，请求将被拒绝，直到 `timeWindow` 过去，之后 `timeWindow` 将重置。server-only。
        rateLimitMax: 100, // server-only, 在一个窗口内允许的最大请求数。一旦达到 `maxRequests`，请求将被拒绝，直到 `timeWindow` 过去，之后 `timeWindow` 将重置。server-only。
        rateLimitEnabled: true, // server-only, 是否启用速率限制。server-only。
        permissions, // server-only, API 密钥的权限。
    },
});
```

### Type Definition

```ts
type createApiKey = {
    /**
     * 要使用的配置 ID。如果未提供，则使用默认配置。
     */
    configId?: string
    /**
     * API 密钥的名称。
     */
    name?: string = 'project-api-key'
    /**
     * API 密钥的过期时间（以秒为单位）。
     */
    expiresIn?: number = 60 * 60 * 24 * 7
    /**
     * 拥有该 API 密钥的用户 ID。server-only。
     * 当不使用会话标头时，这是用户拥有的密钥所必需的。
     * @serverOnly
     */
    userId?: string = "user-id"
    /**
     * 拥有该 API 密钥的组织 ID。
     * 对于 `references: "organization"` 的配置是必需的。
     */
    organizationId?: string = "org-id"
    /**
     * API 密钥的前缀。
     */
    prefix?: string = 'project-api-key'
    /**
     * 剩余的请求数量。server-only。
     * @serverOnly
     */
    remaining?: number = 100
    /**
     * API 密钥的元数据。
     */
    metadata?: any | null = { someKey: 'someValue' }
    /**
     * 要补充的剩余计数。server-only。
     * @serverOnly
     */
    refillAmount?: number = 100
    /**
     * 补充 API 密钥的间隔（以毫秒为单位）。server-only。
     * @serverOnly
     */
    refillInterval?: number = 1000
    /**
     * 每个请求计数的时间窗口（以毫秒为单位）。一旦达到 `maxRequests`，请求将被拒绝，直到 `timeWindow` 过去，之后 `timeWindow` 将重置。server-only。
     * @serverOnly
     */
    rateLimitTimeWindow?: number = 1000
    /**
     * 在一个窗口内允许的最大请求数。一旦达到 `maxRequests`，请求将被拒绝，直到 `timeWindow` 过去，之后 `timeWindow` 将重置。server-only。
     * @serverOnly
     */
    rateLimitMax?: number = 100
    /**
     * 是否启用速率限制。server-only。
     * @serverOnly
     */
    rateLimitEnabled?: boolean = true
    /**
     * API 密钥的权限。
     * @serverOnly
     */
    permissions?: Record<string, string[]>
}
```

<Callout>
  API 密钥可以是用户拥有的，也可以是组织拥有的，具体取决于配置中的 

  `references`

   设置。
</Callout>

#### 返回结果 [#返回结果]

返回包含 `key` 值的 `ApiKey` 对象供您使用。
如果发生异常，则抛出 `APIError`。

***

### 验证 API 密钥 [#验证-api-密钥]

**Endpoint:** `POST /api-key/verify`

### Server Side

```ts
const permissions = { // 需要检查的权限是可选的
  projects: ["read", "read-write"],
}
const data = await auth.api.verifyApiKey({
    body: {
        configId, // 用于限定验证范围的配置 ID。省略时，将根据密钥自身的配置进行验证。
        key: "your_api_key_here", // required, 要验证的密钥。
        permissions, // 要验证的权限。可选。
    },
});
```

### Type Definition

```ts
type verifyApiKey = {
    /**
     * 用于限定验证范围的配置 ID。省略时，将根据密钥自身的配置进行验证。
     */
    configId?: string
    /**
     * 要验证的密钥。
     */
    key: string = "your_api_key_here"
    /**
     * 要验证的权限。可选。
     */
    permissions?: Record<string, string[]>
}
```

#### 结果 [#结果]

```ts
type Result = {
  valid: boolean;
  error: { message: string; code: string } | null;
  key: Omit<ApiKey, "key"> | null;
};
```

***

### 获取 API 密钥 [#获取-api-密钥]

**Endpoint:** `GET /api-key/get`

### Client Side

```ts
const { data, error } = await authClient.apiKey.get({
    query: {
        configId, // 用于 API 密钥查找的配置 ID。如果未提供，则使用默认配置。
        id: "some-api-key-id", // required, API 密钥的 ID。
    },
});
```

### Server Side

```ts
const data = await auth.api.getApiKey({
    query: {
        configId, // 用于 API 密钥查找的配置 ID。如果未提供，则使用默认配置。
        id: "some-api-key-id", // required, API 密钥的 ID。
    },
    // This endpoint requires session cookies.
    headers: await headers(),
});
```

### Type Definition

```ts
type getApiKey = {
    /**
     * 用于 API 密钥查找的配置 ID。如果未提供，则使用默认配置。
     */
    configId?: string
    /**
     * API 密钥的 ID。
     */
    id: string = "some-api-key-id"
}
```

#### 返回结果 [#返回结果-1]

返回除 `key` 字段外的所有 API 密钥详细信息。
如果失败，则抛出 `APIError`。

```ts
type Result = Omit<ApiKey, "key">;
```

***

### 更新 API 密钥 [#更新-api-密钥]

**Endpoint:** `POST /api-key/update`

### Client Side

```ts
const { data, error } = await authClient.apiKey.update({
    configId, // 用于 API 密钥查找的配置 ID。如果未提供，则使用默认配置。
    keyId: "some-api-key-id", // required, 要更新的 API 密钥的 ID。
    name: "some-api-key-name", // 密钥的名称。
});
```

### Server Side

```ts
const data = await auth.api.updateApiKey({
    body: {
        configId, // 用于 API 密钥查找的配置 ID。如果未提供，则使用默认配置。
        keyId: "some-api-key-id", // required, 要更新的 API 密钥的 ID。
        userId: "some-user-id", // server-only, 拥有该 API 密钥的用户 ID。server-only。
        name: "some-api-key-name", // 密钥的名称。
        enabled: true, // server-only, API 密钥是否启用。server-only。
        remaining: 100, // server-only, 剩余的请求数量。server-only。
        refillAmount: 100, // server-only, 补充数量。server-only。
        refillInterval: 1000, // server-only, 补充间隔（以毫秒为单位）。server-only。
        metadata: { "key": "value" }, // server-only, API 密钥的元数据。server-only。
        expiresIn: 60 * 60 * 24 * 7, // server-only, API 密钥的过期时间（以秒为单位）。server-only。
        rateLimitEnabled: true, // server-only, 是否启用速率限制。server-only。
        rateLimitTimeWindow: 1000, // server-only, 每个请求计数的时间窗口（以毫秒为单位）。server-only。
        rateLimitMax: 100, // server-only, 在一个窗口内允许的最大请求数。一旦达到 `maxRequests`，请求将被拒绝，直到 `timeWindow` 过去，之后 `timeWindow` 将重置。server-only。
        permissions, // server-only, 更新 API 密钥的权限。server-only。
    },
});
```

### Type Definition

```ts
type updateApiKey = {
    /**
     * 用于 API 密钥查找的配置 ID。如果未提供，则使用默认配置。
     */
    configId?: string
    /**
     * 要更新的 API 密钥的 ID。
     */
    keyId: string = "some-api-key-id"
    /**
     * 拥有该 API 密钥的用户 ID。server-only。
     * @serverOnly
     */
    userId?: string = "some-user-id"
    /**
     * 密钥的名称。
     */
    name?: string = "some-api-key-name"
    /**
     * API 密钥是否启用。server-only。
     * @serverOnly
     */
    enabled?: boolean = true
    /**
     * 剩余的请求数量。server-only。
     * @serverOnly
     */
    remaining?: number = 100
    /**
     * 补充数量。server-only。
     * @serverOnly
     */
    refillAmount?: number = 100
    /**
     * 补充间隔（以毫秒为单位）。server-only。
     * @serverOnly
     */
    refillInterval?: number = 1000
    /**
     * API 密钥的元数据。server-only。
     * @serverOnly
     */
    metadata?: any | null = { "key": "value" }
    /**
     * API 密钥的过期时间（以秒为单位）。server-only。
     * @serverOnly
     */
    expiresIn?: number = 60 * 60 * 24 * 7
    /**
     * 是否启用速率限制。server-only。
     * @serverOnly
     */
    rateLimitEnabled?: boolean = true
    /**
     * 每个请求计数的时间窗口（以毫秒为单位）。server-only。
     * @serverOnly
     */
    rateLimitTimeWindow?: number = 1000
    /**
     * 在一个窗口内允许的最大请求数。一旦达到 `maxRequests`，请求将被拒绝，直到 `timeWindow` 过去，之后 `timeWindow` 将重置。server-only。
     * @serverOnly
     */
    rateLimitMax?: number = 100
    /**
     * 更新 API 密钥的权限。server-only。
     * @serverOnly
     */
    permissions?: Record<string, string[]>
}
```

#### 返回结果 [#返回结果-2]

如果失败，则抛出 `APIError`。
成功时返回 API 密钥详细信息，但不包含 `key` 字段。

***

### 删除 API 密钥 [#删除-api-密钥]

**Endpoint:** `POST /api-key/delete`

> **Note:** 此端点从用户角度尝试删除 API 密钥。它会检查用户 ID 是否与密钥所有者匹配，以确定是否可以删除该密钥。如果您希望在不进行这些检查的情况下删除密钥，我们建议您使用 ORM 直接修改数据库。

### Client Side

```ts
const { data, error } = await authClient.apiKey.delete({
    configId, // 用于 API 密钥查找的配置 ID。如果未提供，则使用默认配置。
    keyId: "some-api-key-id", // required, 要删除的 API 密钥的 ID。
});
```

### Server Side

```ts
const data = await auth.api.deleteApiKey({
    body: {
        configId, // 用于 API 密钥查找的配置 ID。如果未提供，则使用默认配置。
        keyId: "some-api-key-id", // required, 要删除的 API 密钥的 ID。
    },
    // This endpoint requires session cookies.
    headers: await headers(),
});
```

### Type Definition

```ts
type deleteApiKey = {
    /**
     * 用于 API 密钥查找的配置 ID。如果未提供，则使用默认配置。
     */
    configId?: string
    /**
     * 要删除的 API 密钥的 ID。
     */
    keyId: string = "some-api-key-id"
}
```

#### 返回结果 [#返回结果-3]

如果失败，则抛出 `APIError`。
成功时返回：

```ts
type Result = {
  success: boolean;
};
```

***

### 列出 API 密钥 [#列出-api-密钥]

**Endpoint:** `GET /api-key/list`

### Client Side

```ts
const { data, error } = await authClient.apiKey.list({
    query: {
        configId, // 根据配置 ID 进行筛选。如果未提供，则返回所有配置的密钥。
        organizationId, // 要列出密钥的组织 ID。如果提供，则返回组织拥有的密钥。 如果未提供，则返回当前会话用户拥有的密钥。
        limit, // 返回的 API 密钥数量。
        offset, // 分页开始位置（偏移量）。
        sortBy, // 排序字段（例如："createdAt"、"name"、"expiresAt"）。
        sortDirection, // 排序方向。
    },
});
```

### Server Side

```ts
const data = await auth.api.listApiKeys({
    query: {
        configId, // 根据配置 ID 进行筛选。如果未提供，则返回所有配置的密钥。
        organizationId, // 要列出密钥的组织 ID。如果提供，则返回组织拥有的密钥。 如果未提供，则返回当前会话用户拥有的密钥。
        limit, // 返回的 API 密钥数量。
        offset, // 分页开始位置（偏移量）。
        sortBy, // 排序字段（例如："createdAt"、"name"、"expiresAt"）。
        sortDirection, // 排序方向。
    },
    // This endpoint requires session cookies.
    headers: await headers(),
});
```

### Type Definition

```ts
type listApiKeys = {
    /**
     * 根据配置 ID 进行筛选。如果未提供，则返回所有配置的密钥。
     */
    configId?: string
    /**
     * 要列出密钥的组织 ID。如果提供，则返回组织拥有的密钥。
     * 如果未提供，则返回当前会话用户拥有的密钥。
     */
    organizationId?: string
    /**
     * 返回的 API 密钥数量。
     */
    limit?: number
    /**
     * 分页开始位置（偏移量）。
     */
    offset?: number
    /**
     * 排序字段（例如："createdAt"、"name"、"expiresAt"）。
     */
    sortBy?: string
    /**
     * 排序方向。
     */
    sortDirection?: "asc" | "desc"
}
```

#### 返回结果 [#返回结果-4]

如果失败，抛出 `APIError`。
成功时返回分页响应：

```ts
type Result = {
  apiKeys: Omit<ApiKey, "key">[];
  total: number;
  limit?: number;
  offset?: number;
};
```

#### 分页用例 [#分页用例]

```ts
// 获取当前用户的前 10 个 API 密钥
const result = await authClient.apiKey.list({
  query: { limit: 10 }
});

// 获取第二页（每页10条）
const page2 = await authClient.apiKey.list({
  query: { limit: 10, offset: 10 }
});

// 按创建时间排序（最新优先）
const sorted = await authClient.apiKey.list({
  query: { sortBy: "createdAt", sortDirection: "desc" }
});

// 分页和排序结合
const combined = await authClient.apiKey.list({
  query: { 
    limit: 20, 
    offset: 0, 
    sortBy: "name", 
    sortDirection: "asc" 
  }
});

// 列出组织拥有的密钥
const orgKeys = await authClient.apiKey.list({
  query: { organizationId: "org_123" }
});

// 列出指定配置的组织密钥
const orgPublicKeys = await authClient.apiKey.list({
  query: { 
    organizationId: "org_123",
    configId: "public" 
  }
});
```

***

### 删除所有过期的 API 密钥 [#删除所有过期的-api-密钥]

此功能会删除所有已过期的 API 密钥。

**Endpoint:** `POST /api-key/delete-all-expired-api-keys`

### Server Side

```ts
const data = await auth.api.deleteAllExpiredApiKeys();
```

### Type Definition

```ts
type deleteAllExpiredApiKeys = {
}
```

<Callout>
  我们会在每次调用任何 apiKey 插件的接口时自动删除过期密钥，
  但调用频率限制为每 10 秒冷却一次，以防多次访问数据库。
</Callout>

## 后续步骤 [#后续步骤]

<Cards>
  <Card href="/docs/plugins/api-key/advanced" title="高级特性">
    会话、多个配置、组织密钥、存储、速率限制等。
  </Card>

  <Card href="/docs/plugins/api-key/reference" title="参考">
    插件选项、权限和架构。
  </Card>
</Cards>

