App Store Connect API 密钥:Issuer ID、Key ID 和 .p8
命令行上传、CI、脚本、拉销售报表、让编程 Agent 操作 App Store Connect,第一步都是同一件事:一把 App Store Connect API 密钥。这篇讲清楚怎么创建、三样东西各填在哪、该给它什么职能。
三样东西:Issuer ID、Key ID 和 .p8
API 密钥分两半:公钥留在 Apple,私钥由你下载,文件名是 AuthKey_<Key ID>.p8。每次请求 API 时,用私钥签一个短时有效的令牌(JWT)。用到的三样东西必须是同一套:
| 名称 | 样子 | 在哪里 |
|---|---|---|
| Issuer ID | 57246542-96fe-1a63-e053-0824d011072a |
“用户和访问” ›“集成”页面顶部,旁边有“拷贝” |
| Key ID | 2X9R4HXF34(10 位) |
密钥所在的那一行 |
| 私钥 | AuthKey_2X9R4HXF34.p8 |
你下载的文件,Apple 不留副本 |
这种密钥只能用于 App Store Connect API。同在“集成”页面里的“App 内购买项目”密钥是另一类,给 App Store Server API 和订阅优惠用,两者不能混用。
团队密钥还是个人密钥
- 团队密钥:能访问账户里的所有 App,权限由你给密钥选的职能决定,不能只限定部分 App。只有账户持有人和“管理”职能的成员能创建。
- 个人密钥:权限和创建它的那个人一样,每人同一时间只能有一把。它不能用 Provisioning 相关接口,不能拉销售和财务报告,也不能用于 notarytool。
要拉销售或财务报表,或者希望有人离开团队后密钥照常能用,就选团队密钥。
第一次用之前:请求访问权限
第一次使用时,要由账户持有人在“用户和访问” ›“集成”里点“请求访问权限”,勾选同意条款后提交。Apple 会逐个审核。批准之后,账户持有人和“管理”职能的成员就能创建团队密钥了。
创建团队密钥
- 打开 App Store Connect 的“用户和访问”,点“集成”,默认就在 App Store Connect API 下。
- 点“团队密钥”。
- 点“生成 API 密钥”;已经有密钥的话,点添加按钮(+)。
- 填一个名称,只给自己看,比如写上用它的工具或机器。
- 在“访问”下选择密钥的职能,见下一节。
- 点“生成”,新密钥会带着 Key ID 出现在列表里。
- 点“下载 API 密钥”,把
.p8收好。下载过一次,链接就不再出现。
密钥生成后,名称和职能都不能改。要改,只能撤销后重新生成。
什么工作选什么职能
密钥的职能(也常叫“角色”)和团队成员的职能是同一套,够用就好。下表依据 Apple 的职能权限,只算“完全访问”,不算“只读访问”:
| 要做的事 | 需要的职能 |
|---|---|
| 上传构建 | App 管理或开发者(均需有“证书、标识符和描述文件”访问权限) |
| 提交审核、发布版本、分阶段发布 | App 管理 |
| 创建、编辑和提交 App 内购买项目 | App 管理 |
| TestFlight 构建和外部测试组 | App 管理 |
| TestFlight 内部测试组 | App 管理、开发者或营销 |
| 销售和趋势报告 | 财务,或有报告访问权限的销售 |
| 付款和财务报告 | 财务 |
| 查看用户评论 | App 管理、开发者、营销或客户支持 |
| 回复用户评论 | 客户支持 |
大多数情况套这两种就够:负责上传、分发给外部测试员和提审的 CI 机器给“App 管理”;只读销售和付款的看板或脚本给“财务”。两件事都要做的工具,两个职能都得有。“管理”职能什么都能做,所以更不该放在构建服务器上。
私钥怎么保管
- 放进密码管理器或钥匙串,别放进代码仓库。Apple 的原话是:不要分享密钥,不要存进代码库,也不要放进客户端代码。
- 编程 Agent 能读到项目里的所有文件,密钥文件请放在 Agent 工作目录之外。
- 命令行工具会在固定位置找密钥。比如
altool会在~/.appstoreconnect/private_keys/等目录里找AuthKey_<Key ID>.p8。
签一个 JWT
每个请求都带 Authorization: Bearer <token>,令牌是用 ES256 签名的 JWT:
- 头部:
alg为ES256,kid为 Key ID,typ为JWT。 - 载荷:
iss为 Issuer ID,iat为当前时间,exp最多比iat晚 20 分钟,aud为appstoreconnect-v1。可选的scope能把令牌限定在你列出的请求上。 - 个人密钥不用
iss,改用sub,值为user。
用 Apple 自带的 CryptoKit,十几行就够。存成 jwt.swift,和密钥文件放在同一个文件夹,运行 swift jwt.swift:
import CryptoKit
import Foundation
let keyID = "2X9R4HXF34" // Key ID
let issuerID = "57246542-96fe-1a63-e053-0824d011072a" // Issuer ID
let pem = try String(contentsOfFile: "AuthKey_\(keyID).p8", encoding: .utf8)
func base64URL(_ data: Data) -> String {
data.base64EncodedString()
.replacingOccurrences(of: "+", with: "-")
.replacingOccurrences(of: "/", with: "_")
.replacingOccurrences(of: "=", with: "")
}
let now = Int(Date().timeIntervalSince1970)
let header = #"{"alg":"ES256","kid":"\#(keyID)","typ":"JWT"}"#
let payload = #"{"iss":"\#(issuerID)","iat":\#(now),"exp":\#(now + 1200),"aud":"appstoreconnect-v1"}"#
let input = base64URL(Data(header.utf8)) + "." + base64URL(Data(payload.utf8))
let key = try P256.Signing.PrivateKey(pemRepresentation: pem)
let signature = try key.signature(for: Data(input.utf8))
print(input + "." + base64URL(signature.rawRepresentation))
试一下:
curl -H "Authorization: Bearer $(swift jwt.swift)" https://api.appstoreconnect.apple.com/v1/apps
签名要用 64 字节的原始格式(rawRepresentation),不是 DER。令牌不用每次请求都重签,过期前可以一直复用;只发一次请求的话,Apple 建议有效期短到两分钟就行。
报错怎么查
- 401 Unauthorized:Apple 的状态码表里没有列出它,实际使用中它表示令牌没被接受。按 Apple 的令牌规则逐项核对:Key ID、Issuer ID 和
.p8属于同一把密钥;exp最多比iat晚 20 分钟(只有部分限定范围的只读请求允许更长);本机时间准确;aud为appstoreconnect-v1;个人密钥的令牌用sub而不是iss。 - 403 Forbidden:Apple 文档列出的原因是密钥已撤销、令牌格式不对,或者这个操作不在密钥职能的权限内。典型例子:只有“App 管理”职能的密钥去拉销售报告。
- 429 Too Many Requests:限额按每把密钥、滚动一小时计算。每个响应都带
X-Rate-Limit头,写着上限和剩余次数。
撤销和更换
“用户和访问” ›“集成” ›“团队密钥”,点“编辑”,选中密钥后点“撤销密钥”。撤销后无法恢复,已撤销的密钥会在列表里保留 30 天。想无缝更换:先建新密钥,把工具都换过去,再撤销旧的。
在 SwiftSales 里用这把密钥
SwiftSales 的两部分都用你的团队密钥:仪表盘背后的销售和财务报表,以及 Agent 通过它的 App Store Connect MCP 服务器替你做的 App Store Connect 工作。
用哪把密钥、选哪个职能
- 团队密钥。 销售和财务报表只能用团队密钥读取,个人密钥不行。
- 推荐“财务”加“App 管理”。 “财务”能读取财务报表,财月显示的是 Apple 实际结算的金额;“App 管理”让 Agent 能上传构建、安排 TestFlight、提审、发布和创建 App 内购买项目。
- 只选“财务”,仪表盘就够用了。以后想让 Agent 帮你发布,再加一把发布密钥:另一把选了“App 管理”的团队密钥,在 Mac 上的 SwiftSales 里到“设置 › 团队”添加。发布密钥只用于发布相关的工作。
- **“销售”**职能加上报告访问权限,也能读取销售数据,这时财月金额根据每日报表估算。
密钥做不了某件事时,SwiftSales 会告诉你该加哪个职能。在 App 里怎么操作,见创建团队密钥。
密钥存在哪里
.p8 文件只需导入一次,再填上 Issuer ID 和 Vendor 编号;文件保留原名时,SwiftSales 会自动填好 Key ID。密钥保存在你的钥匙串里;打开 iCloud 同步后(永久高级版的功能,免费试用期间也可以使用),你的其他 iPhone、iPad 和 Mac 也能使用;除此之外,它哪儿也不去。SwiftSales 在你的设备上签名每个请求、直接和 Apple 通信,所以密钥不用放进任何项目文件夹,Agent 也看不到它。




