App Store Connect API 令牌生成器
拖入你的 AuthKey_XXXXXXXXXX.p8,填写 Key ID 和 Issuer ID(或选择个人密钥),选一个不超过 20 分钟的有效期,就能得到 App Store Connect API 用的 ES256 签名 JWT,并看到头部、载荷和一条用来测试的 curl 命令。签名由你的浏览器用 Web Crypto 完成:密钥不上传、不保存,本页不发出任何网络请求。
密钥只留在本页
- •.p8 密钥由你自己的浏览器读取并签名,不会上传;使用期间本页不发出任何网络请求。
- •不保存任何内容:没有 Cookie,也不写入本地存储。刷新页面密钥就被清除。
- •用完请关闭这个标签页。令牌在 exp 时间之前一直有效,关掉页面也一样,所以别分享它,有效期尽量设短。
头部和载荷字段、aud 以及有效期限制均摘自苹果文档《Generating Tokens for API Requests》,核对日期 2026-10-30。
1. 你的私钥
把 AuthKey_XXXXXXXXXX.p8 文件拖到这里
也可以打开文件,或在下面粘贴文件内容。Key ID 会按文件名替你填好。
2. 密钥信息
在 App Store Connect 中密钥旁边显示,例如 2X9R4HXF34。
显示在“用户和访问 > 集成”页面顶部,例如 57246542-96fe-1a63-e053-0824d011072a。
对大多数请求,苹果拒绝有效期超过 20 分钟的令牌。选够用的最短时间:单次请求 2 分钟就够。
只有当 scope 里全部是苹果允许的资源(Xcode Cloud、源代码管理、测试结果、功耗与性能指标)上的 GET 请求时,才能选更长的有效期。
方法、路径和可选的查询串,例如 GET /v1/apps?filter[platform]=IOS。设置 scope 后,App Store Connect 只对匹配的请求接受这个令牌;比较时忽略 limit、cursor 和 sort。
3. 你的令牌
签名前请修正
- •请填写 Key ID。
- •请填写 Issuer ID,或切换为个人密钥。
填好密钥和信息后点签名,令牌会显示在这里。
它是怎么工作的
- •头部按苹果规定为 {"alg": "ES256", "kid": 你的 Key ID, "typ": "JWT"}。团队密钥的载荷包含 iss(Issuer ID)、iat、exp 和 aud "appstoreconnect-v1";个人密钥的载荷用 sub "user" 代替 iss。
- •iat 取本设备当前时间(Unix 秒),exp 等于 iat 加上你选的有效期。除非 scope 符合苹果的长期令牌条件,表单最多只允许 20 分钟。
- •.p8 文件按 PKCS#8 PEM 读取,确认是 P-256 椭圆曲线密钥后,以不可导出的方式导入 Web Crypto,用 ECDSA P-256 + SHA-256 对 base64url(header).base64url(payload) 签名。
- •Web Crypto 返回的签名就是原始的 R 和 S(64 字节),正是 JWT 的 ES256 要求的格式,所以直接使用。很多库输出 DER 格式签名,是 401 错误的常见原因;本页不会有这个问题。
- •添加 scope 后,令牌只对这些请求有效。curl 命令使用第一个 GET 项;没有 scope 时用 GET /v1/apps。
它做不到的事
- •它不会替你调用 App Store Connect。把 curl 命令或令牌复制到你自己的工具里使用。
- •它不保存也不续期令牌。脚本或 CI 任务应在任务里用自己的代码生成令牌,密钥放在该环境的密钥存储中。
- •它无法确认 Key ID、Issuer ID 是否属于你,也无法确认密钥的角色是否允许该请求,这些由 App Store Connect 在调用时判断。
- •它无法吊销令牌。令牌泄露时,请在 App Store Connect 吊销密钥;令牌在过期前一直有效。
- •它需要未经改动的 PKCS#8 .p8 文件。“EC PRIVATE KEY” 格式的文件需先转换(页面会给出命令)。
常见问题
- 把 App Store Connect 私钥放进网页安全吗?
- 前提是网页绝不把它发出去,本页正是如此:密钥只在你的浏览器标签页里由 Web Crypto 读取和使用,以不可导出的方式导入,不保存任何内容;页面的内容安全策略只允许连接本站,而签名期间本页也不发出任何请求。但仍应像对待任何机密一样:只在自己的电脑上用,用完关闭标签页,有效期尽量短。
- App Store Connect 令牌最长能用多久?
- 大多数请求为 20 分钟:exp 比 iat 晚超过 20 分钟的令牌会被苹果拒绝。只有当令牌带有 scope、每一项都是 GET 请求、且资源都在苹果的名单里(如 Xcode Cloud 构建、工作流、产品、源代码仓库、测试结果、功耗与性能指标)时,苹果才接受最长六个月的令牌。
- 团队密钥和个人密钥有什么区别?
- 团队密钥在“用户和访问 > 集成”中创建,令牌包含 iss(Issuer ID)。个人密钥在你自己的个人资料页创建,没有 Issuer ID,令牌改用值为 "user" 的 sub。两者都使用 ES256、kid 头部和 aud "appstoreconnect-v1"。
- 为什么会收到 401 NOT_AUTHORIZED?
- 常见原因:kid 与签名的密钥不对应;团队密钥的 Issuer ID 错误或缺失;有效期超过 20 分钟;设备时钟不准导致 iat 或 exp 异常;签名是 DER 格式而不是原始 R 和 S;或者 scope 与请求不匹配。本页可以排除签名格式和有效期的问题。
- scope 声明有什么用?
- 它把令牌限制在你列出的请求上,每项写成方法、路径和可选的查询串,例如 GET /v1/apps?filter[platform]=IOS。请求与任何一项都不匹配时,App Store Connect 拒绝该令牌;比较时忽略 limit、cursor 和 sort。没有 scope 时,令牌可用于密钥角色允许的任何请求。
- 每个请求都要生成新令牌吗?
- 不用。苹果建议在过期前用同一个签名令牌发多个请求。长时间运行的任务应每隔一段时间签一个新令牌,而不是生成一个有效期很长的令牌。