RSS

App Store Connect API 키: Team Key로 할 수 있는 것과 없는 것

새 앱을 App Store Connect에 등록하면서, 화면을 계속 왔다 갔다 하기 귀찮아서 API로 자동화할 수 있는 부분은 자동화해보려고 했습니다. 결론부터 적으면 절반만 성공했습니다. 조회·수정은 되는데, 앱 생성 자체는 API로 안 됩니다.

인증부터

App Store Connect API는 OAuth가 아니라 자체 서명한 JWT로 인증합니다. 필요한 건 셋입니다.

  • Key ID: 키를 만들면 발급되는 10자리 식별자 (예: AuthKey_XXXXXXXXXX.p8 파일명에 들어있음)
  • Issuer ID: 계정 전체에 하나, UUID 형태. App Store Connect → 사용자 및 접근 → 통합 탭 상단에 있습니다
  • .p8 개인키 파일: 생성 시점에 딱 한 번만 다운로드할 수 있습니다. 잃어버리면 키를 새로 만들어야 합니다

Key ID·Issuer ID는 식별자일 뿐 비밀이 아닙니다(OAuth의 Client ID 같은 개념). 보호해야 하는 건 .p8 파일 하나뿐입니다.

JWT는 직접 서명하면 됩니다. Node 기준으로 외부 라이브러리 없이 crypto.sign만으로 됩니다. ES256 알고리즘이라 dsaEncoding: 'ieee-p1363' 옵션을 꼭 줘야 합니다(안 주면 Node 기본값인 DER 인코딩으로 서명되는데, Apple은 raw R||S 형식을 기대합니다).

const signature = crypto.sign('sha256', Buffer.from(signingInput), {
  key: privateKeyPem,
  dsaEncoding: 'ieee-p1363',
});

팀 키와 개별 키

App Store Connect API 키는 두 종류입니다.

  • 팀 키(Team Key): 조직 계정 자체에 속합니다. 역할을 직접 지정하고, 만든 사람이 팀에서 빠져도 유지됩니다. CI·자동화용입니다. 계정당 최대 50개까지 활성 상태로 둘 수 있습니다.
  • 개별 키(Individual Key): 특정 사람 계정에 묶입니다. 그 사람이 팀에서 가진 권한을 그대로 상속받고, 1인당 1개만 만들 수 있습니다.

자동화라면 당연히 팀 키입니다.

역할을 올려도 안 되는 것

여기서 한참 헤맸습니다. 처음 쓰던 키가 "앱 관리(App Manager)" 역할이었는데, 새 앱을 만들려고 POST /v1/apps를 호출하니 이런 에러가 났습니다.

{
  "code": "FORBIDDEN_ERROR",
  "detail": "The resource 'apps' does not allow 'CREATE'. Allowed operations are: GET_COLLECTION, GET_INSTANCE, UPDATE"
}

권한이 부족한가 싶어서 "관리자(Admin)" 역할로 새 키를 만들어 다시 시도했습니다. 똑같은 에러였습니다. 혹시나 해서 세 번째 키까지 만들어봤는데 결과는 같았습니다.

세 번 다 같은 응답이 나오고 나서야 이게 권한 문제가 아니라는 걸 알았습니다. App Store Connect의 공개 API는 앱 생성을 아예 지원하지 않습니다. 역할을 아무리 올려도 apps 리소스의 CREATE는 원천적으로 막혀 있고, 허용되는 건 조회(GET_COLLECTION, GET_INSTANCE)와 수정(UPDATE)뿐입니다. Fastlane의 produce나 다른 CI 도구들이 앱 생성을 자동화할 때 공개 API 대신 Apple ID 로그인 세션(2단계 인증 포함)을 흉내 내는 비공식 방식을 쓰는 이유가 이거였습니다.

반대로 Bundle ID(App ID) 등록은 공개 API로 됩니다. POST /v1/bundleIds는 정상적으로 201을 반환합니다. 그래서 "번들 ID는 미리 등록해두고, 실제 앱 레코드 생성만 웹 화면에서 하는" 순서로 정리했습니다.

// 되는 것
POST /v1/bundleIds   // 201

// 안 되는 것 (역할 무관)
POST /v1/apps        // 403 FORBIDDEN_ERROR

이름 필드에서 한 번 더 걸렸습니다

Bundle ID를 등록할 때 name에 한글을 넣었더니 409 ENTITY_ERROR.ATTRIBUTE.INVALID가 났습니다. 이 필드는 Apple 내부에서 쓰는 식별용 라벨이라 영문/숫자만 허용하고, 스토어에 노출되는 실제 앱 이름과는 다른 값입니다. 앱 레코드 자체의 name(App Store에 노출되는 이름)은 한글이 됩니다. 같은 "이름"이라는 단어를 쓰는 필드 두 개가 서로 다른 규칙을 가진 셈이라 처음엔 헷갈렸습니다.

앱 단위 접근 범위도 따로 있었습니다

앱을 웹 화면에서 만들 때 "사용자 액세스 권한"을 묻는 단계가 있습니다. 제한된 액세스를 고르면 그 자리에서 지정한 사람·역할만 이 앱을 볼 수 있고, 이미 "전체 앱" 범위로 설정된 키라도 이 목록에 없으면 안 보입니다. 전체 액세스를 고르면 "전체 앱" 범위를 가진 역할·키가 자동으로 이 앱에 접근하게 됩니다.

키 쪽의 "앱 관리" 역할 + "전체 앱" 범위 설정과, 앱 쪽의 "전체 액세스" 설정이 둘 다 맞아야 자동화 키가 새로 만든 앱을 조회할 수 있습니다. 하나라도 어긋나면 목록 조회에서 그 앱만 조용히 빠집니다. 에러가 나는 게 아니라 그냥 안 보이니, 처음엔 "아직 전파가 안 됐나" 하고 몇 번 더 조회해봤습니다.

정리

하려는 것 공개 API 필요 조건
앱 목록/상세 조회 가능 팀 키, 최소 조회 권한
Bundle ID 등록 가능 POST /v1/bundleIds
앱 레코드 생성 불가 역할 무관, 웹 UI(또는 비공식 세션 인증)만 가능
새로 만든 앱 조회 조건부 키 범위 "전체 앱" + 앱 자체 "전체 액세스" 둘 다 필요

키를 세 개나 만들어보고서야 확인한 사실이라, 이 글이 같은 삽질을 한 번 줄여주면 좋겠습니다.