Summary
Every request to the buildBundles relationship of a build returns HTTP 403,
regardless of the build's age or state, even with an Admin-role App Store Connect
API key. This blocks access to buildBundleFileSizes, which I need to read the
app's download/install size.
Error response
GET https://api.appstoreconnect.apple.com/v1/builds/{buildId}/buildBundles
HTTP/1.1 403 Forbidden { "errors": [ { "status": "403", "code": "FORBIDDEN_ERROR", "title": "The given operation is not allowed", "detail": "The relationship 'buildBundles' has no allowed operations defined." } ] }
Environment
- App Store Connect API (JWT, ES256)
- API key role: Admin (Team key)
- JWT payload contains only iss / iat / exp / aud (aud = "appstoreconnect-v1"),
no
scopefield - Organization account
What works (same key, same token)
- GET /v1/builds?filter[app]={appId}&limit=5&sort=-uploadedDate → 200 OK
- GET /v1/apps/{appId}/builds → 200 OK
- GET /v1/appStoreVersions/{id}?include=app,build → 200 OK
So the token itself is valid and can read builds and app store versions.
What fails
- GET /v1/builds/{buildId}/buildBundles → 403 (above)
Minimal reproduction (curl)
1) List builds — WORKS (200), returns valid build IDs
curl -s
-H "Authorization: Bearer $JWT"
"https://api.appstoreconnect.apple.com/v1/builds?filter[app]=<APP_ID>&limit=1&sort=-uploadedDate"
2) Read buildBundles for that build — FAILS (403)
curl -s
-H "Authorization: Bearer $JWT"
"https://api.appstoreconnect.apple.com/v1/builds/<BUILD_ID>/buildBundles"
-> 403 FORBIDDEN_ERROR:
"The relationship 'buildBundles' has no allowed operations defined."
$JWT is an ES256 token, aud=appstoreconnect-v1, NO scope claim.
Steps to reproduce
- Generate an ES256 JWT with an Admin-role key (no
scopein payload). - List builds for an app — succeeds, returns valid build IDs.
- For ANY returned build ID, GET /v1/builds/{buildId}/buildBundles — always 403.
What I have already ruled out
- Role: the key is Admin, not Developer. Still 403.
- Build age/state: tested the newest build (uploaded today, processingState = VALID) and builds from several years ago — all return 403.
- JWT scope: the token has no
scopeclaim (verified by decoding it), so it is not scope-restricted. Still 403. - Token validity: the same token successfully reads /v1/builds and /v1/appStoreVersions.
- Malformed URL / double slash: I verified the request URL is exactly
https://api.appstoreconnect.apple.com/v1/builds/{id}/buildBundleswith a single slash after the host (no.com//v1). A related thread traced a 403 to a double-slash URL breaking a scoped token (https://developer.apple.com/forums/thread/820203), but that does not apply here: my URL is well-formed AND my token has no scope.
Questions
- Is the
buildBundlesrelationship (andbuildBundleFileSizes) actually supported via the public App Store Connect API for organization accounts? - If yes, what specific configuration (key type, role, account setting, or
entitlement) is required to make
GET /v1/builds/{id}/buildBundlesreturn 200 instead of 403? - Is there any alternative endpoint to retrieve a build's download/install size (the "size" Apple pushes to the developer, e.g. "206.6 MB, Wi-Fi required")?
Thanks in advance.
Found a workaround: direct access to buildBundles is blocked (403 "has no allowed operations defined"), but you can still get it via include.
Working chain:
GET /v1/builds/{buildId}?include=buildBundles — the bundle comes back in the included array
GET /v1/buildBundles/{bundleId}/buildBundleFileSizes — per-device download/install sizes
The include step is what bypasses the 403. Works with both Admin and App Manager keys.