A lightweight PHP REST gateway for Apple App Store Connect API.
- API style: REST only
- Auth mode: Authorization Bearer only for protected routes
- Token: create JWT for App Store Connect
- Apps: list, details, app store versions
- Devices: list, create, details, update, delete
- Bundle IDs: list, create, details, update, delete
- Certificates: list, details, delete
- Profiles: list, create, details, delete
- TestFlight: beta groups, beta testers, builds
- App Store Version Localizations: list, create, details, update
app/
Controllers/
Http/
Services/
Support/
v1/
index.php
routes.php
openapi.yaml
- PHP 8.1+
- PHP extensions: curl, openssl, json
- Composer (recommended, for tests)
Apple API client supports split timeouts and idempotent retries.
ASC_HTTP_CONNECT_TIMEOUT: connect timeout in secondsASC_HTTP_READ_TIMEOUT: read timeout in secondsASC_HTTP_MAX_RETRIES: max retry count for idempotent methods only (GET/HEAD/PUT/DELETE/OPTIONS)ASC_HTTP_RETRY_DELAY_MS: base delay in milliseconds for exponential backoffASC_HTTP_RETRYABLE_CODES: comma-separated retryable HTTP status codes
Compatibility fallback:
- If split timeout variables are not set,
ASC_HTTP_TIMEOUTis still used as fallback. - Non-idempotent methods (
POST,PATCH) are not retried.
- Copy env template:
cp .env.example .env- Put your key file in AuthKey:
AuthKey/AuthKey_<kid>.p8
- Start local server:
php -S 127.0.0.1:8080 v1/index.php- Create JWT token:
curl -X POST http://127.0.0.1:8080/v1/token \
-H 'Content-Type: application/json' \
-d '{"iss":"<issuer-id>","kid":"<key-id>"}'- Call protected endpoint:
curl http://127.0.0.1:8080/v1/apps \
-H 'Authorization: Bearer <jwt-token>'- GET /v1/health
- POST /v1/token
- GET /v1/apps
- GET /v1/apps/{id}
- GET /v1/apps/{id}/appStoreVersions
- GET /v1/devices
- POST /v1/devices
- GET /v1/devices/{id}
- PATCH /v1/devices/{id}
- DELETE /v1/devices/{id}
- GET /v1/bundleIds
- POST /v1/bundleIds
- GET /v1/bundleIds/{id}
- PATCH /v1/bundleIds/{id}
- DELETE /v1/bundleIds/{id}
- GET /v1/certificates
- GET /v1/certificates/{id}
- DELETE /v1/certificates/{id}
- GET /v1/profiles
- POST /v1/profiles
- GET /v1/profiles/{id}
- DELETE /v1/profiles/{id}
- GET /v1/betaGroups
- GET /v1/betaTesters
- GET /v1/builds
- GET /v1/appStoreVersions/{id}/appStoreVersionLocalizations
- POST /v1/appStoreVersionLocalizations
- GET /v1/appStoreVersionLocalizations/{id}
- PATCH /v1/appStoreVersionLocalizations/{id}
Success:
{
"success": true,
"request_id": "84744b77baefc0c3",
"data": {}
}Error:
{
"success": false,
"request_id": "c2d188ac8ef6f499",
"error": {
"code": "unauthorized",
"message": "Authorization header with Bearer token is required.",
"details": null
}
}- Specification file: openapi.yaml
composer install
vendor/bin/phpunitIf composer is not available globally, use local composer binary:
php ./composer install
php ./vendor/bin/phpunit| Legacy endpoint | New endpoint |
|---|---|
| GET /v1/GetToken | POST /v1/token |
| GET /v1/ListApps | GET /v1/apps |
| GET /v1/ListBundleIDs | GET /v1/bundleIds |
| GET /v1/ListCertifications | GET /v1/certificates |
| GET /v1/ListDevices | GET /v1/devices |
| GET /v1/RegisterNewDevice | POST /v1/devices |
| GET /v1/RegisterNewBundleID | POST /v1/bundleIds |
Auth migration:
- Legacy: query token parameter
- New: Authorization header with Bearer token