连上之后能看到什么
SwiftSales 直接从 Apple 下载你的报表。总览把每天关心的问题各放在一张卡片上:任意时间段的收入、下载量、新付费用户、活跃订阅和 MRR,以及 Apple 下一次什么时候打款。主屏幕和锁定屏幕小组件、Mac 菜单栏和每天一条通知,显示最新一天的数据。完整介绍见《SwiftSales 来了》。




Agent 能用它做什么
在 Mac 上的 SwiftSales 里打开 Agent 接入,Claude Code、Codex、Cursor、Claude 或 Xcode 就能通过 SwiftSales 使用同一把密钥:回答关于销售和评论的问题,上传构建,安排 TestFlight,填写商店页面,提交审核和发布。每个 Agent 默认是“只读”,级别和能看哪些 App 由你决定,提交审核和发布都要你在 Mac 上批准。用 Claude Code 上架 App Store 按步骤走完一次发布,每一步都有手动和用 SwiftSales 两种做法。
- 让 Agent 把 App 发上去Claude Code、Codex、Cursor、Claude 或 Xcode 通过你 Mac 上的 SwiftSales 上传构建、安排 TestFlight、填写商店页面并提交审核。
- 销售数据一眼看清iPhone、iPad 和 Mac 上的仪表盘,主屏幕和锁定屏幕小组件,Mac 菜单栏,每天一条通知。
- 你的密钥,你来批准团队密钥保存在你的钥匙串里,Agent 看不到。提交审核和发布都要你在 Mac 上批准。
- 直接来自 Apple报表从 Apple 直接到你的设备和你自己的 iCloud,我们的服务器看不到它们。你连接的 Agent 只能读取你允许的数据,并交给它所用的 AI 服务。
免费下载 · 7 天免费试用 · 永久高级版 US$9.99
一次购买,无需订阅。支持家人共享。