Guide

Magic Deploy Setup

Where to find the Key ID, Issuer ID, Team ID, and .p8 file LingCode needs to upload your iOS or Mac app to the App Store. Platform is auto-detected — no picker to configure.

What you're filling in

When you click Magic Deploy in LingCode and choose App Store Connect (API key), you'll see four fields. Each comes from a different page on Apple's developer portals — this guide walks through them in the order LingCode shows them.

FieldWhat it isWhere to get it
Key ID10-character ID for your API key, e.g. ABC123XYZ0.App Store Connect → Users and Access → Integrations → Keys
Issuer IDUUID for your team's API integration.Same Keys page (shown above the table)
Team ID10-character Apple Developer team ID, e.g. HPTTZS5J27.Apple Developer → Membership Details
.p8 filePrivate key Apple generates once when you create the API key.Downloaded the moment you create the key — saved as AuthKey_<KeyID>.p8

Two in-app shortcuts make this easier. Magic Deploy runs a preflight before any xcodebuild call, checking that Xcode (not just Command Line Tools) is selected and that your keychain holds an Apple Distribution certificate matching the Team ID — catching ~70% of first-deploy failures in about a second. And the Auto-bump build number checkbox next to the fields runs agvtool next-version -all before each archive, eliminating the second-most-common failure ("Redundant Binary Upload"). The auto-bump toggle is off by default — tick it the first time you deploy.

Why are there so many pieces? Apple's deploy flow is long because it chains together a trust chain: your Apple ID proves you, your Team ID proves which organization you ship under, your Apple Distribution certificate proves your team holds the private key, the provisioning profile proves the app is allowed to use that cert with those entitlements, and the signed .xcarchive carries that chain all the way to the user's device, which verifies it on every launch. Each field LingCode asks you for plugs into one link of that chain — removing any link breaks the whole thing. Terms unfamiliar? See the glossary.

Before you start — one-time Apple setup

The four fields in Magic Deploy are the final piece. Several things have to already be true on the Apple side, or the upload will fail in ways the UI can't always explain clearly. Walk this checklist once, then you're done for the life of the project.

1. A paid Apple Developer Program membership

A free Apple ID can build and run on your own Mac but cannot upload to App Store Connect. Enroll at developer.apple.com/programs/enroll. It's $99/year for an individual; organizations need a D-U-N-S number and typically take 3–10 business days to be verified. Until your account status shows as Active on developer.apple.com/account, none of the steps below will work.

2. Xcode installed, not just Command Line Tools

LingCode Magic Deploy shells out to xcodebuild, which lives inside the full Xcode app — the standalone Command Line Tools bundle is not enough. Install Xcode from the Mac App Store or developer.apple.com/download, open it once to accept the license, then confirm in Terminal:

xcode-select -p
# should print: /Applications/Xcode.app/Contents/Developer

If it prints /Library/Developer/CommandLineTools instead, point it at Xcode:

sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
sudo xcodebuild -license accept

3. Signed in to Xcode with your developer account

Open Xcode → Settings → Accounts. Click +, pick Apple ID, and sign in with the account that owns your developer membership. The team you want to ship under should appear under your Apple ID row; click it and confirm the Team ID matches the one you'll paste into LingCode.

4. A distribution certificate in your login keychain

xcodebuild signs the archive with a "Apple Distribution" (or legacy "Mac App Distribution") certificate. The easiest way to get one is to let Xcode generate it the first time you archive — but you can also create it yourself:

Sanity-check in Terminal:

security find-identity -v -p codesigning | grep -i distribution

You should see a line like 1) 1A2B... "Apple Distribution: Your Name (HPTTZS5J27)". The 10-character code in parentheses is your Team ID — it must match the Team ID field in LingCode.

Certificates are machine-local. If you regenerate a Mac or switch computers, you'll need to either export/import the private key from the old machine's Keychain Access, or create a new certificate and ship from the new machine. Magic Deploy cannot upload from a machine that has no matching private key.

5. An app record in App Store Connect

