Configure Codemagic to upload signed iOS builds straight to TestFlight, so every qualifying commit reaches your testers without manual Xcode exports.
TestFlight is Apple's beta distribution service, letting you deliver pre-release builds to internal and external testers before an App Store launch. Doing this manually means archiving in Xcode, exporting an .ipa, and uploading through the Organizer or Transporter every single time — a repetitive chore that is easy to get wrong under deadline pressure. Automating it with Codemagic means a qualifying commit or tag triggers a build that compiles, signs, and uploads the resulting binary directly to TestFlight, appearing in App Store Connect ready for testing. This shortens the feedback loop dramatically: testers get new builds within minutes of a merge, without a developer manually shepherding each one. It also reduces human error, since the export options and signing are defined once in configuration rather than clicked through by hand each release. To make this work you need three things already in place: a working signed build, an App Store Connect API key with sufficient permissions, and an app record already created in App Store Connect with a matching bundle identifier. With those established, publishing becomes one more automated step in your pipeline. The payoff compounds over a project's life: a team that ships betas daily saves hours of manual export toil every week and removes a whole class of last-minute release-day mistakes.
Automatic TestFlight publishing sits on top of successful code signing, so make sure your build already produces a valid, distribution-signed .ipa before you add the upload step. If signing is not yet working, solve that first; an unsigned or improperly signed binary will be rejected on upload. You also need an app record in App Store Connect. Codemagic uploads a build against an existing app identified by its bundle identifier, so log in to App Store Connect, create the app under My Apps if it does not exist, and register its bundle identifier, name, primary language, and SKU. The bundle identifier on that record must exactly match the identifier your build signs with. Finally, your App Store Connect API key needs permission to manage builds — App Manager access is commonly sufficient. Reusing the same API key you configured for signing is the simplest path, since it already has the necessary trust established. With signing green, an app record present, and a capable key stored in Codemagic, you are ready to wire up the publishing step itself. Note that creating the App ID identifier in the Apple Developer portal and creating the app record in App Store Connect are two separate actions; you need both, and both must reference the same bundle identifier.
In codemagic.yaml, publishing to TestFlight is configured in the publishing section of your workflow. You reference the App Store Connect integration — the stored API key — and enable submission to TestFlight. The key settings control where the build goes: enabling TestFlight submission delivers the build to internal testers automatically, and you can optionally assign it to specific beta tester groups so external testers receive it too, subject to Apple's external testing review. Codemagic uses its CLI tools under the hood to perform the upload via the App Store Connect API. Because the publishing step runs only after a successful build and sign, a failure earlier in the pipeline prevents a broken binary from ever reaching your testers. Keep the API key referenced by its secure variable name rather than inlined. If you configure everything through the UI instead of YAML, the equivalent settings live in the workflow's publishing or distribution section, where you toggle App Store Connect publishing and choose TestFlight as the destination. Either way, the configuration lives in one place and applies consistently on every triggered build. You can also gate publishing so it only runs for release branches or tags, which prevents every feature-branch build from pushing noise into your testers' TestFlight app.
For a build to be accepted by TestFlight, it must be exported for App Store distribution, not development or ad hoc. This means your signing configuration must use the app_store distribution type so the exported .ipa carries a distribution provisioning profile and the correct export options. If you export with the wrong method, the upload will fail or the binary will be rejected as invalid. In practice, when you set the iOS signing distribution type to app_store in your Codemagic workflow, the export options are handled to match. Double-check that the build configuration is a release configuration rather than debug, because App Store distribution expects an optimized release build. Also confirm the build number and version. TestFlight requires each uploaded build to have a unique build number for a given version string; uploading a build number that already exists for that version will be rejected. Many teams automate the build number, for example by deriving it from the CI build index or a timestamp, so every upload is unique without manual bumping. Getting the export type and build number right prevents the most common upload rejections. Remember too that even correctly exported builds must clear App Store Connect's own server-side processing, which validates the binary after the transfer completes and can surface issues the export step did not catch.
Version and build number management is where automated TestFlight pipelines most often trip up. Apple identifies a build by its marketing version, the CFBundleShortVersionString like 1.4.0, combined with its build number, the CFBundleVersion. Within a single marketing version, every build number must be unique; you cannot upload build 12 twice under version 1.4.0. On CI this is a problem if your Xcode project has a static build number, because every automated upload would collide. The common solution is to set the build number automatically during the build using an environment value Codemagic exposes, such as a monotonically increasing build index, or by querying the latest TestFlight build number and incrementing it. Codemagic's CLI tools can fetch the latest build number from App Store Connect so you can bump from it reliably. Add a script step early in the workflow that writes the computed build number into your Info.plist or via agvtool before archiving. This guarantees each upload is unique and monotonic, which keeps TestFlight happy and makes it easy for testers to tell builds apart chronologically. Keep the marketing version under deliberate human control, bumping it when you ship meaningful changes, while letting the build number increment automatically — that division of responsibility avoids both collisions and confusing version jumps.
With everything configured, trigger a build on the branch or tag you use for beta releases. Codemagic compiles, signs, and then runs the publishing step, uploading the .ipa to App Store Connect via the API. Watch the log to confirm the upload succeeds and note any messages about processing. After upload, App Store Connect processes the binary — this takes a few minutes to sometimes longer — before the build becomes available in TestFlight. Log in to App Store Connect, open your app, and check the TestFlight tab; the new build should appear, initially in a processing state, then ready for internal testers. Internal testers with access can install almost immediately. External tester groups require Apple's beta app review the first time and for significant changes, which adds a delay outside Codemagic's control. If you supplied export compliance information and test details in your configuration or the App Store Connect record, Codemagic can help streamline the flow, but some metadata like encryption compliance and beta review notes may still need to be present. Verify testers actually receive the build to confirm the full pipeline works end to end. Adding the ITSAppUsesNonExemptEncryption key to your Info.plist ahead of time is a common way to stop processing from stalling on the export compliance question for every build.
If the upload step fails, read the specific error before retrying, since each attempt consumes build minutes. Common causes include an API key lacking permission to manage builds, a bundle identifier that does not match any app record in App Store Connect, a duplicate build number for the existing version, or a binary exported with the wrong distribution method. Authentication errors point to the API key — verify the Key ID, Issuer ID, and .p8 are correct and the key has App Manager access. A missing app record error means you must create the app in App Store Connect first. Invalid binary errors often trace back to the export options, an unsupported architecture, or missing required metadata like an app icon or the encryption compliance declaration. Processing failures that appear only after upload usually come from App Store Connect's own validation and are reported by email to your account. Resolve the root cause in your configuration or App Store Connect setup, then re-run. Because publishing runs last, a clean fix to the upload step rarely requires touching the earlier build or signing configuration. If uploads intermittently fail with network or timeout errors rather than validation errors, that is usually a transient App Store Connect issue and a straight re-run resolves it without any configuration change.
Yes. Codemagic uploads a build against an existing app record identified by its bundle identifier. Create the app under My Apps in App Store Connect, matching the bundle identifier your build signs with, before configuring automatic publishing.
Within a single marketing version, every build number must be unique. Uploading a build number already used for that version fails. Automate the build number on CI — for example from the build index or by incrementing the latest TestFlight build — so each upload is unique.
App Store distribution (app_store). TestFlight requires a build signed with a distribution profile and exported for the App Store, not development or ad hoc. Set the signing distribution type to app_store so the export options match.
After upload, App Store Connect processes the binary for a few minutes before it appears in TestFlight. Internal testers can then install almost immediately. External tester groups require Apple's beta app review the first time, which adds a delay outside Codemagic's control.
Yes, and it is the simplest approach. An App Store Connect API key with App Manager access can handle both automatic signing and TestFlight upload, so you configure trust once and reuse it across the pipeline.