# App Store Connect API 密钥（.p8）：创建与使用

> App Store Connect API 密钥（.p8）只能下载一次。本文讲清角色、Issuer ID、Key ID、撤销，以及在 Expo、fastlane 和脚本中的用法。

原始页面：[App Store Connect API 密钥（.p8）：创建与使用](https://devoria.fr/zh-hans/blog/app-store-connect-api-key-p8)
作者：[Mehdi Azizi](https://devoria.fr/zh-hans/mehdi-azizi)
发布：2026-11-04
内容最后修订：2026-11-04


App Store Connect API 密钥能让一个工具（比如 EAS、fastlane、RevenueCat 或你自己的脚本）操作你的账号，不需要你的密码，也不需要双重认证。**Apple 保存密钥的公钥部分，私钥部分是一个 `.p8` 文件，你只能下载一次。** 有了这个文件、Issuer ID 和 Key ID，你就能签发令牌，大多数请求的令牌有效期最多 20 分钟。

我用 Expo 发布自己的 iOS 应用，包括 TradaZen 和 Nolera。一把 App Manager 角色的团队密钥同时供 RevenueCat、我的 Expo 构建，以及一个编辑商店页面的命令行工具使用。本指南依据 2026 年 11 月 3 日重新核对过的 Apple、Expo 和 fastlane 页面。别把它和塞进应用代码里的各类服务密钥搞混：那些内容见 [Expo 应用中的秘密 API 密钥](https://devoria.fr/zh-hans/blog/expo-api-secret-key-security)。

## App Store Connect API 密钥是做什么的

根据 [Apple 的文档](https://developer.apple.com/documentation/appstoreconnectapi/creating-api-keys-for-app-store-connect-api)，App Store Connect API 的每个请求都需要一个 JWT 令牌。令牌由你生成，并用你的私钥签名。这把密钥只能用于这个 API，不能用于 Apple 的其他服务。

它的价值一句话就能说清：**不需要任何人来确认登录。** 用 Apple ID 登录会卡在双重认证上，自动化就无从谈起。[EAS Submit iOS](https://devoria.fr/zh-hans/blog/eas-submit-ios-publish-expo-app-store) 指南展示了它对 Expo 应用提交带来的改变。

## 第一步：申请 API 访问权限

第一把密钥不能直接创建。[App Store Connect 帮助文档](https://developer.apple.com/help/app-store-connect/get-started/app-store-connect-api)写得很明白：**Account Holder 必须先申请 API 访问权限。** 打开 Users and Access，点击 Integrations，再点 Request Access。Apple 会逐个审核申请。

Account Holder 就是注册这个账号的人。如果你是新手，那就是你自己：注册流程见 [Apple 开发者账号](https://devoria.fr/zh-hans/blog/apple-developer-account-price-free-or-99)指南。

## 团队密钥还是个人密钥

Apple 提供两种密钥。下面是它们的区别，整理自[文档](https://developer.apple.com/documentation/appstoreconnectapi/creating-api-keys-for-app-store-connect-api)和 [App Store Connect 帮助](https://developer.apple.com/help/app-store-connect/get-started/app-store-connect-api)：

| 对比项                 | 团队密钥                | 个人密钥           |
| ---------------------- | ----------------------- | ------------------ |
| 谁可以生成             | Account Holder 或 Admin | 几乎所有用户       |
| 可访问的应用           | 全部，无一例外          | 该用户能访问的应用 |
| 权限                   | 所选角色的权限          | 该用户的权限       |
| 密钥数量               | 多把                    | 每人一把有效密钥   |
| 证书和描述文件         | 可以，取决于角色        | 不可以             |
| 销售、财务、notaryTool | 取决于角色              | 不可以             |
| 令牌字段               | `iss` = Issuer ID       | `sub` = `user`     |

按 Apple 的说法，“几乎所有用户”指的是：Account Holder、Admin、App Manager、Customer Support、Developer 和 Marketing，除非 Admin 或 Account Holder 取消了他们生成个人密钥的权限。

**给 Expo 或 fastlane 用，请选团队密钥。** 个人密钥无法访问预配（provisioning）相关的接口，也就是创建证书和描述文件的那些接口。[fastlane 的文档](https://docs.fastlane.tools/app-store-connect-api/)也证实：凡是涉及预配的访问，都需要团队密钥。

## 给密钥分配什么角色

团队密钥无论什么角色，都能访问账号下的所有应用。角色决定它能做什么。**Apple 提醒，Admin 角色的密钥可以创建和删除用户**：请分配能满足用途的最小角色。下面的权限来自 [Apple 的角色表](https://developer.apple.com/help/account/access/roles/)。

| 密钥用途                     | 允许的角色                    |
| ---------------------------- | ----------------------------- |
| 上传构建                     | Admin、App Manager、Developer |
| 管理 TestFlight 构建         | Admin、App Manager            |
| 创建证书和描述文件           | Admin、App Manager            |
| 提交应用审核                 | Admin、App Manager            |
| 导入产品和价格（RevenueCat） | 至少 App Manager              |
| 生成其他团队密钥             | Admin                         |

RevenueCat 那一行来自[它的文档](https://www.revenuecat.com/docs/service-credentials/itunesconnect-app-specific-shared-secret/app-store-connect-api-key-configuration)。而 Expo 的指南[给密钥分配的是 Admin 角色](https://github.com/expo/fyi/blob/main/creating-asc-api-key.md)。在我的应用上，App Manager 就够了：EAS 用它创建分发描述文件，RevenueCat 用它导入产品。

密钥生成后，[名称和角色都不能再修改](https://developer.apple.com/help/app-store-connect/get-started/app-store-connect-api)。想改，只能撤销后重新生成一把。

## 一步步创建团队密钥

你需要 Admin 或 Account Holder 账号。根据 [Apple](https://developer.apple.com/documentation/appstoreconnectapi/creating-api-keys-for-app-store-connect-api)：

1. **打开 Users and Access**，然后进入 Integrations 标签页。
2. **在左栏选择 App Store Connect API**，然后进入 Team Keys 标签页。
3. **点击 Generate API Key**，或者点 + 按钮。
4. **给密钥起个名字。** 名字只给你自己看，不属于密钥本身。按使用它的工具来命名。
5. **在 Access 下选择角色**，然后点击 Generate。
6. **通过 Download API Key 链接下载私钥。**

> 文件一下载完，下载链接就会消失，Apple 也不保留任何副本。关闭页面前先把 `.p8` 存好。

然后记下两个标识。根据 [Apple 关于令牌的页面](https://developer.apple.com/documentation/appstoreconnectapi/generating-tokens-for-api-requests)，**Issuer ID 显示在 Integrations 页面顶部**，旁边有 Copy 按钮。Key ID 在有效密钥列表里：鼠标悬停就会出现 Copy Key ID。账号下所有团队密钥的 Issuer ID 都相同，Key ID 则每把密钥各不相同。

个人密钥更简单：打开你的用户资料，往下滚到 Individual API Key，点击 Generate API Key。同样只能下载一次。

## 保管 .p8 文件

Apple 要求像对待密码一样对待这把密钥：**不要分享，不要放进代码仓库，绝不要写进应用代码。** 我的做法：

- **放在项目之外的文件夹**，或者放进持续集成工具的密钥管理器。
- **把密钥文件夹加进 `.gitignore`**，如果提交期间文件必须暂时放在项目里。
- **严格的文件权限。** 有个 App Store Connect 命令行工具，只要我的 `.p8` 还能被其他账户读取，就拒绝使用它。一条 `chmod 600` 解决了问题。
- **一个工具一把密钥。** Apple 允许[生成多把密钥](https://developer.apple.com/documentation/appstoreconnectapi/creating-api-keys-for-app-store-connect-api)，角色随你选。

最后这一条，我一开始没做到。我那把 App Manager 密钥同时给 RevenueCat、构建和商店页面工具用。要是得撤销它，三个工具会一起挂掉。**如果重来，我会一个工具建一把密钥**，这样能单独停掉一把而不影响其他的。

## 在 Expo 中使用

把密钥交给 EAS 有三种方式：

- **交给 EAS 管理。** `eas credentials --platform ios` 可以创建密钥并保存在 Expo 的服务器上。这是最简单的路。
- **在 `eas.json` 中声明。** `submit` 配置接受 `ascApiKeyPath`、`ascApiKeyIssuerId` 和 `ascApiKeyId`。根据 [eas.json 参考文档](https://docs.expo.dev/eas/json/)，这些字段支持环境变量，比如 `$ASC_API_KEY_PATH`。
- **通过环境变量传入。** [EAS CLI 仓库](https://github.com/expo/eas-cli/blob/main/packages/eas-cli/README.md)记录了 `EXPO_ASC_API_KEY_PATH`、`EXPO_ASC_KEY_ID` 和 `EXPO_ASC_ISSUER_ID`。个人密钥省略 Issuer ID 即可。

构建时有个限制要知道：[Expo 说明](https://docs.expo.dev/build-reference/ios-capabilities/)官方 API 无法关联 App Group、Merchant ID 或 CloudKit 容器。这时需要在本地用你的 Apple ID 登录。我在 Nolera 的小组件 App Group 上就遇到过：密钥启用了这项能力，却没关联上分组。我是在 Apple 开发者网站里手动关联的。**如果能力同步卡住，`EXPO_NO_CAPABILITY_SYNC=1` 可以关闭它**，然后你自己在 App ID 上启用这项能力。构建签名的细节见 [iOS 证书与描述文件](https://devoria.fr/zh-hans/blog/ios-certificate-provisioning-profile-expo)。

## 在 fastlane 中使用

[fastlane](https://docs.fastlane.tools/app-store-connect-api/) 从一个 JSON 文件读取密钥。`key_id`、`issuer_id` 和 `key`（即 `.p8` 的内容）是必填字段，`duration` 和 `in_house` 可选。示例值：

```json
{
  "key_id": "XXXXXXXXXX",
  "issuer_id": "your-issuer-id",
  "key": "-----BEGIN PRIVATE KEY-----\nMIGT...\n-----END PRIVATE KEY-----",
  "duration": 1200,
  "in_house": false
}
```

然后把这个文件传给某个 action，例如 `fastlane pilot distribute --api_key_path fastlane/cle.json`。在 Fastfile 中，`app_store_connect_api_key` action 接受 `key_id`、`issuer_id` 和 `key_filepath`。会话时长不超过 1200 秒，也就是 20 分钟。并非所有 action 都支持：比如 fastlane 指出 `produce` 和 `pem` 无法使用 API 密钥。

## 在你自己的脚本中使用

不借助工具的话，令牌得自己生成。[Apple 规定了做法](https://developer.apple.com/documentation/appstoreconnectapi/generating-tokens-for-api-requests)：

- **头部**：`alg` 为 `ES256`，`kid` 为你的 Key ID，`typ` 为 `JWT`。
- **载荷（团队密钥）**：`iss` 为你的 Issuer ID；`iat` 为创建时间；`exp` 为过期时间；`aud` 为 `appstoreconnect-v1`。
- **载荷（个人密钥）**：用 `sub` 取代 `iss`，值为 `user`。
- **时长**：超过 20 分钟，大多数请求的令牌会被 Apple 拒绝。

用 Python 的话，需要 PyJWT 库及其加密依赖，按[它的文档](https://pyjwt.readthedocs.io/en/stable/installation.html)用 `pip install pyjwt[crypto]` 安装。在 Mac 终端里要加引号：`pip install "pyjwt[crypto]"`，否则 zsh 不认方括号。

```python
import time
import jwt

KEY_ID = "XXXXXXXXXX"
ISSUER_ID = "your-issuer-id"

with open("AuthKey_XXXXXXXXXX.p8") as f:
    private_key = f.read()

now = int(time.time())
token = jwt.encode(
    {"iss": ISSUER_ID, "iat": now, "exp": now + 20 * 60, "aud": "appstoreconnect-v1"},
    private_key,
    algorithm="ES256",
    headers={"kid": KEY_ID, "typ": "JWT"},
)
print(token)
```

然后像 Apple 的示例那样，把它放进 `Authorization` 请求头发送：

```bash
curl -H "Authorization: Bearer $TOKEN" "https://api.appstoreconnect.apple.com/v1/apps"
```

2026 年 11 月 3 日，我用本机生成的一次性密钥运行了这个脚本：令牌的头部和载荷与 Apple 页面一致，ES256 签名也能验证通过。我没有用这把测试密钥去请求 Apple 的 API，因为 Apple 那边并不存在这把密钥。**令牌有效期内请重复使用同一个令牌**：Apple 建议这样做以获得更好的性能。

## 撤销密钥

密钥一旦丢失、泄露，或者某个工具不再使用它，就立刻撤销。根据 [App Store Connect 帮助](https://developer.apple.com/help/app-store-connect/get-started/app-store-connect-api)，使用 Account Holder 或 Admin 账号：

1. 打开 Users and Access，然后进入 Integrations。
2. 选择 Team Keys 或 Individual Keys，然后点击 Edit。
3. 勾选要撤销的密钥，然后点 Revoke Key。
4. 点 Revoke 确认。

**被撤销的密钥永远无法重新启用。** [Apple 会在 Revoked 下显示它](https://developer.apple.com/documentation/appstoreconnectapi/revoking-api-keys) 30 天。之后所有用它的工具都会认证失败。在 Expo 中，报错信息是“[App Store Connect rejected the API authentication credentials](https://github.com/expo/eas-cli/blob/main/packages/build-tools/src/steps/utils/ios/AscApiClient.ts)”。这条信息和其他提交失败的原因，见 [EAS 提交错误及其解决方法](https://devoria.fr/zh-hans/blog/eas-submit-ios-common-errors-fixes)。如果密钥没有泄露，先准备好新密钥再停用旧的。如果已经泄露，Apple 要求立即撤销。

撤销你自己的个人密钥：你的用户资料，Individual API Key，然后 Revoke。

## 我的 .p8 密钥检查清单

- Account Holder 已申请 API 访问权限。
- 用于构建或描述文件的，是团队密钥。
- 角色是满足用途的最小角色，名字标明了使用它的工具。
- `.p8` 存放在仓库之外，权限严格，并有一份加密备份。
- Issuer ID 和 Key ID 另外记录，不和文件放在一起。
- 每个工具各用一把密钥，可以单独撤销。

## 自动化发布，又不暴露密钥

密钥只是整个流程中的一环。[iOS & Android Kit](https://devoria.fr/zh-hans/kits/ios) 以我自己应用的起步代码为基础（包括订阅），分四个阶段带你走到 App Store，节奏由你掌握。如果你要用这把密钥接入 RevenueCat，完整配置见 [RevenueCat 与 iOS 应用内订阅](https://devoria.fr/zh-hans/blog/revenuecat-ios-in-app-subscription-setup)。

如果你正在准备第一次上架，[做一下免费诊断](https://devoria.fr/zh-hans/diagnostic)：它会告诉你真正卡住你的是什么，并把我的防 Apple 拒审清单发给你。[在 App Store 上发布应用](https://devoria.fr/zh-hans/expertise/publish-an-app-on-the-app-store)页面梳理了每一步，从商店页面到审核通过。

## 常见问题

### 如何创建 App Store Connect API 密钥？

先由 Account Holder 申请 API 访问权限。然后 Admin 打开 Users and Access，进入 Integrations 标签页，选择 App Store Connect API、Team Keys。点击 Generate API Key，填写名称、选择角色，生成密钥，再下载 `.p8` 文件。

### 丢失的 .p8 密钥能重新下载吗？

不能。文件只能下载一次，Apple 也不保留副本。撤销丢失的密钥，再生成一把新的，并更新所有用到它的工具。

### Issuer ID 和 Key ID 在哪里找？

在 App Store Connect 的 Users and Access 菜单，Integrations 标签页。Issuer ID 显示在页面顶部，Key ID 在有效密钥列表里。个人密钥不使用 Issuer ID。

### Expo 使用的密钥该分配什么角色？

Expo 的指南给的是 Admin 角色。根据 Apple 的角色表，App Manager 就足以上传构建、创建证书和描述文件。我用于 Expo 构建的密钥就是这个角色。

### API 密钥的角色可以修改吗？

不可以。密钥创建后，Apple 不允许修改名称或角色。撤销它，再用正确的角色生成一把新的。

### App Store Connect API 密钥会过期吗？

Apple 的页面没有提到密钥会过期，只提到撤销。会过期的是用它签发的令牌，大多数请求的令牌最长 20 分钟后过期。


## 你的项目

[Review Kit](https://devoria.fr/zh-hans/kits/app-review)：我的 App Store 审核清单、我被 Apple 拒审后的修正方案、Google Play 审核清单，以及三个 Claude Code skill。¥369。

[iOS & Android Kit](https://devoria.fr/zh-hans/kits/ios)：用 Claude Code 打造你的 iPhone 和 Android 应用：我自己应用的起步代码、上架商店的完整流程，以及全部工具包。¥739。

[诊断：你离自己的 iPhone 应用还差什么](https://devoria.fr/zh-hans/diagnostic)：7 个问题，60 秒：看清真正阻碍你发布 iPhone 应用的原因，拿到你的 4 步路线和适合你的套件。