Apple will not accept uploads for a bundle identifier that doesn't exist yet. Create the record first:

  1. Sign in at appstoreconnect.apple.com.
  2. My Apps → +New App.
  3. Platforms: tick iOS, macOS, or both — whichever matches the Xcode target you're shipping. Magic Deploy auto-detects from the scheme and picks the right altool --type.
  4. Bundle ID: pick the identifier that matches your Xcode project's Bundle Identifier exactly (shown in the target's General tab). If it's not in the dropdown, register it first at developer.apple.com/account/resources/identifiers as a Mac App identifier (not iOS).
  5. SKU: any internal string you'll never reuse. Can't be changed after creation. com-example-myapp is a safe default.
  6. User access: leave as Full Access unless you have a reason to restrict.

The record can be completely unfilled — no screenshots, no description, no pricing — and you still can't submit for review, but you can upload builds to it. That's what Magic Deploy does.

Your Xcode project must have these settings

The Apple side can be perfect and the upload will still fail if the .xcodeproj isn't configured for Mac App Store distribution. Open the target's Signing & Capabilities tab and verify each of these:

Signing & Capabilities

Version and build numbers

In the target's General tab, under Identity:

Scheme

LingCode picks the first scheme that xcodebuild -list returns. If your project has multiple schemes (app + tests + a helper target, for example), make sure the one that builds the distributable app comes first — reorder in Xcode → Product → Scheme → Manage Schemes.

Also ensure the scheme is marked Shared in that same dialog. Non-shared schemes live in your personal xcuserdata/ and may not be visible to xcodebuild.

Step 1 — Create an App Store Connect API key

This single step gets you three of the four fields: the Key ID, the Issuer ID, and the .p8 file.

  1. Sign in at appstoreconnect.apple.com with the Apple ID that owns your developer account.
  2. In the top nav, click Users and Access.
  3. Switch to the Integrations tab, then select App Store Connect API in the sidebar (sometimes labelled just Keys).
  4. Click the + button to generate a new key. Give it a name like "LingCode Magic Deploy" and pick the access level — App Manager is enough to upload builds; use Admin if you also want LingCode to manage app metadata later.
  5. Click Generate. Apple shows a one-time Download API Key link.

The .p8 file can only be downloaded once. Apple will not let you re-download it. If you lose it, you have to revoke the key and create a new one. Save it somewhere you back up — Documents, iCloud Drive, or a password manager that supports file attachments.

After downloading, the file will be named something like AuthKey_ABC123XYZ0.p8. The 10 characters between AuthKey_ and .p8 are your Key ID. The same Key ID appears in the table on the Keys page; the long UUID at the top of that page (above the table, next to Issuer ID) is your Issuer ID.

Copy these into LingCode

Step 2 — Get your Team ID

The Team ID lives on a different site — the Apple Developer portal, not App Store Connect.

  1. Sign in at developer.apple.com/account with the same Apple ID.
  2. In the sidebar, click Membership Details (older accounts may show it as just Membership).
  3. Copy the 10-character Team ID.

If you belong to multiple teams (personal + organization, for example), make sure the team you pick is the one that owns the App Store Connect record for the app you're shipping. The Team ID and the API key must match the same team.

Step 3 — Click Deploy

With all four fields filled and the .p8 selected, the Deploy to App Store button activates. Before we walk through what LingCode actually runs, here's what the manual version of this would look like — it's worth seeing so the automation makes sense.

The typical archive & upload flow (by hand)

