Share a Codemagic build with testers: install links, not downloads
· 7 min read
Codemagic is good at the hard part: it builds and signs Flutter, React Native and native apps on its own Macs, even if you do not own one. The part after the build is where many teams get stuck. A client or a QA person needs the new build on a phone today, and what they get is a file link in an email. This guide covers what Codemagic offers for sharing builds, where those features stop, and how to give testers an install page with one script. Every Codemagic fact below is as listed on docs.codemagic.io and codemagic.io on November 5, 2026. Check those pages again before you rely on a detail.
How Codemagic shares builds today
Codemagic has four ways to get a build to people:
- Email and Slack notices. After a build, Codemagic can email the team or post to Slack with "download links for the build artifacts". The email notification docs say "the links are valid for 24 hours". Since October 2026, external email recipients must verify their address first.
- Build dashboards. A public link that lists the team's builds, release notes and artifacts. The build dashboard docs say the download links "are valid for 24 hours" and are recreated on each refresh, and that "anyone with the public link" can download the artifacts.
- Tester groups. Confirmed testers "receive an email with the app artifacts after every successful build". By default the number of testers "is limited to 20 across all applications in the team" (tester groups docs).
- Public artifact links from the UI. You pick 24 hours, 3 days, 1 week or no expiration. A link with no expiration still stops working when the artifact is removed by retention.
Build dashboards and tester groups are team features, and Codemagic's docs say free minutes are not available to teams. So the moment a client must see builds inside Codemagic, you are on a paid team.
Where the Codemagic link stops
For a developer who installs their own build, a 24 hour link is fine. For testers outside the build team, three things get in the way:
- The link ages out. A tester who opens Tuesday's email on Thursday gets an expired link. Our guide to expired Codemagic artifact links covers this in detail.
- The file goes away. Artifacts are kept 30 days on the free plan, 60 days on pay as you go and one year on fixed annual plans.
- An .ipa is not an install. An iPhone cannot install an .ipa file from a download. It needs an install page with an Install button that points at a manifest. We did not find such a page in Codemagic's docs. Codemagic's App Preview runs a simulator build in the browser, which is useful for a demo but is not the app on the tester's phone.
Option 1: a publishing script that uploads to AppForShare
AppForShare is a build sharing service: you upload the .ipa, .apk or .aab and testers get an install page with an Install button, a QR code and install help in 13 languages. It does not build apps, so Codemagic keeps doing that. You add one publishing script.
First, make an upload token in AppForShare under Dashboard, Settings (upload tokens are part of Pro and Team). In Codemagic, add it as a Secure environment variable named APPFORSHARE_TOKEN in a group, for example appforshare.
One detail matters here. Codemagic's post-publish docs say "Post-publish scripts will be executed even if a build fails." A plain upload script then runs after a failed build too, and either fails on a missing file or sends an older file an earlier step left behind. Codemagic documents the fix: write ~/SUCCESS as the last build script and check for it in the publishing script.
workflows:
android-beta:
name: Android beta
environment:
groups: [appforshare]
flutter: stable
scripts:
- name: Build apk
script: flutter build apk --release
- name: Mark success
script: touch ~/SUCCESS
artifacts:
- build/app/outputs/flutter-apk/app-release.apk
publishing:
scripts:
- name: Share with testers
script: |
if [ -f ~/SUCCESS ]; then
npx --yes appforshare upload build/app/outputs/flutter-apk/app-release.apk \
--notes "$(git log -1 --pretty=%B)" --channel beta
fi
Codemagic has no commit message variable, so the script reads it with git log. With CLI 1.20.0 or later the script can be one line: npx --yes appforshare@latest upload --if-success --channel beta. On Codemagic the CLI then picks the newest build file from the output folders, writes the release notes from the last commit with the branch and short commit, and skips the upload when ~/SUCCESS is missing.
For iPhones, sign the build ad hoc in Codemagic. The exact ios_signing block and the export options file are in Codemagic iOS ad hoc builds for Flutter.
Option 2: Connect Codemagic, nothing in the workflow
If you use the Workflow Editor, or you would rather not touch codemagic.yaml, Connect Codemagic (Pro and Team) imports finished builds for you. An Owner or Admin pastes a Codemagic API token once and maps a Codemagic app and workflow to an AppForShare project and channel. Codemagic documents no outgoing build webhooks, so AppForShare checks every 5 minutes. It only reads from Codemagic: it never starts, cancels or changes a build. The token is stored encrypted and never shown again, and it acts with your Codemagic role, so use an account whose access you are comfortable sharing.
What testers get instead
| Codemagic link | AppForShare link | |
|---|---|---|
| What opens | A file download | An install page with an Install button, QR code and install help |
| How long it works | 24 hours in emails, Slack and dashboards | 7 days on Free, while you subscribe on Pro and Team |
| Newest build | Build dashboard, links remade on refresh | One channel link that always opens the newest build, with rollback (Pro and Team) |
| Tester accounts | None for a public link | None; private projects for invited testers on Team |
| Tester limit | 20 across the team by default | No tester cap; tester groups and install status on Team |
| Feedback | Not found in its docs | Screenshots and notes from the install page, no SDK |
Every build uploaded to an account also gets a store readiness check against current App Store and Google Play rules. It is guidance, not a promise of approval.
Getting new iPhones into the next build
Codemagic can email a device registration link that adds a tester's iPhone to your Apple account. That is a team feature. On AppForShare Pro, an onboarding link per iOS project does the same job without a Codemagic team: the tester installs a profile, the device lands in your devices, and an Admin registers it on Apple in one click with your App Store Connect API key. Then run the Codemagic workflow again: xcode-project use-profiles fetches an ad hoc profile for the bundle id, and the new build includes the device. When that build is uploaded, the tester gets one email with the install link.
Common questions
Do I need a paid Codemagic team for this?
No. A personal Codemagic account with its free macOS minutes can build, and the publishing script uploads with an AppForShare token.
Does AppForShare replace Codemagic?
No. Codemagic builds, signs and can publish to the stores. AppForShare is the tester and store release layer after the build. The AppForShare vs Codemagic comparison lists where each one is ahead.
Can I still use Codemagic tester groups?
Yes. Both can run side by side. Many teams keep Codemagic notices for developers and send AppForShare links to clients and QA.
What about the .aab?
Upload it. AppForShare turns it into one APK testers install, and on Pro and Team keeps the .aab so an Admin can send it to a Google Play testing track.
The full setup, including the Workflow Editor and store steps, is in Use AppForShare with Codemagic. If you want to try it on your next build, create a free account and upload one file by hand first.


