EAS Submit
Automating App Store Connect and Play Console uploads - the cookbook for shipping EAS Build artifacts to TestFlight, App Review, and Google Play tracks on Expo SDK 57.
Search across all documentation pages
Automating App Store Connect and Play Console uploads - the cookbook for shipping EAS Build artifacts to TestFlight, App Review, and Google Play tracks on Expo SDK 57.
Quick-reference recipe card - copy-paste ready.
# Build then submit latest artifact
eas build --profile production --platform ios
eas submit --platform ios --latest
eas build --profile production --platform android
eas submit --platform android --latest
# One-shot build + submit
eas build --profile production --platform ios --auto-submit// eas.json
{
"submit": {
"production": {
"ios": {
"appleId": "release@example.com",
"ascAppId": "1234567890",
"appleTeamId": "ABCDE12345"
},
"android": {
"serviceAccountKeyPath": "./secrets/play-service-account.json",
"track": "internal"
}
}
}
}# Non-interactive CI submit
eas submit --platform all --profile production --latest --non-interactiveWhen to reach for this:
Step 1 - Create App Store Connect API key
.p8 once - store in team secrets vault.eas credentials --platform ios
# Configure App Store Connect API key for submitStep 2 - Configure eas.json
{
"submit": {
"production": {
"ios": {
"ascAppId": "1234567890",
"appleTeamId": "ABCDE12345"
}
}
}
}Find ascAppId in App Store Connect → App Information → Apple ID (numeric).
Step 3 - Build and submit
eas build --profile production --platform ios
eas submit --platform ios --profile production --latestOr with auto-submit:
{
"build": {
"production": {
"distribution": "store",
"autoIncrement": true
}
}
}eas build --profile production --platform ios --auto-submitStep 1 - Create service account
./secrets/play-service-account.json (gitignored).Step 2 - Configure eas.json tracks
{
"submit": {
"production": {
"android": {
"serviceAccountKeyPath": "./secrets/play-service-account.json",
"track": "internal",
"releaseStatus": "completed"
}
},
"closed-beta": {
"android": {
"serviceAccountKeyPath": "./secrets/play-service-account.json",
"track": "alpha"
}
}
}
}Step 3 - Build AAB and submit
eas build --profile production --platform android
eas submit --platform android --profile production --latesttrack": "internal" - fastest QA loop - Internal Testing TracksversionCode must exceed all prior uploads - use autoIncrement on build profile# .github/workflows/release.yml (excerpt)
name: Release
on:
push:
tags: ["v*"]
jobs:
submit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 22 }
- run: npm install -g eas-cli
- run: eas submit --platform all --profile production --latest --non-interactive
env:
EXPO_TOKEN: ${{ secrets.EXPO_TOKEN }}# Submit a specific build ID (not just --latest)
eas submit --platform ios --id <build-uuid>EXPO_TOKEN - machine token from expo.dev → Access tokens.p8 and Play JSON as CI secrets - reference paths in eas.json or env overridesSubmit IPAs or AABs built outside EAS:
eas submit --platform ios --path ./dist/ShopApp.ipa
eas submit --platform android --path ./dist/ShopApp.aab --profile productionUse when:
| Error | Platform | Fix |
|---|---|---|
| "Invalid Provisioning Profile" | iOS | Rebuild with valid distribution profile - iOS Credentials |
| "Redundant Binary Upload" | iOS | Increment buildNumber - enable autoIncrement |
| "Version code has already been used" | Android | Bump versionCode in app.config.ts or remote version |
| "APK/AAB not signed with upload key" | Android | Align EAS keystore with Play upload certificate |
| "Service account lacks permission" | Android | Re-invite SA in Play Console with release rights |
Stack versions: This page was written for React 19.2.3, React Native 0.86.0, and Expo SDK 57 (
expo~57.0.4).
Reviewed by Chris St. John·Last updated Jul 16, 2026