If you were shipping this without Magic Deploy, you'd do roughly this sequence in Xcode and App Store Connect:

  1. Create the app record. In App Store Connect → My Apps+, create a new app with the same bundle ID as your Xcode project. You can't upload a build to an app that doesn't exist yet.
  2. Pick the release scheme. In Xcode's scheme dropdown, choose the scheme that builds the distributable target (usually just your app's scheme, in Release configuration — check Product → Scheme → Edit Scheme → Archive).
  3. Archive. Product → Archive. Xcode builds the release configuration, code-signs with your team's certificate (automatic signing fetches or creates a Distribution profile on the fly), and produces an .xcarchive bundle in ~/Library/Developer/Xcode/Archives/.
  4. Open the Organizer. Xcode jumps to Window → Organizer → Archives automatically when the archive finishes. Pick the archive you just made.
  5. Validate (optional but recommended). Click Validate App. Xcode talks to App Store Connect to check the archive — missing icons, wrong Info.plist keys, bad entitlements surface here before you spend time uploading.
  6. Distribute App. Click Distribute AppApp Store ConnectUpload. Xcode asks about signing (pick Automatically manage signing), then uploads the archive to App Store Connect. On a good connection this takes 1–5 minutes depending on bundle size.
  7. Wait for processing. The build lands in App Store Connect in Processing state. Apple's build servers do their own validation, symbolicate crash info, and extract metadata. This takes anywhere from 2 minutes to 30 minutes, outside your control.
  8. Submit for review or distribute to TestFlight. Once processing finishes, the build is attachable to a new app version (for App Store review) or to a TestFlight group (for internal/external testers).

The tedious parts are steps 3–6: clicking through Xcode, answering the same signing questions every time, and waiting for the Organizer UI to respond. Magic Deploy replaces all of it.

What LingCode Magic Deploy runs instead

Under the hood, the Deploy to App Store button shells out to the same command-line tools Xcode uses. You can see this in your project's build/ directory while it runs. In order:

  1. Find the project and scheme. LingCode looks in the open project folder for a .xcodeproj, then runs xcodebuild -list -project <project> -json to enumerate schemes and picks the first one. There is no scheme override in the UI — if your project has multiple schemes and the first isn't the right one, reorder them in Manage Schemes in Xcode, or for now archive by hand.
  2. Archive.
    xcodebuild archive \
      -scheme <scheme> \
      -configuration Release \
      -archivePath build/<scheme>.xcarchive \
      -destination "generic/platform=macOS"
    The destination (generic/platform=macOS or generic/platform=iOS) and the --type flag on altool are chosen automatically from the scheme's SUPPORTED_PLATFORMS. You'll see [App Store] Detected platform: iOS or macOS in the progress log, so you can confirm before it builds.
  3. Generate ExportOptions.plist. LingCode writes a three-key plist to build/ExportOptions.plist:
    <key>method</key>        <string>app-store</string>
    <key>teamID</key>        <string><your Team ID></string>
    <key>signingStyle</key>  <string>automatic</string>
    That's why the Team ID field matters — it ends up here, and it must match the team that owns the signing certificate installed in your keychain.
  4. Export.
    xcodebuild -exportArchive \
      -archivePath build/<scheme>.xcarchive \
      -exportPath build/AppStoreExport \
      -exportOptionsPlist build/ExportOptions.plist
    This produces build/AppStoreExport/<scheme>.app, a fully signed and packaged app bundle ready for upload.
  5. Upload.
    API_PRIVATE_KEYS_DIR=<dir with .p8> xcrun altool \
      --upload-app \
      -f build/AppStoreExport/<scheme>.app \
      --type macos \
      --apiKey <Key ID> \
      --apiIssuer <Issuer ID>
    This is the same altool that Xcode's Distribute App → Upload uses internally. The .p8 you provided is how it signs JWTs to authenticate against App Store Connect.

Every stdout / stderr line from these commands streams into the progress panel in real time, so when something goes wrong (bad certificate, missing entitlement, App Store Connect validation failure) you see the exact error Xcode would have shown you — without having to click through the Organizer to find it.

On success, the build lands in App Store Connect in Processing. After Apple's processing finishes (2–30 minutes, outside LingCode's control), it shows up under TestFlight → Builds and is ready to submit for review or distribute to testers.

Reading the progress log

While Magic Deploy runs, the right-hand panel streams the live output of xcodebuild and xcrun altool. Everything LingCode prefixes with [App Store] is a status marker from LingCode itself; everything else is verbatim output from Apple's tools.

A successful run looks roughly like this, end-to-end:

[App Store] Archiving...
Build settings from command line:
    ...
ArchiveSucceeded
[App Store] Writing ExportOptions.plist...
[App Store] Exporting...
ExportArchive: signing
ExportArchive: writing /…/build/AppStoreExport/MyApp.app
[App Store] Uploading...
*** Upload Progress: ...
No errors uploading '…/MyApp.app'.
[App Store] Upload complete. Check App Store Connect for the new build.

Where to look when things break: scroll to the very end of the log. xcodebuild prints warnings all the way through the build — the real error is almost always in the last 20 lines, usually after the line that begins ** ARCHIVE FAILED **, ** EXPORT FAILED **, or *** Error: .... LingCode's short "Archive failed. Check the log above." message is just a pointer; the diagnostic detail is in the raw output.

Per-phase troubleshooting

Group failures by which phase they happen in — the fix path is different in each.

Archive phase (xcodebuild archive)

This is where most first-time errors surface, because it's the first time your project is actually being built for Release with real signing.

Log containsWhyFix
No signing certificate "Apple Distribution" found No distribution cert in your keychain, or the one you have belongs to a different team. Xcode → Settings → Accounts → Manage Certificates → + → Apple Distribution. Then re-run Deploy.
No profiles for 'com.example.app' were found Automatic signing couldn't create or fetch a provisioning profile for this bundle ID, usually because the bundle ID isn't registered at developer.apple.com. Register the bundle ID at developer.apple.com/account/resources/identifiers (as Mac App), then retry.
Provisioning profile doesn't include the current device You have manual signing turned on with a wrong profile. Signing & Capabilities → turn Automatically manage signing back on.
Command PhaseScriptExecution failed with a nonzero exit code A Run Script build phase (CocoaPods, SwiftLint, SwiftGen, etc.) errored out. Open the target's Build Phases tab in Xcode, find the failing script, and read its actual error in the log lines just above.
Swift compile errors (error: …) Your code doesn't compile in Release — commonly due to #if DEBUG branches or conditional imports. In Xcode, switch the scheme's Run configuration to Release and build locally until it compiles.
Missing required architecture x86_64 Your project isn't building a universal binary. Mac App Store accepts Apple Silicon-only, but mixed setups often fail here. Target → Build Settings → Architectures → set to $(ARCHS_STANDARD). Remove any hard-coded arm64-only overrides.
The archive was not created Scheme doesn't have an Archive action enabled, or the Archive build configuration isn't set to Release. Product → Scheme → Edit Scheme → Archive tab → Build Configuration: Release, and make sure the app target is ticked.

Export phase (xcodebuild -exportArchive)

Log containsWhyFix
error: exportArchive: No "Apple Distribution" signing certificate matching team ID The teamID in the generated ExportOptions.plist doesn't match any cert in your keychain. Fix the Team ID field in Magic Deploy. Run security find-identity -v -p codesigning — the 10-char code in parentheses is the one to paste.
error: Provisioning profile "…" doesn't include the entitlement com.apple.security.app-sandbox App Sandbox isn't enabled on the target but Mac App Store requires it. Signing & Capabilities → + Capability → App Sandbox.
error: Provisioning profile "…" doesn't include the hardened runtime Hardened Runtime not enabled for the Release config. Signing & Capabilities → + Capability → Hardened Runtime, or set ENABLE_HARDENED_RUNTIME = YES in Build Settings.
error: No matching profiles found for bundle identifier … Automatic signing can generate the profile for Development but not for Distribution — often because the App Store Connect app record doesn't exist yet. Create the app record in App Store Connect (see Before you start step 5). Re-run Deploy.

Upload phase (xcrun altool --upload-app)

Log containsWhyFix
Unable to find API key with Key ID … altool couldn't find AuthKey_<KeyID>.p8 in the directory you picked. Re-select the .p8 file in Magic Deploy, and make sure its filename is exactly AuthKey_<KeyID>.p8. Renaming it will break altool.
Authentication credentials are missing or invalid (HTTP 401) Key ID, Issuer ID, or the .p8 don't match. Copy the Key ID and Issuer ID directly off the Keys page in App Store Connect — don't retype. Issuer ID is a UUID (with dashes); Key ID is 10 alphanumerics.
Forbidden / ITMS-90166 The API key doesn't have upload permission. In App Store Connect → Users and Access → Integrations, edit the key and set role to App Manager or Admin. Developer is read-only.
ERROR ITMS-90189: "Redundant Binary Upload" You're uploading a build number that's already on Apple's servers for this version. Bump the Build field in Xcode (target → General → Build) and re-archive.
ERROR ITMS-90035: "Invalid Signature" The signed app fails Apple's codesign verification — usually a nested framework signed with a development cert, or a helper tool missing its own signature. Check Signing & Capabilities → Frameworks on the target; make sure every embedded framework says Embed & Sign. For helper tools, add an Embed & Sign Copy Files phase.
ERROR ITMS-90338: "Non-public API usage" A framework (often an analytics SDK) links against a private Apple API. Update the offending SDK, or remove it. Apple lists the specific symbol in the error message.
ERROR ITMS-90713: "Missing Info.plist value" A required key like NSCameraUsageDescription or LSApplicationCategoryType is missing. Add the key to your target's Info.plist. Apple's error message names exactly which key.
The network connection was lost / timed out Flaky upload. Large bundles over slow connections time out the 600-second budget. Retry. If it keeps failing, run the xcrun altool command from the log directly in Terminal — altool will show a richer progress indicator and can sometimes resume.

What happens after a successful upload

When Magic Deploy finishes, the build is in App Store Connect → your app → TestFlight → macOS → Builds, initially in Processing state. Apple's build servers run their own post-upload validation — symbolicating crash info, scanning for private API usage, extracting metadata. This usually takes 5–30 minutes but can stretch to an hour or more at peak times. You'll get an email when processing finishes (or when it fails with an ITMS- error).

Once processing is done, you have two paths:

If the build never shows up at all — not even in Processing — check the email associated with your Apple ID. Apple sends rejection emails (ITMS-90xxx codes) for binaries that failed server-side validation, and those rejected builds don't appear in App Store Connect at all.

Quick reference: where to go when something's wrong

SymptomWhere to fix
Magic Deploy button stays disabledOne of the four fields is empty, or the .p8 file isn't attached. LingCode validates all four before enabling the button.
"No Xcode project found"You opened a folder that doesn't contain a .xcodeproj. Open the folder that does, or the .xcodeproj itself.
"No schemes found"Your schemes aren't marked Shared. Xcode → Product → Scheme → Manage Schemes → tick Shared on the one you want to build.
Archive phase failsOpen Xcode, switch to the Release configuration, and do Product → Archive yourself. Fix whatever Xcode complains about, then retry Magic Deploy.
Export phase fails99% of the time it's the ExportOptions.plist teamID not matching your keychain. Run security find-identity -v -p codesigning and fix the Team ID field in LingCode.
Upload phase fails with HTTP 401/403Problem is the API key. Re-download the .p8, or create a fresh key with App Manager role and try again.
Upload succeeds but build never appearsCheck the email on your Apple ID for an ITMS- rejection. If nothing, wait 30 minutes — Apple's processing queue varies.
"Redundant binary upload"Bump the Build number in Xcode. Any integer greater than the previous one.
Still stuckCopy the exact xcodebuild or xcrun altool command from the log and run it in Terminal — the error messages are identical and easier to Google than "Archive failed. Check the log above.".

Common mistakes (quick checklist)

Security notes

The .p8 private key is the equivalent of a password for your App Store Connect account. Treat it that way: don't commit it to git, don't share it in Slack, and revoke it from the Keys page if a teammate leaves or a laptop is lost. LingCode never uploads the .p8 anywhere — it stays on your Mac and is only handed to Apple's xcrun altool at upload time.

Further reading

Primary sources for the concepts on this page, from Apple and the IETF: